1 #include <libpdbg.h> 2 3 #include <attn/attn_main.hpp> 4 #include <boost/interprocess/ipc/message_queue.hpp> 5 #include <cli.hpp> 6 #include <listener.hpp> 7 8 /** @brief openpower-hw-diags message queue name */ 9 static constexpr const char* mq_listener = "openpower-hw-diags-mq"; 10 11 /** @brief maximum length of command line parameter */ 12 static constexpr int max_command_len = 25; 13 14 /** @brief end of command line args message */ 15 static const char* msg_send_end = "999999999999999"; 16 17 /** 18 * @brief Start a thread to monitor the attention GPIO 19 * 20 * @param i_config Attention handler configuration object 21 */ 22 void* threadGpioMon(void* i_config) 23 { 24 // Configure and start attention monitor 25 attn::attnDaemon((attn::Config*)i_config); 26 27 pthread_exit(NULL); 28 } 29 30 /** @brief Start a thread to listen for attention handler messages */ 31 void* threadListener(void* i_params) 32 { 33 using namespace boost::interprocess; 34 35 // remove listener message queue if exists (does not throw) 36 message_queue::remove(mq_listener); 37 38 // thread handle for gpio monitor 39 pthread_t ptidGpio; 40 41 // status of gpio monitor 42 bool gpioMonEnabled = false; 43 44 // create config 45 attn::Config attnConfig; 46 47 // This is the main listener loop. All the above code will be executed 48 // only once. All other communtication with the attention handler will 49 // originate from here via the message queue. 50 do 51 { 52 // vector to hold messages sent to listener 53 std::vector<std::string> messages; 54 // we will catch any exceptions from thread library 55 try 56 { 57 // create new message queue or open existing 58 message_queue mq(open_or_create, mq_listener, 1, max_command_len); 59 60 // message queue parameters 61 char buffer[max_command_len + 1]; 62 size_t recvd_size; 63 unsigned int priority; 64 65 // We will continue receiving messages until we receive 66 // a msg_send_end message to indicate all command line parameters 67 // have been sent. 68 do 69 { 70 // wait for a message to arrive 71 mq.receive((void*)&buffer, max_command_len, recvd_size, 72 priority); 73 74 // null terminate message and store 75 buffer[recvd_size] = '\0'; 76 messages.push_back(buffer); 77 78 } while (buffer != std::string(msg_send_end)); 79 80 messages.pop_back(); // remove msg_send_end message 81 82 // convert messages to command line arguments 83 std::vector<char*> argv; 84 85 std::transform(messages.begin(), messages.end(), 86 std::back_inserter(argv), (char*)data()); 87 88 int argc = argv.size(); 89 argv.push_back(nullptr); 90 91 // stop attention handler daemon? 92 if (true == getCliOption(argv.data(), argv.data() + argc, "--stop")) 93 { 94 message_queue::remove(mq_listener); 95 break; 96 } 97 98 // parse config options 99 parseConfig(argv.data(), argv.data() + argc, &attnConfig); 100 101 // start attention handler daemon? 102 if (true == 103 getCliOption(argv.data(), argv.data() + argc, "--start")) 104 { 105 if (false == gpioMonEnabled) 106 { 107 if (0 == pthread_create(&ptidGpio, NULL, &threadGpioMon, 108 &attnConfig)) 109 { 110 gpioMonEnabled = true; 111 } 112 else 113 { 114 break; 115 } 116 } 117 } 118 } 119 120 catch (interprocess_exception& e) 121 { 122 break; 123 } 124 } while (1); 125 126 // stop the gpio monitor if running 127 if (true == gpioMonEnabled) 128 { 129 pthread_cancel(ptidGpio); 130 } 131 132 pthread_exit(NULL); 133 } 134 135 /** @brief Send command line to a threadi */ 136 int sendCmdLine(int i_argc, char** i_argv) 137 { 138 int count = 0; // number of arguments sent 139 140 using namespace boost::interprocess; 141 142 try 143 { 144 message_queue mq(open_only, mq_listener); 145 146 while (count < i_argc) 147 { 148 mq.send(i_argv[count], strlen(i_argv[count]), 0); 149 count++; 150 } 151 // indicate to listener last cmdline arg was sent 152 mq.send(msg_send_end, strlen(msg_send_end), 0); 153 } 154 catch (interprocess_exception& e) 155 { 156 count = 0; // assume no arguments sent 157 } 158 return count; 159 } 160 161 /** @brief See if the listener thread message queue exists */ 162 bool listenerMqExists() 163 { 164 using namespace boost::interprocess; 165 166 try 167 { 168 message_queue mq(open_only, mq_listener); 169 return true; 170 } 171 catch (interprocess_exception& e) 172 { 173 return false; 174 } 175 } 176