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
This commit is contained in:
patacongo
2008-06-01 17:46:26 +00:00
parent b5d6002463
commit a9b64a7469
6 changed files with 78 additions and 25 deletions
+1
View File
@@ -365,3 +365,4 @@
* Fix several FAT filesystem problems reported by kwonsk (Changes not yet * Fix several FAT filesystem problems reported by kwonsk (Changes not yet
verified). verified).
* Host simulator no longer uses Linux system calls directly; Now works with Cygwin. * 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.
+1
View File
@@ -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 * Fix several FAT filesystem problems reported by kwonsk (Changes not yet
verified). verified).
* Host simulator no longer uses Linux system calls directly; Now works with Cygwin. * 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> pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
+17 -8
View File
@@ -74,7 +74,8 @@
static struct posix_timer_s *timer_allocate(void) static struct posix_timer_s *timer_allocate(void)
{ {
struct posix_timer_s *ret; struct posix_timer_s *ret;
irqstate_t flags; irqstate_t flags;
ubyte pt_flags;
/* Try to get a preallocated timer from the free list */ /* Try to get a preallocated timer from the free list */
@@ -84,23 +85,31 @@ static struct posix_timer_s *timer_allocate(void)
irqrestore(flags); irqrestore(flags);
/* Did we get one? */ /* Did we get one? */
if (!ret) if (ret)
{
pt_flags = PT_FLAGS_PREALLOCATED;
}
else
#endif #endif
{ {
/* Allocate a new timer from the heap */ /* Allocate a new timer from the heap */
ret = (struct posix_timer_s*)malloc(sizeof(struct posix_timer_s)); ret = (struct posix_timer_s*)malloc(sizeof(struct posix_timer_s));
if (ret) pt_flags = 0;
{
ret->pt_flags = 0;
}
} }
/* If we have a timer, then put it into the allocated timer list */ /* If we have a timer, then put it into the allocated timer list */
if (ret) 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(); flags = irqsave();
sq_addlast((sq_entry_t*)ret, (sq_queue_t*)&g_alloctimers); sq_addlast((sq_entry_t*)ret, (sq_queue_t*)&g_alloctimers);
irqrestore(flags); irqrestore(flags);
+19 -10
View File
@@ -1,7 +1,7 @@
/******************************************************************************** /********************************************************************************
* timer_delete.c * 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> * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* *
* Redistribution and use in source and binary forms, with or without * 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 * notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the * the documentation and/or other materials provided with the
* distribution. * 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 * used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@@ -137,16 +137,25 @@ int timer_delete(timer_t timerid)
*get_errno_ptr() = EINVAL; *get_errno_ptr() = EINVAL;
return ERROR; 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; return OK;
} }
+8 -3
View File
@@ -1,7 +1,7 @@
/******************************************************************************** /********************************************************************************
* timer_internal.h * 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> * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* *
* Redistribution and use in source and binary forms, with or without * 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 * notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the * the documentation and/or other materials provided with the
* distribution. * 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 * used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@@ -49,7 +49,12 @@
* Definitions * 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 * Public Types
+32 -4
View File
@@ -39,7 +39,9 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <time.h> #include <time.h>
#include <string.h>
#include <errno.h> #include <errno.h>
#include "os_internal.h" #include "os_internal.h"
#include "clock_internal.h" #include "clock_internal.h"
#include "sig_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. */ /* Send the specified signal to the specified task. */
u.timer->pt_flags |= PT_FLAGS_BUSY;
timer_sigqueue(u.timer); 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 #else
FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)itimer; FAR struct posix_timer_s *timer = (FAR struct posix_timer_s *)itimer;
/* Send the specified signal to the specified task. */ /* Send the specified signal to the specified task. */
timer->pt_flags |= PT_FLAGS_BUSY;
timer_sigqueue(timer); 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 #endif
} }