summaryrefslogtreecommitdiff
path: root/nuttx/sched
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-06-01 17:46:26 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-06-01 17:46:26 +0000
commit60baf60892705bec8c3180025cd797c5d64a1e1e (patch)
tree26e2646c057a968cf9b83f137d533badf5eb219a /nuttx/sched
parente6e16479eb1559c46d23c0187f0c33735935185a (diff)
downloadpx4-nuttx-60baf60892705bec8c3180025cd797c5d64a1e1e.tar.gz
px4-nuttx-60baf60892705bec8c3180025cd797c5d64a1e1e.tar.bz2
px4-nuttx-60baf60892705bec8c3180025cd797c5d64a1e1e.zip
Fix problem when timer deleted by timer handler
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@762 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/sched')
-rw-r--r--nuttx/sched/timer_create.c25
-rw-r--r--nuttx/sched/timer_delete.c27
-rw-r--r--nuttx/sched/timer_internal.h11
-rw-r--r--nuttx/sched/timer_settime.c36
4 files changed, 75 insertions, 24 deletions
diff --git a/nuttx/sched/timer_create.c b/nuttx/sched/timer_create.c
index 645007c9f..a9e19dc2a 100644
--- a/nuttx/sched/timer_create.c
+++ b/nuttx/sched/timer_create.c
@@ -74,7 +74,8 @@
static struct posix_timer_s *timer_allocate(void)
{
struct posix_timer_s *ret;
- irqstate_t flags;
+ irqstate_t flags;
+ ubyte pt_flags;
/* Try to get a preallocated timer from the free list */
@@ -84,23 +85,31 @@ static struct posix_timer_s *timer_allocate(void)
irqrestore(flags);
/* Did we get one? */
-
- if (!ret)
+
+ if (ret)
+ {
+ pt_flags = PT_FLAGS_PREALLOCATED;
+ }
+ else
#endif
{
/* Allocate a new timer from the heap */
- ret = (struct posix_timer_s*)malloc(sizeof(struct posix_timer_s));
- if (ret)
- {
- ret->pt_flags = 0;
- }
+ ret = (struct posix_timer_s*)malloc(sizeof(struct posix_timer_s));
+ pt_flags = 0;
}
/* If we have a timer, then put it into the allocated timer list */
if (ret)
{
+ /* Initialize the timer structure */
+
+ memset(ret, 0, sizeof(struct posix_timer_s));
+ ret->pt_flags = pt_flags;
+
+ /* And add it to the end of the list of allocated timers */
+
flags = irqsave();
sq_addlast((sq_entry_t*)ret, (sq_queue_t*)&g_alloctimers);
irqrestore(flags);
diff --git a/nuttx/sched/timer_delete.c b/nuttx/sched/timer_delete.c
index 386807575..e6afc57bf 100644
--- a/nuttx/sched/timer_delete.c
+++ b/nuttx/sched/timer_delete.c
@@ -1,7 +1,7 @@
/********************************************************************************
* timer_delete.c
*
- * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@@ -14,7 +14,7 @@
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
- * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
@@ -137,16 +137,25 @@ int timer_delete(timer_t timerid)
*get_errno_ptr() = EINVAL;
return ERROR;
}
+
+ /* If the watchdog structure is busy now, then just mark it for deletion later */
+
+ if ((timer->pt_flags & PT_FLAGS_BUSY) != 0)
+ {
+ timer->pt_flags |= PT_FLAGS_DELETED;
+ }
+ else
+ {
+ /* Free the underlying watchdog instance (the timer will be canceled by the
+ * watchdog logic before it is actually deleted)
+ */
- /* Free the underlying watchdog instance (the timer will be canceled by the
- * watchdog logic before it is actually deleted)
- */
-
- (void)wd_delete(timer->pt_wdog);
+ (void)wd_delete(timer->pt_wdog);
- /* Release the timer structure */
+ /* Release the timer structure */
- timer_free(timer);
+ timer_free(timer);
+ }
return OK;
}
diff --git a/nuttx/sched/timer_internal.h b/nuttx/sched/timer_internal.h
index 604adbc8e..e4403499c 100644
--- a/nuttx/sched/timer_internal.h
+++ b/nuttx/sched/timer_internal.h
@@ -1,7 +1,7 @@
/********************************************************************************
* timer_internal.h
*
- * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@@ -14,7 +14,7 @@
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
- * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
@@ -49,7 +49,12 @@
* Definitions
********************************************************************************/
-#define PT_FLAGS_PREALLOCATED 0x01
+#define PT_FLAGS_PREALLOCATED 0x01 /* Timer comes from a pool of preallocated timers */
+#define PT_FLAGS_BUSY 0x02 /* Timer cannot be deleted now */
+#define PT_FLAGS_DELETED 0x04 /* Busy timer marked for deletion */
+
+#define PT_FLAGS_STATIC PT_FLAGS_PREALLOCATED
+#define PT_FLAGS_DYNAMIC (~PT_FLAGS_STATIC)
/********************************************************************************
* Public Types
diff --git a/nuttx/sched/timer_settime.c b/nuttx/sched/timer_settime.c
index 27f7d2af1..ab130210e 100644
--- a/nuttx/sched/timer_settime.c
+++ b/nuttx/sched/timer_settime.c
@@ -39,7 +39,9 @@
#include <nuttx/config.h>
#include <time.h>
+#include <string.h>
#include <errno.h>
+
#include "os_internal.h"
#include "clock_internal.h"
#include "sig_internal.h"
@@ -181,21 +183,47 @@ static void timer_timeout(int argc, uint32 itimer)
/* Send the specified signal to the specified task. */
+ u.timer->pt_flags |= PT_FLAGS_BUSY;
timer_sigqueue(u.timer);
+ u.timer->pt_flags &= ~PT_FLAGS_BUSY;
+
+ /* Check if the signal handler attempted to delete the timer */
+
+ if ((u.timer->pt_flags & PT_FLAGS_DELETED) != 0)
+ {
+ /* Yes.. delete the timer now that we are no longer busy */
- /* If this is a repetitive timer, the restart the watchdog */
+ timer_delete(u.timer);
+ }
+ else
+ {
+ /* If this is a repetitive timer, the restart the watchdog */
- timer_restart(u.timer, itimer);
+ timer_restart(u.timer, itimer);
+ }
#else
FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)itimer;
/* Send the specified signal to the specified task. */
+ timer->pt_flags |= PT_FLAGS_BUSY;
timer_sigqueue(timer);
+ timer->pt_flags &= ~PT_FLAGS_BUSY;
- /* If this is a repetitive timer, the restart the watchdog */
+ /* Check if the signal handler attempted to delete the timer */
- timer_restart(timer, itimer);
+ if ((timer->pt_flags & PT_FLAGS_DELETED) != 0)
+ {
+ /* Yes.. delete the timer now that we are no longer busy */
+
+ timer_delete(timer);
+ }
+ else
+ {
+ /* If this is a repetitive timer, the restart the watchdog */
+
+ timer_restart(timer, itimer);
+ }
#endif
}