Fix a potential race condition
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2234 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
7f84a8bea1
commit
bf7555cc4a
@ -101,6 +101,13 @@ EXTERN pid_t g_worker;
|
|||||||
* Queue work to be performed at a later time. All queued work will be
|
* Queue work to be performed at a later time. All queued work will be
|
||||||
* performed on the worker thread of of execution (not the caller's).
|
* performed on the worker thread of of execution (not the caller's).
|
||||||
*
|
*
|
||||||
|
* The work structure is allocated by caller, but completely managed by
|
||||||
|
* the work queue logic. The caller should never modify the contents of
|
||||||
|
* the work queue structure; the caller should not call work_queue()
|
||||||
|
* again until either (1) the previous work has been performed and removed
|
||||||
|
* from the queue, or (2) work_cancel() has been called to cancel the work
|
||||||
|
* and remove it from the work queue.
|
||||||
|
*
|
||||||
* Input parameters:
|
* Input parameters:
|
||||||
* work - The work structure to queue
|
* work - The work structure to queue
|
||||||
* worker - The worker callback to be invoked. The callback will invoked
|
* worker - The worker callback to be invoked. The callback will invoked
|
||||||
@ -121,7 +128,9 @@ EXTERN int work_queue(struct work_s *work, worker_t worker, FAR void *arg, uint3
|
|||||||
* Name: work_cancel
|
* Name: work_cancel
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Cancel previously queued work.
|
* Cancel previously queued work. This removes work from the work queue.
|
||||||
|
* After work has been canceled, it may be re-queue by calling work_queue()
|
||||||
|
* again.
|
||||||
*
|
*
|
||||||
* Input parameters:
|
* Input parameters:
|
||||||
* work - The previously queue work structure to cancel
|
* work - The previously queue work structure to cancel
|
||||||
@ -137,7 +146,9 @@ EXTERN int work_cancel(struct work_s *work);
|
|||||||
* Name: work_signal
|
* Name: work_signal
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Signal the worker thread to process the work queue now.
|
* Signal the worker thread to process the work queue now. This function
|
||||||
|
* is used internally by the work logic but could also be used by the
|
||||||
|
* user to force an immediate re-assessment of pending work.
|
||||||
*
|
*
|
||||||
* Input parameters:
|
* Input parameters:
|
||||||
* None
|
* None
|
||||||
|
@ -79,7 +79,9 @@
|
|||||||
* Name: work_cancel
|
* Name: work_cancel
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Cancel previously queued work.
|
* Cancel previously queued work. This removes work from the work queue.
|
||||||
|
* After work has been canceled, it may be re-queue by calling work_queue()
|
||||||
|
* again.
|
||||||
*
|
*
|
||||||
* Input parameters:
|
* Input parameters:
|
||||||
* work - The previously queue work structure to cancel
|
* work - The previously queue work structure to cancel
|
||||||
|
@ -83,6 +83,13 @@
|
|||||||
* Queue work to be performed at a later time. All queued work will be
|
* Queue work to be performed at a later time. All queued work will be
|
||||||
* performed on the worker thread of of execution (not the caller's).
|
* performed on the worker thread of of execution (not the caller's).
|
||||||
*
|
*
|
||||||
|
* The work structure is allocated by caller, but completely managed by
|
||||||
|
* the work queue logic. The caller should never modify the contents of
|
||||||
|
* the work queue structure; the caller should not call work_queue()
|
||||||
|
* again until either (1) the previous work has been performed and removed
|
||||||
|
* from the queue, or (2) work_cancel() has been called to cancel the work
|
||||||
|
* and remove it from the work queue.
|
||||||
|
*
|
||||||
* Input parameters:
|
* Input parameters:
|
||||||
* work - The work structure to queue
|
* work - The work structure to queue
|
||||||
* worker - The worker callback to be invoked. The callback will invoked
|
* worker - The worker callback to be invoked. The callback will invoked
|
||||||
|
@ -101,6 +101,8 @@ struct dq_queue_s g_work;
|
|||||||
int work_thread(int argc, char *argv[])
|
int work_thread(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
volatile FAR struct work_s *work;
|
volatile FAR struct work_s *work;
|
||||||
|
worker_t worker;
|
||||||
|
FAR void *arg;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
|
||||||
/* Loop forever */
|
/* Loop forever */
|
||||||
@ -130,37 +132,44 @@ int work_thread(int argc, char *argv[])
|
|||||||
work = (FAR struct work_s *)g_work.head;
|
work = (FAR struct work_s *)g_work.head;
|
||||||
while (work)
|
while (work)
|
||||||
{
|
{
|
||||||
/* Is this work ready? It is ready if there is no delay or if
|
/* Is this work ready? It is ready if there is no delay or if
|
||||||
* the delay has elapsed.
|
* the delay has elapsed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (work->delay == 0 || g_system_timer - work->qtime > work->delay)
|
if (work->delay == 0 || g_system_timer - work->qtime > work->delay)
|
||||||
{
|
{
|
||||||
/* Remove the ready-to-execute work from the list */
|
/* Remove the ready-to-execute work from the list */
|
||||||
|
|
||||||
(void)dq_rem((struct dq_entry_s *)work, &g_work);
|
(void)dq_rem((struct dq_entry_s *)work, &g_work);
|
||||||
|
|
||||||
/* Do the work. Re-enable interrupts while the work is being
|
/* Extract the work description from the entry (in case the work
|
||||||
* performed... we don't have any idea how long that will take!
|
* instance by the re-used after it has been de-queued).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
irqrestore(flags);
|
worker = work->worker;
|
||||||
work->worker(work->arg);
|
arg = work->arg;
|
||||||
|
|
||||||
/* Now, unfortunately, since we re-enabled interrupts we don't
|
/* Do the work. Re-enable interrupts while the work is being
|
||||||
* the state of the work list and we will have to start back at
|
* performed... we don't have any idea how long that will take!
|
||||||
* the head of the list.
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
flags = irqsave();
|
irqrestore(flags);
|
||||||
work = (FAR struct work_s *)g_work.head;
|
worker(arg);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This one is not ready, try the next in the list. */
|
|
||||||
|
|
||||||
work = (FAR struct work_s *)work->dq.flink;
|
/* Now, unfortunately, since we re-enabled interrupts we don't
|
||||||
}
|
* know the state of the work list and we will have to start
|
||||||
|
* back at the head of the list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
flags = irqsave();
|
||||||
|
work = (FAR struct work_s *)g_work.head;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This one is not ready, try the next in the list. */
|
||||||
|
|
||||||
|
work = (FAR struct work_s *)work->dq.flink;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user