From f041ae5ca8d3e48433f42c9e4389c8585d3a3485 Mon Sep 17 00:00:00 2001 From: hujun5 Date: Thu, 24 Oct 2024 14:20:28 +0800 Subject: [PATCH] pthread: remove enter_critical_section in pthread_mutex reason: We would like to replace the critical section with a small lock. Signed-off-by: hujun5 --- include/nuttx/sched.h | 5 ++ sched/init/nx_start.c | 4 + sched/pthread/CMakeLists.txt | 3 +- sched/pthread/Make.defs | 2 +- sched/pthread/pthread_create.c | 4 + sched/pthread/pthread_mutex.c | 54 +++++++++++++- sched/pthread/pthread_mutexinconsistent.c | 89 ----------------------- sched/task/task_fork.c | 4 + sched/task/task_init.c | 4 + 9 files changed, 73 insertions(+), 96 deletions(-) delete mode 100644 sched/pthread/pthread_mutexinconsistent.c diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index e2507f9938..68284461a6 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -48,6 +48,7 @@ #include #include #include +#include #include @@ -737,6 +738,10 @@ struct tcb_s size_t level_deepest; size_t level; #endif + +#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE + spinlock_t mutex_lock; +#endif }; /* struct task_tcb_s ********************************************************/ diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c index 01ba4df823..5602caf9b0 100644 --- a/sched/init/nx_start.c +++ b/sched/init/nx_start.c @@ -469,6 +469,10 @@ static void idle_group_initialize(void) nxtask_joininit(tcb); +#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE + spin_lock_init(&tcb->mutex_lock); +#endif + #ifdef CONFIG_SMP /* Create a stack for all CPU IDLE threads (except CPU0 which already * has a stack). diff --git a/sched/pthread/CMakeLists.txt b/sched/pthread/CMakeLists.txt index 2ccf5d358f..6921bfe6f6 100644 --- a/sched/pthread/CMakeLists.txt +++ b/sched/pthread/CMakeLists.txt @@ -46,8 +46,7 @@ if(NOT CONFIG_DISABLE_PTHREAD) pthread_setschedprio.c) if(NOT CONFIG_PTHREAD_MUTEX_UNSAFE) - list(APPEND SRCS pthread_mutex.c pthread_mutexconsistent.c - pthread_mutexinconsistent.c) + list(APPEND SRCS pthread_mutex.c pthread_mutexconsistent.c) endif() if(CONFIG_SMP) diff --git a/sched/pthread/Make.defs b/sched/pthread/Make.defs index bff1a88da1..4a696068fa 100644 --- a/sched/pthread/Make.defs +++ b/sched/pthread/Make.defs @@ -32,7 +32,7 @@ CSRCS += pthread_completejoin.c pthread_findjoininfo.c CSRCS += pthread_release.c pthread_setschedprio.c ifneq ($(CONFIG_PTHREAD_MUTEX_UNSAFE),y) -CSRCS += pthread_mutex.c pthread_mutexconsistent.c pthread_mutexinconsistent.c +CSRCS += pthread_mutex.c pthread_mutexconsistent.c endif ifeq ($(CONFIG_SMP),y) diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c index e9ff4ef88c..80d74fec50 100644 --- a/sched/pthread/pthread_create.c +++ b/sched/pthread/pthread_create.c @@ -222,6 +222,10 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, nxtask_joininit(&ptcb->cmn); +#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE + spin_lock_init(&ptcb->cmn.mutex_lock); +#endif + /* Bind the parent's group to the new TCB (we have not yet joined the * group). */ diff --git a/sched/pthread/pthread_mutex.c b/sched/pthread/pthread_mutex.c index 36eae29a08..24a063908f 100644 --- a/sched/pthread/pthread_mutex.c +++ b/sched/pthread/pthread_mutex.c @@ -65,10 +65,10 @@ static void pthread_mutex_add(FAR struct pthread_mutex_s *mutex) /* Add the mutex to the list of mutexes held by this pthread */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&rtcb->mutex_lock); mutex->flink = rtcb->mhead; rtcb->mhead = mutex; - leave_critical_section(flags); + spin_unlock_irqrestore(&rtcb->mutex_lock, flags); } /**************************************************************************** @@ -92,7 +92,7 @@ static void pthread_mutex_remove(FAR struct pthread_mutex_s *mutex) FAR struct pthread_mutex_s *prev; irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&rtcb->mutex_lock); /* Remove the mutex from the list of mutexes held by this task */ @@ -118,7 +118,7 @@ static void pthread_mutex_remove(FAR struct pthread_mutex_s *mutex) } mutex->flink = NULL; - leave_critical_section(flags); + spin_unlock_irqrestore(&rtcb->mutex_lock, flags); } /**************************************************************************** @@ -346,3 +346,49 @@ int pthread_mutex_restorelock(FAR struct pthread_mutex_s *mutex, return ret; } + +/**************************************************************************** + * Name: pthread_mutex_inconsistent + * + * Description: + * This function is called when a pthread is terminated via either + * pthread_exit() or pthread_cancel(). It will check for any mutexes + * held by exitting thread. It will mark them as inconsistent and + * then wake up the highest priority waiter for the mutex. That + * instance of pthread_mutex_lock() will then return EOWNERDEAD. + * + * Input Parameters: + * tcb -- a reference to the TCB of the exitting pthread. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void pthread_mutex_inconsistent(FAR struct tcb_s *tcb) +{ + FAR struct pthread_mutex_s *mutex; + irqstate_t flags; + + DEBUGASSERT(tcb != NULL); + + flags = spin_lock_irqsave(&tcb->mutex_lock); + + /* Remove and process each mutex held by this task */ + + while (tcb->mhead != NULL) + { + /* Remove the mutex from the TCB list */ + + mutex = tcb->mhead; + tcb->mhead = mutex->flink; + mutex->flink = NULL; + + /* Mark the mutex as INCONSISTENT and wake up any waiting thread */ + + mutex->flags |= _PTHREAD_MFLAGS_INCONSISTENT; + mutex_unlock(&mutex->mutex); + } + + spin_unlock_irqrestore(&tcb->mutex_lock, flags); +} diff --git a/sched/pthread/pthread_mutexinconsistent.c b/sched/pthread/pthread_mutexinconsistent.c deleted file mode 100644 index c946edfb2e..0000000000 --- a/sched/pthread/pthread_mutexinconsistent.c +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** - * sched/pthread/pthread_mutexinconsistent.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 -#include -#include - -#include -#include - -#include "pthread/pthread.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: pthread_mutex_inconsistent - * - * Description: - * This function is called when a pthread is terminated via either - * pthread_exit() or pthread_cancel(). It will check for any mutexes - * held by exitting thread. It will mark them as inconsistent and - * then wake up the highest priority waiter for the mutex. That - * instance of pthread_mutex_lock() will then return EOWNERDEAD. - * - * Input Parameters: - * tcb -- a reference to the TCB of the exitting pthread. - * - * Returned Value: - * None. - * - ****************************************************************************/ - -void pthread_mutex_inconsistent(FAR struct tcb_s *tcb) -{ - FAR struct pthread_mutex_s *mutex; - irqstate_t flags; - - DEBUGASSERT(tcb != NULL); - - sched_lock(); - - /* Remove and process each mutex held by this task */ - - while (tcb->mhead != NULL) - { - /* Remove the mutex from the TCB list */ - - flags = enter_critical_section(); - mutex = tcb->mhead; - tcb->mhead = mutex->flink; - mutex->flink = NULL; - leave_critical_section(flags); - - /* Mark the mutex as INCONSISTENT and wake up any waiting thread */ - - mutex->flags |= _PTHREAD_MFLAGS_INCONSISTENT; - mutex_unlock(&mutex->mutex); - } - - sched_unlock(); -} diff --git a/sched/task/task_fork.c b/sched/task/task_fork.c index 44551f32d4..39dd755f40 100644 --- a/sched/task/task_fork.c +++ b/sched/task/task_fork.c @@ -164,6 +164,10 @@ FAR struct task_tcb_s *nxtask_setup_fork(start_t retaddr) nxtask_joininit(&child->cmn); +#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE + spin_lock_init(&child->cmn.mutex_lock); +#endif + /* Allocate a new task group with the same privileges as the parent */ ret = group_initialize(child, ttype); diff --git a/sched/task/task_init.c b/sched/task/task_init.c index bcf8b30811..7d338f53b2 100644 --- a/sched/task/task_init.c +++ b/sched/task/task_init.c @@ -126,6 +126,10 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, nxtask_joininit(&tcb->cmn); #endif +#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE + spin_lock_init(&tcb->cmn.mutex_lock); +#endif + /* Duplicate the parent tasks environment */ ret = env_dup(tcb->cmn.group, envp);