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