From 4193d413c600c78215c69af8089a7386836184ff Mon Sep 17 00:00:00 2001 From: zhangyuan29 Date: Thu, 22 Aug 2024 10:24:30 +0800 Subject: [PATCH] sem: add mutex protect in sem_trywait Signed-off-by: zhangyuan29 --- sched/semaphore/CMakeLists.txt | 4 ++ sched/semaphore/Make.defs | 4 ++ sched/semaphore/sem_post.c | 11 +--- sched/semaphore/sem_protect.c | 116 +++++++++++++++++++++++++++++++++ sched/semaphore/sem_trywait.c | 7 ++ sched/semaphore/sem_wait.c | 17 ++--- sched/semaphore/semaphore.h | 12 +++- 7 files changed, 148 insertions(+), 23 deletions(-) create mode 100644 sched/semaphore/sem_protect.c diff --git a/sched/semaphore/CMakeLists.txt b/sched/semaphore/CMakeLists.txt index 8d378e04b0286..c50e1b9baab17 100644 --- a/sched/semaphore/CMakeLists.txt +++ b/sched/semaphore/CMakeLists.txt @@ -36,4 +36,8 @@ if(CONFIG_PRIORITY_INHERITANCE) list(APPEND CSRCS sem_initialize.c sem_holder.c sem_setprotocol.c) endif() +if(CONFIG_PRIORITY_PROTECT) + list(APPEND CSRCS sem_protect.c) +endif() + target_sources(sched PRIVATE ${CSRCS}) diff --git a/sched/semaphore/Make.defs b/sched/semaphore/Make.defs index f2a9e7ffb4f06..cf119fc3ad909 100644 --- a/sched/semaphore/Make.defs +++ b/sched/semaphore/Make.defs @@ -28,6 +28,10 @@ ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) CSRCS += sem_initialize.c sem_holder.c sem_setprotocol.c endif +ifeq ($(CONFIG_PRIORITY_PROTECT),y) +CSRCS += sem_protect.c +endif + # Include semaphore build support DEPPATH += --dep-path semaphore diff --git a/sched/semaphore/sem_post.c b/sched/semaphore/sem_post.c index 94c09ef59a442..3d10bf9a9776c 100644 --- a/sched/semaphore/sem_post.c +++ b/sched/semaphore/sem_post.c @@ -200,16 +200,9 @@ int nxsem_post(FAR sem_t *sem) nxsem_restore_baseprio(stcb, sem); #endif } - - if (proto == SEM_PRIO_PROTECT) + else if (proto == SEM_PRIO_PROTECT) { -#ifdef CONFIG_PRIORITY_PROTECT - if (sem->saved > 0) - { - nxsched_set_priority(this_task(), sem->saved); - sem->saved = 0; - } -#endif + nxsem_protect_post(sem); } sched_unlock(); diff --git a/sched/semaphore/sem_protect.c b/sched/semaphore/sem_protect.c new file mode 100644 index 0000000000000..501dd3402d6a9 --- /dev/null +++ b/sched/semaphore/sem_protect.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * sched/semaphore/sem_protect.c + * + * 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 + +#include "sched/sched.h" +#include "semaphore/semaphore.h" + +#ifdef CONFIG_PRIORITY_PROTECT + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxsem_protect_wait + * + * Description: + * This function attempts to lock the protected semaphore, set the + * holder tcb priority to ceiling priority. + * + * This is an internal OS interface. It is functionally equivalent to + * sem_wait except that: + * + * - It is not a cancellation point, and + * - It does not modify the errno value. + * + * Input Parameters: + * sem - Semaphore descriptor. + * + * 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. + * Possible returned errors: + * + * - EINVAL: Invalid attempt to get the semaphore + * + ****************************************************************************/ + +int nxsem_protect_wait(FAR sem_t *sem) +{ + if ((sem->flags & SEM_PRIO_MASK) == SEM_PRIO_PROTECT) + { + FAR struct tcb_s *rtcb = this_task(); + + if (rtcb->sched_priority > sem->ceiling) + { + return -EINVAL; + } + + sem->saved = rtcb->sched_priority; + rtcb->sched_priority = sem->ceiling; + } + + return OK; +} + +/**************************************************************************** + * Name: nxsem_protect_post + * + * Description: + * This function attempts to unlock the protected semaphore, restore the + * holder tcb priority. + * + * This is an internal OS interface. It is functionally equivalent to + * sem_wait except that: + * + * - It is not a cancellation point, and + * - It does not modify the errno value. + * + * Input Parameters: + * sem - Semaphore descriptor. + * + * 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. + * Possible returned errors: + * + ****************************************************************************/ + +void nxsem_protect_post(FAR sem_t *sem) +{ + if (sem->saved > 0) + { + nxsched_set_priority(this_task(), sem->saved); + sem->saved = 0; + } +} + +#endif /* CONFIG_PRIORITY_PROTECT */ diff --git a/sched/semaphore/sem_trywait.c b/sched/semaphore/sem_trywait.c index df95efcdbb4c2..5201c0fc2688a 100644 --- a/sched/semaphore/sem_trywait.c +++ b/sched/semaphore/sem_trywait.c @@ -88,6 +88,13 @@ int nxsem_trywait(FAR sem_t *sem) { /* It is, let the task take the semaphore */ + ret = nxsem_protect_wait(sem); + if (ret < 0) + { + leave_critical_section(flags); + return ret; + } + sem->semcount--; nxsem_add_holder(sem); rtcb->waitobj = NULL; diff --git a/sched/semaphore/sem_wait.c b/sched/semaphore/sem_wait.c index bec292be5ccaf..b44fade3cd768 100644 --- a/sched/semaphore/sem_wait.c +++ b/sched/semaphore/sem_wait.c @@ -94,21 +94,12 @@ int nxsem_wait(FAR sem_t *sem) { /* It is, let the task take the semaphore. */ -#ifdef CONFIG_PRIORITY_PROTECT - if ((sem->flags & SEM_PRIO_MASK) == SEM_PRIO_PROTECT) + ret = nxsem_protect_wait(sem); + if (ret < 0) { - if (rtcb->sched_priority <= sem->ceiling) - { - sem->saved = rtcb->sched_priority; - rtcb->sched_priority = sem->ceiling; - } - else - { - leave_critical_section_nonirq(flags); - return -EINVAL; - } + leave_critical_section_nonirq(flags); + return ret; } -#endif sem->semcount--; nxsem_add_holder(sem); diff --git a/sched/semaphore/semaphore.h b/sched/semaphore/semaphore.h index 7a24f5e696a7f..529f246e29824 100644 --- a/sched/semaphore/semaphore.h +++ b/sched/semaphore/semaphore.h @@ -61,7 +61,7 @@ void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode); void nxsem_timeout(wdparm_t pid); -/* Recover semaphore resources with a task or thread is destroyed */ +/* Recover semaphore resources with a task or thread is destroyed */ void nxsem_recover(FAR struct tcb_s *tcb); @@ -91,6 +91,16 @@ void nxsem_release_all(FAR struct tcb_s *stcb); # define nxsem_release_all(stcb) #endif +/* Special logic needed only by priority protect */ + +#ifdef CONFIG_PRIORITY_PROTECT +int nxsem_protect_wait(FAR sem_t *sem); +void nxsem_protect_post(FAR sem_t *sem); +#else +# define nxsem_protect_wait(sem) 0 +# define nxsem_protect_post(sem) +#endif + #undef EXTERN #ifdef __cplusplus }