43
43
44
44
static pendsv_dispatch_t pendsv_dispatch_table [PENDSV_DISPATCH_NUM_SLOTS ];
45
45
46
+ static inline void pendsv_resume_run_dispatch (void );
47
+
46
48
void PendSV_Handler (void );
47
49
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.
50
54
sta
8000
tic mp_thread_recursive_mutex_t pendsv_mutex ;
51
55
52
56
void pendsv_init (void ) {
@@ -62,7 +66,40 @@ void pendsv_suspend(void) {
62
66
63
67
void pendsv_resume (void ) {
64
68
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
+ }
65
95
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 ) {
66
103
// Run pendsv if needed. Find an entry with a dispatch and call pendsv dispatch
67
104
// with it. If pendsv runs it will service all slots.
68
105
int count = PENDSV_DISPATCH_NUM_SLOTS ;
@@ -76,7 +113,7 @@ void pendsv_resume(void) {
76
113
77
114
void pendsv_schedule_dispatch (size_t slot , pendsv_dispatch_t f ) {
78
115
pendsv_dispatch_table [slot ] = f ;
79
- if (pendsv_mutex . mutex . enter_count == 0 ) {
116
+ if (pendsv_suspend_count () == 0 ) {
80
117
#if PICO_ARM
81
118
// There is a race here where other core calls pendsv_suspend() before
82
119
// 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) {
97
134
// PendSV interrupt handler to perform background processing.
98
135
void PendSV_Handler (void ) {
99
136
137
+ #if MICROPY_PY_THREAD
100
138
if (!mp_thread_recursive_mutex_lock (& pendsv_mutex , 0 )) {
101
139
// Failure here means core 1 holds pendsv_mutex. ISR will
102
140
// run again after core 1 calls pendsv_resume().
103
141
return ;
104
142
}
105
143
// Core 0 should not already have locked pendsv_mutex
106
144
assert (pendsv_mutex .mutex .enter_count == 1 );
145
+ #else
146
+ assert (pendsv_suspend_count () == 0 );
147
+ #endif
107
148
108
149
#if MICROPY_PY_NETWORK_CYW43
109
150
CYW43_STAT_INC (PENDSV_RUN_COUNT );
@@ -117,5 +158,7 @@ void PendSV_Handler(void) {
117
158
}
118
159
}
119
160
161
+ #if MICROPY_PY_THREAD
120
162
mp_thread_recursive_mutex_unlock (& pendsv_mutex );
163
+ #endif
121
164
}
0 commit comments