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