diff --git a/libc/semaphore/Make.defs b/libc/semaphore/Make.defs index cafa18b65a..6c91f068cd 100644 --- a/libc/semaphore/Make.defs +++ b/libc/semaphore/Make.defs @@ -37,6 +37,10 @@ CSRCS += sem_init.c sem_getprotocol.c sem_getvalue.c +ifneq ($(CONFIG_PRIORITY_INHERITANCE),y) +CSRCS += sem_setprotocol.c +endif + # Add the semaphore directory to the build DEPPATH += --dep-path semaphore diff --git a/libc/semaphore/sem_setprotocol.c b/libc/semaphore/sem_setprotocol.c new file mode 100644 index 0000000000..38336a31a0 --- /dev/null +++ b/libc/semaphore/sem_setprotocol.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * libc/semaphore/sem_setprotocol.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 + +#ifndef CONFIG_PRIORITY_INHERITANCE + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sem_setprotocol + * + * Description: + * Set semaphore protocol attribute. + * + * One particularly important use of this furnction is when a semaphore + * is used for inter-task communication like: + * + * TASK A TASK B + * sem_init(sem, 0, 0); + * sem_wait(sem); + * sem_post(sem); + * Awakens as holder + * + * In this case priority inheritance can interfere with the operation of + * the semaphore. The problem is that when TASK A is restarted it is a + * holder of the semaphore. However, it never calls sem_post(sem) so it + * becomes *permanently* a holder of the semaphore and may have its + * priority boosted when any other task tries to acquire the semaphore. + * + * The fix is to call sem_setprotocol(SEM_PRIO_NONE) immediately after + * the sem_init() call so that there will be no priority inheritance + * operations on this semaphore. + * + * Parameters: + * sem - A pointer to the semaphore whose attributes are to be + * modified + * protocol - The new protocol to use + * + * Return Value: + * 0 if successful. Otherwise, -1 is returned and the errno value is set + * appropriately. + * + ****************************************************************************/ + +int sem_setprotocol(FAR sem_t *sem, int protocol) +{ + int errcode; + + DEBUGASSERT(sem != NULL); + + switch (protocol) + { + case SEM_PRIO_NONE: + return OK; + + case SEM_PRIO_INHERIT: + case SEM_PRIO_PROTECT: + errcode = ENOSYS; + break; + + default: + errcode = EINVAL; + break; + } + + set_errno(errcode); + return ERROR; +} + +#endif /* !CONFIG_PRIORITY_INHERITANCE */ diff --git a/sched/semaphore/Make.defs b/sched/semaphore/Make.defs index 93fd35a0d0..7eb1740424 100644 --- a/sched/semaphore/Make.defs +++ b/sched/semaphore/Make.defs @@ -37,10 +37,10 @@ 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_reset.c sem_setprotocol.c sem_waitirq.c +CSRCS += sem_reset.c sem_waitirq.c ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) -CSRCS += sem_initialize.c sem_holder.c +CSRCS += sem_initialize.c sem_holder.c sem_setprotocol.c endif ifeq ($(CONFIG_SPINLOCK),y) diff --git a/sched/semaphore/sem_setprotocol.c b/sched/semaphore/sem_setprotocol.c index 6f4392bcce..89764f6ad7 100644 --- a/sched/semaphore/sem_setprotocol.c +++ b/sched/semaphore/sem_setprotocol.c @@ -46,6 +46,8 @@ #include "semaphore/semaphore.h" +#ifdef CONFIG_PRIORITY_INHERITANCE + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -95,7 +97,6 @@ int sem_setprotocol(FAR sem_t *sem, int protocol) switch (protocol) { case SEM_PRIO_NONE: -#ifdef CONFIG_PRIORITY_INHERITANCE /* Disable priority inheritance */ sem->flags |= PRIOINHERIT_FLAGS_DISABLE; @@ -103,16 +104,13 @@ int sem_setprotocol(FAR sem_t *sem, int protocol) /* Remove any current holders */ sem_destroyholder(sem); -#endif return OK; case SEM_PRIO_INHERIT: -#ifdef CONFIG_PRIORITY_INHERITANCE /* Enable priority inheritance (dangerous) */ sem->flags &= ~PRIOINHERIT_FLAGS_DISABLE; return OK; -#endif case SEM_PRIO_PROTECT: /* Not yet supported */ @@ -128,3 +126,5 @@ int sem_setprotocol(FAR sem_t *sem, int protocol) set_errno(errcode); return ERROR; } + +endif /* CONFIG_PRIORITY_INHERITANCE */ diff --git a/syscall/syscall.csv b/syscall/syscall.csv index 99071ea27d..8ecf52854f 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -118,7 +118,7 @@ "sem_destroy","semaphore.h","","int","FAR sem_t*" "sem_open","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","FAR sem_t*","FAR const char*","int","..." "sem_post","semaphore.h","","int","FAR sem_t*" -"sem_setprotocol","nuttx/semaphore.h","","int","FAR sem_t*","int" +"sem_setprotocol","nuttx/semaphore.h","defined(CONFIG_PRIORITY_INHERITANCE)","int","FAR sem_t*","int" "sem_timedwait","semaphore.h","","int","FAR sem_t*","FAR const struct timespec *" "sem_trywait","semaphore.h","","int","FAR sem_t*" "sem_unlink","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","int","FAR const char*"