diff --git a/core/arch/arm/include/kernel/thread.h b/core/arch/arm/include/kernel/thread.h index d9bf4f936ad..defc64b74d4 100644 --- a/core/arch/arm/include/kernel/thread.h +++ b/core/arch/arm/include/kernel/thread.h @@ -497,6 +497,8 @@ vaddr_t thread_stack_start(void); /* Returns the stack size for the current thread */ size_t thread_stack_size(void); +bool thread_is_in_normal_mode(void); + /* * Adds a mutex to the list of held mutexes for current thread * Requires foreign interrupts to be disabled. diff --git a/core/arch/arm/kernel/mutex.c b/core/arch/arm/kernel/mutex.c index 6d3cd0ceca2..0469356758d 100644 --- a/core/arch/arm/kernel/mutex.c +++ b/core/arch/arm/kernel/mutex.c @@ -40,6 +40,7 @@ static void __mutex_lock(struct mutex *m, const char *fname, int lineno) { assert_have_no_spinlock(); assert(thread_get_id_may_fail() != -1); + assert(thread_is_in_normal_mode()); while (true) { uint32_t old_itr_status; diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c index 2a9b819b57f..2f6955412c7 100644 --- a/core/arch/arm/kernel/thread.c +++ b/core/arch/arm/kernel/thread.c @@ -642,6 +642,28 @@ size_t thread_stack_size(void) return STACK_THREAD_SIZE; } +#ifdef ARM32 +bool thread_is_in_normal_mode(void) +{ + return (read_cpsr() & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_SVC; +} +#endif + +#ifdef ARM64 +bool thread_is_in_normal_mode(void) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + struct thread_core_local *l = thread_get_core_local(); + bool ret; + + /* If any bit in l->flags is set we're handling some exception. */ + ret = !l->flags; + thread_unmask_exceptions(exceptions); + + return ret; +} +#endif + void thread_state_free(void) { struct thread_core_local *l = thread_get_core_local();