4343
4444static pendsv_dispatch_t pendsv_dispatch_table [PENDSV_DISPATCH_NUM_SLOTS ];
4545
46+ static inline void pendsv_resume_run_dispatch (void );
47+
4648void PendSV_Handler (void );
4749
48- // Using the nowait variant here as softtimer updates PendSV from the loop of mp_wfe_or_timeout(),
49- // where we don't want the CPU event bit to be set.
50+ #if MICROPY_PY_THREAD
51+
52+ // Important to use a 'nowait' mutex here as softtimer updates PendSV from the
53+ // loop of mp_wfe_or_timeout(), where we don't want the CPU event bit to be set.
5054static mp_thread_recursive_mutex_t pendsv_mutex ;
5155
5256void pendsv_init (void ) {
@@ -62,7 +66,40 @@ void pendsv_suspend(void) {
6266
6367void pendsv_resume (void ) {
6468 mp_thread_recursive_mutex_unlock (& pendsv_mutex );
69+ pendsv_resume_run_dispatch ();
70+ }
71+
72+ static inline int pendsv_suspend_count (void ) {
73+ return pendsv_mutex .mutex .enter_count ;
74+ }
75+
76+ #else
77+
78+ // Without threads we don't include any pico-sdk mutex in the build,
79+ // but also we don't need to worry about cross-thread contention (or
80+ // races with interrupts that update this counter).
81+ static int pendsv_lock ;
82+
83+ void pendsv_init (void ) {
84+ }
85+
86+ void pendsv_suspend (void ) {
87+ pendsv_lock ++ ;
88+ }
89+
90+ void pendsv_resume (void ) {
91+ assert (pendsv_lock > 0 );
92+ pendsv_lock -- ;
93+ pendsv_resume_run_dispatch ();
94+ }
6595
96+ static inline int pendsv_suspend_count (void ) {
97+ return pendsv_lock ;
98+ }
99+
100+ #endif
101+
102+ static inline void pendsv_resume_run_dispatch (void ) {
66103 // Run pendsv if needed. Find an entry with a dispatch and call pendsv dispatch
67104 // with it. If pendsv runs it will service all slots.
68105 int count = PENDSV_DISPATCH_NUM_SLOTS ;
@@ -76,7 +113,7 @@ void pendsv_resume(void) {
76113
77114void pendsv_schedule_dispatch (size_t slot , pendsv_dispatch_t f ) {
78115 pendsv_dispatch_table [slot ] = f ;
79- if (pendsv_mutex . mutex . enter_count == 0 ) {
116+ if (pendsv_suspend_count () == 0 ) {
80117 #if PICO_ARM
81118 // There is a race here where other core calls pendsv_suspend() before
82119 // ISR can execute, but dispatch will happen later when other core
@@ -97,13 +134,17 @@ void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) {
97134// PendSV interrupt handler to perform background processing.
98135void PendSV_Handler (void ) {
99136
137+ #if MICROPY_PY_THREAD
100138 if (!mp_thread_recursive_mutex_lock (& pendsv_mutex , 0 )) {
101139 // Failure here means core 1 holds pendsv_mutex. ISR will
102140 // run again after core 1 calls pendsv_resume().
103141 return ;
104142 }
105143 // Core 0 should not already have locked pendsv_mutex
106144 assert (pendsv_mutex .mutex .enter_count == 1 );
145+ #else
146+ assert (pendsv_suspend_count () == 0 );
147+ #endif
107148
108149 #if MICROPY_PY_NETWORK_CYW43
109150 CYW43_STAT_INC (PENDSV_RUN_COUNT );
@@ -117,5 +158,7 @@ void PendSV_Handler(void) {
117158 }
118159 }
119160
161+ #if MICROPY_PY_THREAD
120162 mp_thread_recursive_mutex_unlock (& pendsv_mutex );
163+ #endif
121164}
0 commit comments