From 4cd57e1e4ee490192203d80809b76a4b20f2e938 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 30 Sep 2015 11:04:29 -0600 Subject: [PATCH] Work queues: Logic that sets the queued indication and the logic that does the actual queuing must be atomic --- ChangeLog | 5 ++++- arch | 2 +- configs | 2 +- libc/wqueue/work_queue.c | 12 ++++++------ sched/wqueue/kwork_cancel.c | 6 ++++-- sched/wqueue/kwork_queue.c | 20 ++++++++++---------- 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index acadd39a2f..3a319bcbe3 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10996,4 +10996,7 @@ board from Lok Tep (2015-09-29). * configs/nucleo-f303re: Add SSD1351 SPI 4-wire interface. From Paul Alexander Patience (2015-09-29). - + * arch/arm/src/armv7-m/up_schedulesigaction.c: Fix logic that determines + if there is a pending signal action before scheduling the next signal + action. Both the test and the scheduling action need to be atomic + (2015-09-30). diff --git a/arch b/arch index 69721cb374..22e48d4266 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 69721cb3742b2cb6f399c966b56da00ae3e9cb05 +Subproject commit 22e48d4266c8c6a8d31aefabe375dcb78173975b diff --git a/configs b/configs index 5a319c2e71..e2bff41896 160000 --- a/configs +++ b/configs @@ -1 +1 @@ -Subproject commit 5a319c2e71ccc64e4cb3ebdc6fecc535f544e260 +Subproject commit e2bff41896393f786062d37bf12b09ec89028921 diff --git a/libc/wqueue/work_queue.c b/libc/wqueue/work_queue.c index ffe98af8c7..ce0bf4024c 100644 --- a/libc/wqueue/work_queue.c +++ b/libc/wqueue/work_queue.c @@ -107,16 +107,16 @@ static int work_qqueue(FAR struct usr_wqueue_s *wqueue, { DEBUGASSERT(work != NULL); - /* First, initialize the work structure */ - - work->worker = worker; /* Work callback */ - work->arg = arg; /* Callback argument */ - work->delay = delay; /* Delay until work performed */ - /* Get exclusive access to the work queue */ while (work_lock() < 0); + /* Initialize the work structure */ + + work->worker = worker; /* Work callback. non-NULL means queued */ + work->arg = arg; /* Callback argument */ + work->delay = delay; /* Delay until work performed */ + /* Now, time-tag that entry and put it in the work queue. */ work->qtime = clock_systimer(); /* Time work queued */ diff --git a/sched/wqueue/kwork_cancel.c b/sched/wqueue/kwork_cancel.c index 8aa133aaab..99a6ac0fd8 100644 --- a/sched/wqueue/kwork_cancel.c +++ b/sched/wqueue/kwork_cancel.c @@ -109,8 +109,10 @@ static int work_qcancel(FAR struct kwork_wqueue_s *wqueue, { /* A little test of the integrity of the work queue */ - DEBUGASSERT(work->dq.flink || (FAR dq_entry_t *)work == wqueue->q.tail); - DEBUGASSERT(work->dq.blink || (FAR dq_entry_t *)work == wqueue->q.head); + DEBUGASSERT(work->dq.flink != NULL || + (FAR dq_entry_t *)work == wqueue->q.tail); + DEBUGASSERT(work->dq.blink != NULL || + (FAR dq_entry_t *)work == wqueue->q.head); /* Remove the entry from the work queue and make sure that it is * mark as available (i.e., the worker field is nullified). diff --git a/sched/wqueue/kwork_queue.c b/sched/wqueue/kwork_queue.c index 842fe656ff..69eca718c1 100644 --- a/sched/wqueue/kwork_queue.c +++ b/sched/wqueue/kwork_queue.c @@ -107,20 +107,20 @@ static void work_qqueue(FAR struct kwork_wqueue_s *wqueue, { irqstate_t flags; - DEBUGASSERT(work != NULL); + DEBUGASSERT(work != NULL && worker != NULL); - /* First, initialize the work structure */ - - work->worker = worker; /* Work callback */ - work->arg = arg; /* Callback argument */ - work->delay = delay; /* Delay until work performed */ - - /* Now, time-tag that entry and put it in the work queue. This must be - * done with interrupts disabled. This permits this function to be called - * from with task logic or interrupt handlers. + /* First, initialize the work structure. This must be done with interrupts + * disabled. This permits this function to be called from with task logic + * or interrupt handlers. */ flags = irqsave(); + work->worker = worker; /* Work callback. non-NULL means queued */ + work->arg = arg; /* Callback argument */ + work->delay = delay; /* Delay until work performed */ + + /* Now, time-tag that entry and put it in the work queue */ + work->qtime = clock_systimer(); /* Time work queued */ dq_addlast((FAR dq_entry_t *)work, &wqueue->q);