diff --git a/sched/Makefile b/sched/Makefile index 75d07676a4..39a526edaf 100644 --- a/sched/Makefile +++ b/sched/Makefile @@ -117,10 +117,10 @@ PTHREAD_SRCS += pthread_condtimedwait.c pthread_kill.c pthread_sigmask.c endif SEM_SRCS = sem_initialize.c sem_destroy.c sem_open.c sem_close.c sem_unlink.c \ - sem_wait.c sem_trywait.c sem_post.c sem_findnamed.c + sem_wait.c sem_trywait.c sem_timedwait.c sem_post.c sem_findnamed.c ifneq ($(CONFIG_DISABLE_SIGNALS),y) -SEM_SRCS += sem_waitirq.c sem_timedwait.c +SEM_SRCS += sem_waitirq.c endif ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) diff --git a/sched/sem_internal.h b/sched/sem_internal.h index cbb7e96ddf..b67e506bfb 100644 --- a/sched/sem_internal.h +++ b/sched/sem_internal.h @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sem_internal.h * - * Copyright (C) 2007, 2009-2010 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009-2011 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -90,7 +90,7 @@ extern "C" { #endif EXTERN void weak_function sem_initialize(void); -EXTERN void sem_waitirq(FAR _TCB *wtcb); +EXTERN void sem_waitirq(FAR _TCB *wtcb, int errcode); EXTERN FAR nsem_t *sem_findnamed(const char *name); #ifdef CONFIG_PRIORITY_INHERITANCE diff --git a/sched/sem_timedwait.c b/sched/sem_timedwait.c index 7b01d22d81..5a1b943a56 100644 --- a/sched/sem_timedwait.c +++ b/sched/sem_timedwait.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sem_timedwait.c * - * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Copyright (C) 2011 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -51,6 +51,7 @@ #include "os_internal.h" #include "clock_internal.h" +#include "sem_internal.h" /**************************************************************************** * Pre-processor Definitions @@ -111,13 +112,9 @@ static void sem_timeout(int argc, uint32_t pid) if (wtcb && wtcb->task_state == TSTATE_WAIT_SEM) { - /* Mark the errno value for the thread. */ - - wtcb->pterrno = ETIMEDOUT; - - /* Restart the task. */ - - up_unblock_task(wtcb); + /* Cancel the semaphore wait */ + + sem_waitirq(wtcb, ETIMEDOUT); } /* Interrupts may now be enabled. */ diff --git a/sched/sem_wait.c b/sched/sem_wait.c index 12d8c98ca6..d7a38e5555 100644 --- a/sched/sem_wait.c +++ b/sched/sem_wait.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sem_wait.c * - * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -171,16 +171,16 @@ int sem_wait(FAR sem_t *sem) #endif /* Add the TCB to the prioritized semaphore wait queue */ - errno = 0; + errno = OK; up_block_task(rtcb, TSTATE_WAIT_SEM); /* When we resume at this point, either (1) the semaphore has been * assigned to this thread of execution, or (2) the semaphore wait - * has been interrupted by a signal. We can detect the latter case - * be examining the errno value. + * has been interrupted by a signal or a timeout. We can detect these + * latter cases be examining the errno value. * - * In the event that the semaphore wait was interrupt was interrupted - * by a signal, certain semaphore clean-up operations have already been + * In the event that the semaphore wait was interrupted by a signal or + * a timeout, certain semaphore clean-up operations have already been * performed (see sem_waitirq.c). Specifically: * * - sem_canceled() was called to restore the priority of all threads @@ -194,9 +194,9 @@ int sem_wait(FAR sem_t *sem) * race conditions. */ - if (errno != EINTR) + if (errno != EINTR && errno != ETIMEDOUT) { - /* We hold the semaphore */ + /* Not awakened by a signal or a timeout... We hold the semaphore */ sem_addholder(sem); ret = OK; diff --git a/sched/sem_waitirq.c b/sched/sem_waitirq.c index 317a37a062..409cf780ad 100644 --- a/sched/sem_waitirq.c +++ b/sched/sem_waitirq.c @@ -73,15 +73,16 @@ * Function: sem_waitirq * * Description: - * This function is called when a signal is received by a - * task that is waiting on a semaphore. According to the - * POSIX spec, "...the calling thread shall not return - * from the call to [sem_wait] until it either locks the - * semaphore or the call is interrupted by a signal." + * This function is called when a signal is received by a task that is + * waiting on a semaphore. According to the POSIX spec, "...the calling + * thread shall not return from the call to [sem_wait] until it either + * locks the semaphore or the call is interrupted by a signal." * * Parameters: - * wtcb - A pointer to the TCB of the task that is waiting - * on a semphare, but has received a signal instead. + * wtcb - A pointer to the TCB of the task that is waiting on a + * semphaphore, but has received a signal or timeout instead. + * errcode - EINTR if the semaphore wait was awakened by a signal; + * ETIMEDOUT if awakened by a timeout * * Return Value: * None @@ -90,7 +91,7 @@ * ****************************************************************************/ -void sem_waitirq(FAR _TCB *wtcb) +void sem_waitirq(FAR _TCB *wtcb, int errcode) { irqstate_t saved_state; @@ -101,8 +102,8 @@ void sem_waitirq(FAR _TCB *wtcb) saved_state = irqsave(); - /* It is possible that an interrupt/context switch beat us to the - * punch and already changed the task's state. + /* It is possible that an interrupt/context switch beat us to the punch + * and already changed the task's state. */ if (wtcb->task_state == TSTATE_WAIT_SEM) @@ -116,10 +117,10 @@ void sem_waitirq(FAR _TCB *wtcb) sem_canceled(wtcb, sem); - /* And increment the count on the semaphore. This releases the - * count that was taken by sem_post(). This count decremented - * the semaphore count to negative and caused the thread to be - * blocked in the first place. + /* And increment the count on the semaphore. This releases the count + * that was taken by sem_post(). This count decremented the semaphore + * count to negative and caused the thread to be blocked in the first + * place. */ sem->semcount++; @@ -130,7 +131,7 @@ void sem_waitirq(FAR _TCB *wtcb) /* Mark the errno value for the thread. */ - wtcb->pterrno = EINTR; + wtcb->pterrno = errcode; /* Restart the task. */ diff --git a/sched/sig_received.c b/sched/sig_received.c index 775d36df1e..56f7f1deac 100644 --- a/sched/sig_received.c +++ b/sched/sig_received.c @@ -1,7 +1,7 @@ /************************************************************************ * sched/sig_received.c * - * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -43,7 +43,9 @@ #include #include #include +#include #include + #include #include "os_internal.h" @@ -377,7 +379,7 @@ int sig_received(FAR _TCB *stcb, siginfo_t *info) if (stcb->task_state == TSTATE_WAIT_SEM) { - sem_waitirq(stcb); + sem_waitirq(stcb, EINTR); } /* If the task is blocked waiting on a message queue, then that