From 7d0fb9d34f68ea704b93783f0064bcfc52420236 Mon Sep 17 00:00:00 2001 From: wangchengdong Date: Wed, 3 Sep 2025 18:12:40 +0800 Subject: [PATCH] sched/semaphore: add support to customize semaphore max allowed value Curernt implementation default semaphore max allowed value to SEM_VALUE_MAX. In some cases, user may want to change this, so provide a function to do this: sem_setmaxvalue Signed-off-by: Chengdong Wang --- .../reference/user/05_counting_semaphore.rst | 5 ++ include/nuttx/semaphore.h | 21 ++++++ include/semaphore.h | 4 ++ libs/libc/semaphore/CMakeLists.txt | 4 ++ libs/libc/semaphore/Make.defs | 4 ++ libs/libc/semaphore/sem_init.c | 4 ++ libs/libc/semaphore/sem_setmaxvalue.c | 66 +++++++++++++++++++ sched/Kconfig | 7 ++ sched/semaphore/sem_post.c | 4 ++ 9 files changed, 119 insertions(+) create mode 100644 libs/libc/semaphore/sem_setmaxvalue.c diff --git a/Documentation/reference/user/05_counting_semaphore.rst b/Documentation/reference/user/05_counting_semaphore.rst index 638037718b4..e10255e6eb2 100644 --- a/Documentation/reference/user/05_counting_semaphore.rst +++ b/Documentation/reference/user/05_counting_semaphore.rst @@ -108,6 +108,11 @@ result. Semaphore does not support priority inheritance by default. If you need to use a semaphore as a mutex you need to change its default behavior. +Each semaphore is assigned a default maximum value defined by SEM_VALUE_MAX. +If ``CONFIG_CUSTOM_SEMAPHORE_MAXVALUE`` is enabled, applications may override this limit. +In such cases, the function ``nxsem_setmaxvalue()`` can be used to specify a custom maximum value +for an individual semaphore. + In user space, it is recommended to use pthread_mutex instead of semaphore for resource protection diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h index 1c28dc94104..1c3b3256dbf 100644 --- a/include/nuttx/semaphore.h +++ b/include/nuttx/semaphore.h @@ -412,6 +412,27 @@ int nxsem_post_slow(FAR sem_t *sem); int nxsem_get_value(FAR sem_t *sem, FAR int *sval); +#ifdef CONFIG_CUSTOM_SEMAPHORE_MAXVALUE +/**************************************************************************** + * Name: nxsem_setmaxvalue + * + * Description: + * This function sets the maximum allowed value for a specific semaphore. + * + * Input Parameters: + * sem - Semaphore descriptor + * maxvalue - The maximum allowed value + * + * Returned Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * + ****************************************************************************/ + +int nxsem_setmaxvalue(FAR sem_t *sem, int32_t maxvalue); +#endif + /**************************************************************************** * Name: nxsem_open * diff --git a/include/semaphore.h b/include/semaphore.h index 75df214577d..0af204d54cb 100644 --- a/include/semaphore.h +++ b/include/semaphore.h @@ -123,6 +123,10 @@ struct sem_s dq_queue_t waitlist; +#ifdef CONFIG_CUSTOM_SEMAPHORE_MAXVALUE + int32_t maxvalue; +#endif + #ifdef CONFIG_PRIORITY_INHERITANCE # if CONFIG_SEM_PREALLOCHOLDERS > 0 FAR struct semholder_s *hhead; /* List of holders of semaphore counts */ diff --git a/libs/libc/semaphore/CMakeLists.txt b/libs/libc/semaphore/CMakeLists.txt index f544ca82d07..0cbb02b21c3 100644 --- a/libs/libc/semaphore/CMakeLists.txt +++ b/libs/libc/semaphore/CMakeLists.txt @@ -36,6 +36,10 @@ if(CONFIG_FS_NAMED_SEMAPHORES) list(APPEND SRCS sem_open.c sem_close.c sem_unlink.c) endif() +if(CONFIG_CUSTOM_SEMAPHORE_MAXVALUE) + list(APPEND SRCS sem_setmaxvalue.c) +endif() + if(CONFIG_PRIORITY_PROTECT) list(APPEND SRCS sem_getprioceiling.c sem_setprioceiling.c) endif() diff --git a/libs/libc/semaphore/Make.defs b/libs/libc/semaphore/Make.defs index b967da80ae3..e648ceba48d 100644 --- a/libs/libc/semaphore/Make.defs +++ b/libs/libc/semaphore/Make.defs @@ -30,6 +30,10 @@ ifeq ($(CONFIG_FS_NAMED_SEMAPHORES),y) CSRCS += sem_open.c sem_close.c sem_unlink.c endif +ifeq ($(CONFIG_CUSTOM_SEMAPHORE_MAXVALUE),y) +CSRCS += sem_setmaxvalue.c +endif + ifeq ($(CONFIG_PRIORITY_PROTECT),y) CSRCS += sem_getprioceiling.c sem_setprioceiling.c endif diff --git a/libs/libc/semaphore/sem_init.c b/libs/libc/semaphore/sem_init.c index be0cba9fde5..eadd2a73a5d 100644 --- a/libs/libc/semaphore/sem_init.c +++ b/libs/libc/semaphore/sem_init.c @@ -72,6 +72,10 @@ int nxsem_init(FAR sem_t *sem, int pshared, int32_t value) sem->val.semcount = (int32_t)value; +#ifdef CONFIG_CUSTOM_SEMAPHORE_MAXVALUE + sem->maxvalue = SEM_VALUE_MAX; +#endif + /* Initialize semaphore wait list */ dq_init(&sem->waitlist); diff --git a/libs/libc/semaphore/sem_setmaxvalue.c b/libs/libc/semaphore/sem_setmaxvalue.c new file mode 100644 index 00000000000..5dbb496035a --- /dev/null +++ b/libs/libc/semaphore/sem_setmaxvalue.c @@ -0,0 +1,66 @@ +/**************************************************************************** + * libs/libc/semaphore/sem_setmaxvalue.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#ifdef CONFIG_CUSTOM_SEMAPHORE_MAXVALUE + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxsem_setmaxvalue + * + * Description: + * Set sem max allowed value + * + * Input Parameters: + * sem - Semaphore object + * delay - Max allowed semaphore value. + * + * Returned Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * + ****************************************************************************/ + +int nxsem_setmaxvalue(FAR sem_t *sem, int32_t maxvalue) +{ + if (sem != NULL) + { + sem->maxvalue = maxvalue; + return OK; + } + + return -EINVAL; +} + +#endif /* CONFIG_PRIORITY_INHERITANCE */ diff --git a/sched/Kconfig b/sched/Kconfig index 1d5c88f16a1..194dac51888 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -2027,3 +2027,10 @@ config COREDUMP The memory state embeds a snapshot of all segments mapped in the memory space of the program. The CPU state contains register values when the core dump has been generated. + +config CUSTOM_SEMAPHORE_MAXVALUE + bool "Custom max value for semaphores" + default n + ---help--- + Enable to support custom max value for semaphores. + When this option is enabled, the max value of a semaphore can be set diff --git a/sched/semaphore/sem_post.c b/sched/semaphore/sem_post.c index cbf5758f67e..26f17e63b58 100644 --- a/sched/semaphore/sem_post.c +++ b/sched/semaphore/sem_post.c @@ -125,7 +125,11 @@ int nxsem_post_slow(FAR sem_t *sem) sem_count = atomic_read(NXSEM_COUNT(sem)); do { +#ifdef CONFIG_CUSTOM_SEMAPHORE_MAXVALUE + if (sem_count >= sem->maxvalue) +#else if (sem_count >= SEM_VALUE_MAX) +#endif { leave_critical_section(flags); return -EOVERFLOW;