summaryrefslogtreecommitdiff
path: root/nuttx/libc
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-06-29 09:30:09 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-06-29 09:30:09 -0600
commit1deaf2a9634576bf0e0f35a24911c3f22215fbd2 (patch)
treecfc63769fd41a0e4417e2a723d79e4ba8fb6f077 /nuttx/libc
parent02bad8e430f112e7f0bac29f52861c7048cb2bbe (diff)
downloadpx4-nuttx-1deaf2a9634576bf0e0f35a24911c3f22215fbd2.tar.gz
px4-nuttx-1deaf2a9634576bf0e0f35a24911c3f22215fbd2.tar.bz2
px4-nuttx-1deaf2a9634576bf0e0f35a24911c3f22215fbd2.zip
Fixes for networking and tiny webserver from Max
Diffstat (limited to 'nuttx/libc')
-rw-r--r--nuttx/libc/wqueue/work_thread.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/nuttx/libc/wqueue/work_thread.c b/nuttx/libc/wqueue/work_thread.c
index 285f7183c..c0474ad69 100644
--- a/nuttx/libc/wqueue/work_thread.c
+++ b/nuttx/libc/wqueue/work_thread.c
@@ -148,26 +148,44 @@ static void work_process(FAR struct wqueue_s *wqueue)
*/
worker = work->worker;
- arg = work->arg;
- /* Mark the work as no longer being queued */
+ /* Check for a race condition where the work may be nullified
+ * before it is removed from the queue.
+ */
- work->worker = NULL;
+ if (worker != NULL)
+ {
+ /* Extract the work argument (before re-enabling interrupts) */
- /* Do the work. Re-enable interrupts while the work is being
- * performed... we don't have any idea how long that will take!
- */
+ arg = work->arg;
- irqrestore(flags);
- worker(arg);
+ /* Mark the work as no longer being queued */
- /* 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.
- */
+ work->worker = NULL;
+
+ /* Do the work. Re-enable interrupts while the work is being
+ * performed... we don't have any idea how long that will take!
+ */
+
+ irqrestore(flags);
+ worker(arg);
- flags = irqsave();
- work = (FAR struct work_s *)wqueue->q.head;
+ /* 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 *)wqueue->q.head;
+ }
+ else
+ {
+ /* Cancelled.. Just move to the next work in the list with
+ * interrupts still disabled.
+ */
+
+ work = (FAR struct work_s *)work->dq.flink;
+ }
}
else
{