Skip to content

Commit 669eda9

Browse files
authored
Merge pull request #341 from niklas-arm/fix/atomic_thread_switch
Wrap thread_switch in an atomic section
2 parents fbb50fe + 286f991 commit 669eda9

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

core/system/src/export_table.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@
2727
#include "halt.h"
2828
#include "vmpu.h"
2929

30+
/* Wrap a function call into an atomic section with IRQ state restoration. */
31+
#define atomic_call_wrapper(fn) { \
32+
uint32_t primask = __get_PRIMASK(); \
33+
__disable_irq(); \
34+
fn; \
35+
if (!(primask & 0x01)) { \
36+
__enable_irq(); \
37+
} \
38+
}
39+
3040
/* By default a maximum of 16 threads are allowed. This can only be overridden
3141
* by the porting engineer for the current platform. */
3242
#ifndef UVISOR_EXPORT_TABLE_THREADS_MAX_COUNT
@@ -584,6 +594,18 @@ static void thread_switch(void * c)
584594
}
585595
}
586596

597+
/* uVisor expects all calls to its API to be executed in the highest priority
598+
* interrupt (SVC) since they are not re-entrant.
599+
* If this is not the case, we need to make sure that no other interrupt can
600+
* preempt these calls by wrapping them in an atomic section.
601+
*/
602+
static void thread_switch_atomic(void * c)
603+
{
604+
atomic_call_wrapper(
605+
thread_switch(c)
606+
);
607+
}
608+
587609
static void boxes_init(void)
588610
{
589611
/* Tell uVisor to call the uVisor lib box_init function for each box with
@@ -606,7 +628,7 @@ const TUvisorExportTable __uvisor_export_table = {
606628
.pre_start = boxes_init,
607629
.thread_create = thread_create,
608630
.thread_destroy = thread_destroy,
609-
.thread_switch = thread_switch,
631+
.thread_switch = thread_switch_atomic,
610632
},
611633
.pool = {
612634
.init = uvisor_pool_init,

0 commit comments

Comments
 (0)