18
18
#include "at_read.h"
19
19
#include "chan_quectel.h"
20
20
#include "channel.h"
21
+ #include "eventfd.h"
21
22
#include "helpers.h"
22
23
#include "smsdb.h"
23
24
#include "tty.h"
@@ -70,10 +71,6 @@ static void handle_expired_reports(struct pvt* pvt)
70
71
71
72
static int handle_expired_reports_taskproc (void * tpdata ) { return PVT_TASKPROC_TRYLOCK_AND_EXECUTE (tpdata , handle_expired_reports ); }
72
73
73
- static void restart_monitor (struct pvt * pvt ) { pvt -> terminate_monitor = 1 ; }
74
-
75
- static int restart_monitor_taskproc (void * tpdata ) { return PVT_TASKPROC_TRYLOCK_AND_EXECUTE (tpdata , restart_monitor ); }
76
-
77
74
static void cmd_timeout (struct pvt * const pvt )
78
75
{
79
76
const struct at_queue_cmd * const ecmd = at_queue_head_cmd (pvt );
@@ -83,15 +80,15 @@ static void cmd_timeout(struct pvt* const pvt)
83
80
84
81
if (at_response (pvt , & pvt -> empty_str , RES_TIMEOUT )) {
85
82
ast_log (LOG_ERROR , "[%s] Fail to handle response\n" , PVT_ID (pvt ));
86
- pvt -> terminate_monitor = 1 ;
83
+ eventfd_signal ( pvt -> monitor_thread_event ) ;
87
84
return ;
88
85
}
89
86
90
87
if (ecmd -> flags & ATQ_CMD_FLAG_IGNORE ) {
91
88
return ;
92
89
}
93
90
94
- pvt -> terminate_monitor = 1 ;
91
+ eventfd_signal ( pvt -> monitor_thread_event ) ;
95
92
}
96
93
97
94
static int cmd_timeout_taskproc (void * tpdata ) { return PVT_TASKPROC_TRYLOCK_AND_EXECUTE (tpdata , cmd_timeout ); }
@@ -165,6 +162,19 @@ static int check_dev_status(struct pvt* const pvt, struct ast_taskprocessor* tps
165
162
return 0 ;
166
163
}
167
164
165
+ static int at_wait_n (int * fds , int n , int * ms )
166
+ {
167
+ int exception ;
168
+
169
+ const int outfd = ast_waitfor_n_fd (fds , n , ms , & exception );
170
+
171
+ if (outfd < 0 ) {
172
+ return 0 ;
173
+ }
174
+
175
+ return outfd ;
176
+ }
177
+
168
178
static void monitor_threadproc_pvt (struct pvt * const pvt )
169
179
{
170
180
static const size_t RINGBUFFER_SIZE = 2 * 1024 ;
@@ -188,8 +198,8 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
188
198
}
189
199
190
200
/* 4 reduce locking time make copy of this readonly fields */
191
- const int fd = pvt -> data_fd ;
192
- at_clean_data (dev , fd , & rb );
201
+ int fd [ 2 ] = { pvt -> data_fd , pvt -> monitor_thread_event } ;
202
+ at_clean_data (dev , fd [ 0 ] , & rb );
193
203
194
204
/* schedule initilization */
195
205
if (at_enqueue_initialization (& pvt -> sys_chan )) {
@@ -206,8 +216,12 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
206
216
}
207
217
208
218
if (ao2_trylock (pvt )) { // pvt unlocked
209
- int t = RESPONSE_READ_TIMEOUT ;
210
- if (!at_wait (fd , & t )) {
219
+ int t = RESPONSE_READ_TIMEOUT ;
220
+ const int w = at_wait_n (fd , 2 , & t );
221
+ if (w == fd [1 ]) {
222
+ eventfd_reset (pvt -> monitor_thread_event );
223
+ goto e_restart ;
224
+ } else if (w != fd [0 ]) {
211
225
if (ast_taskprocessor_push (tps , at_enqueue_ping_taskproc , pvt )) {
212
226
ast_debug (5 , "[%s] Unable to handle timeout\n" , dev );
213
227
}
@@ -218,11 +232,6 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
218
232
goto e_cleanup ;
219
233
}
220
234
221
- if (pvt -> terminate_monitor ) {
222
- ast_log (LOG_NOTICE , "[%s] Stopping by %s request\n" , dev , dev_state2str (pvt -> desired_state ));
223
- goto e_restart ;
224
- }
225
-
226
235
int t ;
227
236
int is_cmd_timeout = 1 ;
228
237
if (at_queue_timeout (pvt , & t )) {
@@ -234,32 +243,45 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
234
243
if (is_cmd_timeout ) {
235
244
if (t <= 0 ) {
236
245
if (check_taskprocessor (tps , dev )) {
237
- if (ast_taskprocessor_push (tps , restart_monitor_taskproc , pvt )) {
238
- ast_debug (5 , "[%s] Unable to restart monitor thread\n" , dev );
239
- }
246
+ eventfd_signal (pvt -> monitor_thread_event );
240
247
}
241
248
242
249
if (ast_taskprocessor_push (tps , cmd_timeout_taskproc , pvt )) {
243
250
ast_debug (5 , "[%s] Unable to handle timeout\n" , dev );
244
251
}
245
252
246
- t = UNHANDLED_COMMAND_TIMEOUT ;
247
- if (!at_wait (fd , & t )) {
253
+ t = UNHANDLED_COMMAND_TIMEOUT ;
254
+ const int w = at_wait_n (fd , 2 , & t );
255
+ if (w == fd [1 ]) {
256
+ eventfd_reset (pvt -> monitor_thread_event );
257
+ goto e_restart ;
258
+ } else if (w != fd [0 ]) {
248
259
continue ;
249
260
}
250
- } else if (!at_wait (fd , & t )) {
251
- if (ast_taskprocessor_push (tps , cmd_timeout_taskproc , pvt )) {
252
- ast_debug (5 , "[%s] Unable to handle timeout\n" , dev );
261
+ } else {
262
+ const int w = at_wait_n (fd , 2 , & t );
263
+ if (w == fd [1 ]) {
264
+ eventfd_reset (pvt -> monitor_thread_event );
265
+ goto e_restart ;
266
+
267
+ } else if (w != fd [0 ]) {
268
+ if (ast_taskprocessor_push (tps , cmd_timeout_taskproc , pvt )) {
269
+ ast_debug (5 , "[%s] Unable to handle timeout\n" , dev );
270
+ }
271
+ continue ;
253
272
}
254
- continue ;
255
273
}
256
274
} else {
257
- t = RESPONSE_READ_TIMEOUT ;
258
- if (!at_wait (fd , & t )) {
275
+ t = RESPONSE_READ_TIMEOUT ;
276
+ const int w = at_wait_n (fd , 2 , & t );
277
+ if (w == fd [1 ]) {
278
+ eventfd_reset (pvt -> monitor_thread_event );
279
+ goto e_restart ;
280
+
281
+ } else if (w != fd [0 ]) {
259
282
if (check_taskprocessor (tps , dev )) {
260
- if (ast_taskprocessor_push (tps , restart_monitor_taskproc , pvt )) {
261
- ast_debug (5 , "[%s] Unable to restart monitor thread\n" , dev );
262
- }
283
+ eventfd_signal (pvt -> monitor_thread_event );
284
+ goto e_restart ;
263
285
}
264
286
265
287
if (ast_taskprocessor_push (tps , at_enqueue_ping_taskproc , pvt )) {
@@ -271,7 +293,7 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
271
293
}
272
294
273
295
/* FIXME: access to device not locked */
274
- int iovcnt = at_read (dev , fd , & rb );
296
+ int iovcnt = at_read (dev , fd [ 0 ] , & rb );
275
297
if (iovcnt < 0 ) {
276
298
break ;
277
299
}
@@ -310,8 +332,6 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
310
332
// TODO: send monitor event
311
333
ast_verb (3 , "[%s] Error initializing channel\n" , dev );
312
334
}
313
- /* it real, unsolicited disconnect */
314
- pvt -> terminate_monitor = 0 ;
315
335
316
336
e_restart :
317
337
pvt_disconnect (pvt );
@@ -329,9 +349,17 @@ static void* monitor_threadproc(void* _pvt)
329
349
int pvt_monitor_start (struct pvt * pvt )
330
350
{
331
351
ao2_ref (pvt , 1 );
352
+
353
+ const int monitor_thread_event = eventfd_create ();
354
+ if (monitor_thread_event <= 0 ) {
355
+ return 0 ;
356
+ }
357
+
358
+ pvt -> monitor_thread_event = monitor_thread_event ;
332
359
if (ast_pthread_create_background (& pvt -> monitor_thread , NULL , monitor_threadproc , pvt ) < 0 ) {
333
360
ao2_ref (pvt , -1 );
334
361
pvt -> monitor_thread = AST_PTHREADT_NULL ;
362
+ eventfd_close (& pvt -> monitor_thread_event );
335
363
return 0 ;
336
364
}
337
365
@@ -344,15 +372,14 @@ void pvt_monitor_stop(struct pvt* pvt)
344
372
return ;
345
373
}
346
374
347
- pvt -> terminate_monitor = 1 ;
348
- pthread_kill (pvt -> monitor_thread , SIGURG );
375
+ eventfd_signal (pvt -> monitor_thread_event );
349
376
350
377
{
351
378
const pthread_t id = pvt -> monitor_thread ;
352
379
SCOPED_LOCK (pvtl , pvt , ao2_unlock , ao2_lock ); // scoped UNlock
353
380
pthread_join (id , NULL );
354
381
}
355
382
356
- pvt -> terminate_monitor = 0 ;
357
- pvt -> monitor_thread = AST_PTHREADT_NULL ;
383
+ pvt -> monitor_thread = AST_PTHREADT_NULL ;
384
+ eventfd_close ( & pvt -> monitor_thread_event ) ;
358
385
}
0 commit comments