Skip to content
This repository was archived by the owner on Sep 13, 2024. It is now read-only.

Commit 44707f5

Browse files
committed
Use eventfd to terminate monitor thread
1 parent 4d9c2bb commit 44707f5

File tree

4 files changed

+81
-61
lines changed

4 files changed

+81
-61
lines changed

src/at_response.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3053,7 +3053,7 @@ static void response_taskproc(struct pvt_taskproc_data* ptd)
30533053

30543054
if (at_queue_run(rtd->ptd.pvt)) {
30553055
ast_log(LOG_ERROR, "[%s] Fail to run command from queue\n", PVT_ID(rtd->ptd.pvt));
3056-
rtd->ptd.pvt->terminate_monitor = 1;
3056+
eventfd_signal(rtd->ptd.pvt->monitor_thread_event);
30573057
}
30583058
}
30593059

src/chan_quectel.c

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -658,21 +658,18 @@ int pvt_taskproc_trylock_and_execute(struct pvt* pvt, void (*task_exe)(struct pv
658658
return 0;
659659
}
660660

661+
ao2_ref(pvt, 1);
661662
if (ao2_trylock(pvt)) {
663+
ao2_ref(pvt, -1);
662664
ast_debug(4, "[%s] Task skipping: no lock\n", S_OR(task_name, "UNKNOWN"));
663665
return 0;
664666
}
665667

666-
if (pvt->terminate_monitor) {
667-
ast_debug(5, "[%s][%s] Task skipping: monitor thread terminated\n", PVT_ID(pvt), S_OR(task_name, "UNKNOWN"));
668-
ao2_unlock(pvt);
669-
return 0;
670-
}
671-
672668
ast_debug(5, "[%s][%s] Task executing\n", PVT_ID(pvt), S_OR(task_name, "UNKNOWN"));
673669
task_exe(pvt);
674670
ast_debug(6, "[%s][%s] Task executed\n", PVT_ID(pvt), S_OR(task_name, "UNKNOWN"));
675671
ao2_unlock(pvt);
672+
ao2_ref(pvt, -1);
676673
return 0;
677674
}
678675

@@ -682,16 +679,11 @@ int pvt_taskproc_lock_and_execute(struct pvt_taskproc_data* ptd, void (*task_exe
682679
return 0;
683680
}
684681

685-
SCOPED_AO2LOCK(plock, ptd->pvt);
686-
687-
if (ptd->pvt->terminate_monitor) {
688-
ast_debug(5, "[%s][%s] Task skipping: monitor thread terminated\n", PVT_ID(ptd->pvt), S_OR(task_name, "UNKNOWN"));
689-
return 0;
690-
}
691-
682+
AO2_REF_AND_LOCK(ptd->pvt);
692683
ast_debug(5, "[%s][%s] Task executing\n", PVT_ID(ptd->pvt), S_OR(task_name, "UNKNOWN"));
693684
task_exe(ptd);
694685
ast_debug(6, "[%s][%s] Task executed\n", PVT_ID(ptd->pvt), S_OR(task_name, "UNKNOWN"));
686+
AO2_UNLOCK_AND_UNREF(ptd->pvt);
695687
return 0;
696688
}
697689

@@ -1236,16 +1228,17 @@ static struct pvt* pvt_create(const pvt_config_t* settings)
12361228
AST_LIST_HEAD_INIT_NOLOCK(&pvt->at_queue);
12371229
AST_LIST_HEAD_INIT_NOLOCK(&pvt->chans);
12381230

1239-
pvt->monitor_thread = AST_PTHREADT_NULL;
1240-
pvt->sys_chan.pvt = pvt;
1241-
pvt->sys_chan.state = CALL_STATE_RELEASED;
1242-
pvt->audio_fd = -1;
1243-
pvt->data_fd = -1;
1244-
pvt->gsm_reg_status = -1;
1245-
pvt->has_sms = SCONFIG(settings, msg_direct) ? 0 : 1;
1246-
pvt->incoming_sms_index = -1;
1247-
pvt->incoming_sms_type = RES_UNKNOWN;
1248-
pvt->desired_state = SCONFIG(settings, init_state);
1231+
pvt->monitor_thread = AST_PTHREADT_NULL;
1232+
pvt->monitor_thread_event = -1;
1233+
pvt->sys_chan.pvt = pvt;
1234+
pvt->sys_chan.state = CALL_STATE_RELEASED;
1235+
pvt->audio_fd = -1;
1236+
pvt->data_fd = -1;
1237+
pvt->gsm_reg_status = -1;
1238+
pvt->has_sms = SCONFIG(settings, msg_direct) ? 0 : 1;
1239+
pvt->incoming_sms_index = -1;
1240+
pvt->incoming_sms_type = RES_UNKNOWN;
1241+
pvt->desired_state = SCONFIG(settings, init_state);
12491242

12501243
ast_string_field_init(pvt, 14);
12511244
ast_string_field_set(pvt, provider_name, "NONE");

src/chan_quectel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ typedef struct pvt {
9898

9999
unsigned long channel_instance; /*!< number of channels created on this device */
100100
pthread_t monitor_thread; /*!< monitor (at commands reader) thread handle */
101+
int monitor_thread_event;
101102

102103
int audio_fd; /*!< audio descriptor */
103104
snd_pcm_t* icard;
@@ -166,7 +167,6 @@ typedef struct pvt {
166167
unsigned int prov_last_used :1; /*!< mark the last used device */
167168
unsigned int sim_last_used :1; /*!< mark the last used device */
168169

169-
unsigned int terminate_monitor :1; /*!< non-zero if we want terminate monitor thread i.e. restart, stop, remove */
170170
unsigned int has_subscriber_number:1; /*!< subscriber_number field is valid */
171171
unsigned int must_remove :1; /*!< mean must removed from list: NOT FULLY THREADSAFE */
172172

src/monitor_thread.c

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "at_read.h"
1919
#include "chan_quectel.h"
2020
#include "channel.h"
21+
#include "eventfd.h"
2122
#include "helpers.h"
2223
#include "smsdb.h"
2324
#include "tty.h"
@@ -70,10 +71,6 @@ static void handle_expired_reports(struct pvt* pvt)
7071

7172
static int handle_expired_reports_taskproc(void* tpdata) { return PVT_TASKPROC_TRYLOCK_AND_EXECUTE(tpdata, handle_expired_reports); }
7273

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-
7774
static void cmd_timeout(struct pvt* const pvt)
7875
{
7976
const struct at_queue_cmd* const ecmd = at_queue_head_cmd(pvt);
@@ -83,15 +80,15 @@ static void cmd_timeout(struct pvt* const pvt)
8380

8481
if (at_response(pvt, &pvt->empty_str, RES_TIMEOUT)) {
8582
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);
8784
return;
8885
}
8986

9087
if (ecmd->flags & ATQ_CMD_FLAG_IGNORE) {
9188
return;
9289
}
9390

94-
pvt->terminate_monitor = 1;
91+
eventfd_signal(pvt->monitor_thread_event);
9592
}
9693

9794
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
165162
return 0;
166163
}
167164

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+
168178
static void monitor_threadproc_pvt(struct pvt* const pvt)
169179
{
170180
static const size_t RINGBUFFER_SIZE = 2 * 1024;
@@ -188,8 +198,8 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
188198
}
189199

190200
/* 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);
193203

194204
/* schedule initilization */
195205
if (at_enqueue_initialization(&pvt->sys_chan)) {
@@ -206,8 +216,12 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
206216
}
207217

208218
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]) {
211225
if (ast_taskprocessor_push(tps, at_enqueue_ping_taskproc, pvt)) {
212226
ast_debug(5, "[%s] Unable to handle timeout\n", dev);
213227
}
@@ -218,11 +232,6 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
218232
goto e_cleanup;
219233
}
220234

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-
226235
int t;
227236
int is_cmd_timeout = 1;
228237
if (at_queue_timeout(pvt, &t)) {
@@ -234,32 +243,45 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
234243
if (is_cmd_timeout) {
235244
if (t <= 0) {
236245
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);
240247
}
241248

242249
if (ast_taskprocessor_push(tps, cmd_timeout_taskproc, pvt)) {
243250
ast_debug(5, "[%s] Unable to handle timeout\n", dev);
244251
}
245252

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]) {
248259
continue;
249260
}
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;
253272
}
254-
continue;
255273
}
256274
} 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]) {
259282
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;
263285
}
264286

265287
if (ast_taskprocessor_push(tps, at_enqueue_ping_taskproc, pvt)) {
@@ -271,7 +293,7 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
271293
}
272294

273295
/* FIXME: access to device not locked */
274-
int iovcnt = at_read(dev, fd, &rb);
296+
int iovcnt = at_read(dev, fd[0], &rb);
275297
if (iovcnt < 0) {
276298
break;
277299
}
@@ -310,8 +332,6 @@ static void monitor_threadproc_pvt(struct pvt* const pvt)
310332
// TODO: send monitor event
311333
ast_verb(3, "[%s] Error initializing channel\n", dev);
312334
}
313-
/* it real, unsolicited disconnect */
314-
pvt->terminate_monitor = 0;
315335

316336
e_restart:
317337
pvt_disconnect(pvt);
@@ -329,9 +349,17 @@ static void* monitor_threadproc(void* _pvt)
329349
int pvt_monitor_start(struct pvt* pvt)
330350
{
331351
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;
332359
if (ast_pthread_create_background(&pvt->monitor_thread, NULL, monitor_threadproc, pvt) < 0) {
333360
ao2_ref(pvt, -1);
334361
pvt->monitor_thread = AST_PTHREADT_NULL;
362+
eventfd_close(&pvt->monitor_thread_event);
335363
return 0;
336364
}
337365

@@ -344,15 +372,14 @@ void pvt_monitor_stop(struct pvt* pvt)
344372
return;
345373
}
346374

347-
pvt->terminate_monitor = 1;
348-
pthread_kill(pvt->monitor_thread, SIGURG);
375+
eventfd_signal(pvt->monitor_thread_event);
349376

350377
{
351378
const pthread_t id = pvt->monitor_thread;
352379
SCOPED_LOCK(pvtl, pvt, ao2_unlock, ao2_lock); // scoped UNlock
353380
pthread_join(id, NULL);
354381
}
355382

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);
358385
}

0 commit comments

Comments
 (0)