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