blob: 5360d813b0904ae976bba34a15ece014fb3fcf98 [file] [log] [blame]
Ben Tyner8c2f8b22020-03-27 10:39:31 -05001#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 */
9static constexpr const char* mq_listener = "openpower-hw-diags-mq";
10
11/** @brief maximum length of command line parameter */
12static constexpr int max_command_len = 25;
13
14/** @brief end of command line args message */
15static const char* msg_send_end = "999999999999999";
16
17/** @brief structure for holding main args (for threads) */
18typedef 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 */
29void* 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 */
38void* threadListener(void* i_params)
39{
40 using namespace boost::interprocess;
41
Ben Tyner8c2f8b22020-03-27 10:39:31 -050042 // 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
Ben Tyner8c2f8b22020-03-27 10:39:31 -050051 // create config
Ben Tyner72feadc2020-04-06 12:57:31 -050052 attn::Config attnConfig;
Ben Tyner8c2f8b22020-03-27 10:39:31 -050053
Ben Tyner8c2f8b22020-03-27 10:39:31 -050054 // 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 {
Ben Tynerd3cda742020-05-04 08:00:28 -050059 // vector to hold messages sent to listener
60 std::vector<std::string> messages;
Ben Tyner8c2f8b22020-03-27 10:39:31 -050061 // 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
Ben Tyner72feadc2020-04-06 12:57:31 -0500108 parseConfig(argv.data(), argv.data() + argc, &attnConfig);
Ben Tyner8c2f8b22020-03-27 10:39:31 -0500109
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,
Ben Tyner72feadc2020-04-06 12:57:31 -0500117 &attnConfig))
Ben Tyner8c2f8b22020-03-27 10:39:31 -0500118 {
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 */
145int 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 */
171bool 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}