From 5d63cd85c73328e181106337c7a57bb17e95474b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 5 Mar 2016 07:33:24 -0600 Subject: [PATCH] sched/semaphore: Add an internal interface to reset a semaphore count. --- ChangeLog | 5 +- arch | 2 +- configs | 2 +- include/nuttx/semaphore.h | 18 ++++++ sched/semaphore/Make.defs | 4 +- sched/semaphore/sem_reset.c | 121 ++++++++++++++++++++++++++++++++++++ 6 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 sched/semaphore/sem_reset.c diff --git a/ChangeLog b/ChangeLog index 13184a8589..4db1c92df0 100755 --- a/ChangeLog +++ b/ChangeLog @@ -11536,4 +11536,7 @@ * configs/sabre-6quad: Placeholder that will eventually become board support for the NXP/Freescale Sabre 6Quad board (2016-02-28). * arch/arm/src/stm32: Support for STM32F46xx from Paul Alexander Patience - (2016-03-01). + * sched/semaphore/sem_reset.c and include/nuttx/semaphore.h: Add an internal, + non-standard interface to reset a semaphore count. This is sometimes + needed by drivers in order to recover from error conditions (2016-03-05) + diff --git a/arch b/arch index 7fe684d488..0b8fe68bf5 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 7fe684d488ea88c31b2a155690de8beb7345f913 +Subproject commit 0b8fe68bf5c15b49d7877c97516fdda542b2149b diff --git a/configs b/configs index bc95bb361c..0c764446fe 160000 --- a/configs +++ b/configs @@ -1 +1 @@ -Subproject commit bc95bb361c0963b69782cc77cec251d047eadb0d +Subproject commit 0c764446fee7b6b4c6bb9c188042fb98b4d1e8eb diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h index 691e2f9624..bdb5cfb27f 100644 --- a/include/nuttx/semaphore.h +++ b/include/nuttx/semaphore.h @@ -113,6 +113,24 @@ extern "C" int sem_tickwait(FAR sem_t *sem, systime_t start, uint32_t delay); +/**************************************************************************** + * Name: sem_reset + * + * Description: + * Reset a semaphore to a specific value. This kind of operation is + * sometimes required for certain error handling conditions. + * + * Parameters: + * sem - Semaphore descriptor to be reset + * count - The requested semaphore count + * + * Return Value: + * 0 (OK) or a negated errno value if unsuccessful + * + ****************************************************************************/ + +int sem_reset(FAR sem_t *sem, int16_t count); + #undef EXTERN #ifdef __cplusplus } diff --git a/sched/semaphore/Make.defs b/sched/semaphore/Make.defs index e9624282c9..39ba7cd2dc 100644 --- a/sched/semaphore/Make.defs +++ b/sched/semaphore/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # sched/semaphore/Make.defs # -# Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. +# Copyright (C) 2014-2016 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -35,7 +35,7 @@ CSRCS += sem_destroy.c sem_wait.c sem_trywait.c sem_tickwait.c CSRCS += sem_timedwait.c sem_timeout.c sem_post.c sem_recover.c -CSRCS += sem_waitirq.c +CSRCS += sem_reset.c sem_waitirq.c ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) CSRCS += sem_initialize.c sem_holder.c diff --git a/sched/semaphore/sem_reset.c b/sched/semaphore/sem_reset.c new file mode 100644 index 0000000000..6db75887ab --- /dev/null +++ b/sched/semaphore/sem_reset.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * sched/semaphore/sem_reset.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "semaphore/semaphore.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sem_reset + * + * Description: + * Reset a semaphore to a specific value. This kind of operation is + * sometimes required for certain error handling conditions. + * + * Parameters: + * sem - Semaphore descriptor to be reset + * count - The requested semaphore count + * + * Return Value: + * 0 (OK) or a negated errno value if unsuccessful + * + ****************************************************************************/ + +int sem_reset(FAR sem_t *sem, int16_t count) +{ + irqstate_t flags; + + DEBUGASSERT(sem != NULL && count >= 0); + + /* Don't allow any context switches that may result from the following + * sem_post operations. + */ + + sched_lock(); + + /* Prevent any access to the semaphore by interrupt handlers while we are + * performing this operation. + */ + + flags = enter_critical_section(); + + /* A negative count indicates the negated number of threads that are + * waiting to take a count from the semaphore. Loop here, handing + * out counts to any waiting threads. + */ + + while (sem->semcount < 0 && count > 0) + { + /* Give out one counting, waking up one of the waiting threads + * and, perhaps, kicking off a lot of priority inheritance + * logic (REVISIT). + */ + + DEBUGVERIFY(sem_post(sem)); + count--; + } + + /* We exit the above loop with either (1) no threads waiting for the + * (i.e., with sem->semcount >= 0). In this case, 'count' holds the + * the new value of the semaphore count. OR (2) with threads still + * waiting but all of the semaphore counts exhausted: The current + * value of sem->semcount is correct. + */ + + if (sem->semcount >= 0) + { + sem->semcount = count; + } + + /* Allow any pending context switches to occur now */ + + leave_critical_section(flags); + sched_unlock(); + return OK; +}