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