From a9b64a74694908e200732e411a2555a86619044c Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 1 Jun 2008 17:46:26 +0000 Subject: [PATCH] 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 --- ChangeLog | 1 + Documentation/NuttX.html | 1 + sched/timer_create.c | 25 +++++++++++++++++-------- sched/timer_delete.c | 29 +++++++++++++++++++---------- sched/timer_internal.h | 11 ++++++++--- sched/timer_settime.c | 36 ++++++++++++++++++++++++++++++++---- 6 files changed, 78 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index ddf3e9e136d..f3742881d07 100644 --- a/ChangeLog +++ b/ChangeLog @@ -365,3 +365,4 @@ * Fix several FAT filesystem problems reported by kwonsk (Changes not yet verified). * Host simulator no longer uses Linux system calls directly; Now works with Cygwin. + * Fix an error that occurs when a POSIX timer is deleted by the timer signal handler. diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index 43e26d663ca..c6b94fa5952 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -1015,6 +1015,7 @@ nuttx-0.3.11 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> * Fix several FAT filesystem problems reported by kwonsk (Changes not yet verified). * Host simulator no longer uses Linux system calls directly; Now works with Cygwin. + * Fix an error that occurs when a POSIX timer is deleted by the timer signal handler. pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> diff --git a/sched/timer_create.c b/sched/timer_create.c index 645007c9fc5..a9e19dc2ade 100644 --- a/sched/timer_create.c +++ b/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/sched/timer_delete.c b/sched/timer_delete.c index 3868075756f..e6afc57bf20 100644 --- a/sched/timer_delete.c +++ b/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 * * 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; } - - /* 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); - /* Release the timer structure */ + /* If the watchdog structure is busy now, then just mark it for deletion later */ - timer_free(timer); + 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) + */ + + (void)wd_delete(timer->pt_wdog); + + /* Release the timer structure */ + + timer_free(timer); + } return OK; } diff --git a/sched/timer_internal.h b/sched/timer_internal.h index 604adbc8ef5..e4403499cb9 100644 --- a/sched/timer_internal.h +++ b/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 * * 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/sched/timer_settime.c b/sched/timer_settime.c index 27f7d2af196..ab130210e3f 100644 --- a/sched/timer_settime.c +++ b/sched/timer_settime.c @@ -39,7 +39,9 @@ #include #include +#include #include + #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; - /* If this is a repetitive timer, the restart the watchdog */ + /* Check if the signal handler attempted to delete the timer */ - timer_restart(u.timer, itimer); + if ((u.timer->pt_flags & PT_FLAGS_DELETED) != 0) + { + /* Yes.. delete the timer now that we are no longer busy */ + + timer_delete(u.timer); + } + else + { + /* If this is a repetitive timer, the restart the watchdog */ + + 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 }