From b9957f0957ffc36edd194730695d20d6aa658bbc Mon Sep 17 00:00:00 2001 From: Chris Copeland Date: Sun, 31 Mar 2024 22:42:54 -0700 Subject: [PATCH] remove rt_mutex_holder, avoid priority donation to an interrupt --- include/rt/mutex.h | 7 ------- src/rt.c | 15 ++++++++++----- src/rwlock.c | 6 +++++- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/include/rt/mutex.h b/include/rt/mutex.h index 8d1e9e5..b233c1e 100644 --- a/include/rt/mutex.h +++ b/include/rt/mutex.h @@ -50,13 +50,6 @@ struct rt_task; #define RT_MUTEX_RECURSIVE(name) \ struct rt_mutex name = RT_MUTEX_INIT_RECURSIVE(name) -static inline struct rt_task *rt_mutex_holder(const struct rt_mutex *mutex) -{ - return (struct rt_task *)(rt_atomic_load(&mutex->holder, - RT_ATOMIC_RELAXED) & - RT_MUTEX_HOLDER_MASK); -} - #ifdef __cplusplus } #endif diff --git a/src/rt.c b/src/rt.c index 768dc1c..a26930c 100644 --- a/src/rt.c +++ b/src/rt.c @@ -357,23 +357,28 @@ static void mutex_donate(struct rt_mutex *mutex) { do { - struct rt_task *holder = rt_mutex_holder(mutex); - if (holder == NULL) + uintptr_t holder = rt_atomic_load(&mutex->holder, RT_ATOMIC_RELAXED); + if ((holder == RT_MUTEX_UNLOCKED) || + (holder == RT_MUTEX_HOLDER_INTERRUPT)) { - // If the mutex is not held then no donation is needed. + /* If the mutex is not held or held by an interrupt, then no + * donation is needed. */ return; } + struct rt_task *const task = + (struct rt_task *)(holder & RT_MUTEX_HOLDER_MASK); + if (!rt_list_is_empty(&mutex->wait_list)) { // Re-sort the mutex in the holder's mutex list. rt_list_remove(&mutex->list); - insert_mutex_by_priority(&holder->mutex_list, mutex); + insert_mutex_by_priority(&task->mutex_list, mutex); } /* Update the holder's priority and get the next mutex to calculate * donation on, if any. */ - mutex = task_donate(holder); + mutex = task_donate(task); } while (mutex != NULL); } diff --git a/src/rwlock.c b/src/rwlock.c index c3f20ab..330fbed 100644 --- a/src/rwlock.c +++ b/src/rwlock.c @@ -215,7 +215,11 @@ void rt_rwlock_wrunlock(struct rt_rwlock *lock) void rt_rwlock_unlock(struct rt_rwlock *lock) { - if (rt_mutex_holder(&lock->mutex) == rt_task_self()) + const uintptr_t holder = + rt_atomic_load(&lock->mutex.holder, RT_ATOMIC_RELAXED) & + RT_MUTEX_HOLDER_MASK; + if ((holder == (uintptr_t)rt_task_self()) || + (holder == RT_MUTEX_HOLDER_INTERRUPT)) { rt_rwlock_wrunlock(lock); }