@@ -63,16 +63,21 @@ void Thread::constructor(Callback<void()> task,
63
63
}
64
64
65
65
osStatus Thread::start (Callback<void ()> task) {
66
+ _mutex.lock ();
67
+
66
68
if (_tid != 0 ) {
69
+ _mutex.unlock ();
67
70
return osErrorParameter;
68
71
}
69
72
70
73
#if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM)
71
- _thread_def.pthread = ( void (*)( const void *))Callback< void ()>::thunk ;
74
+ _thread_def.pthread = Thread::_thunk ;
72
75
if (_thread_def.stack_pointer == NULL ) {
73
76
_thread_def.stack_pointer = new uint32_t [_thread_def.stacksize /sizeof (uint32_t )];
74
- if (_thread_def.stack_pointer == NULL )
77
+ if (_thread_def.stack_pointer == NULL ) {
78
+ _mutex.unlock ();
75
79
return osErrorNoMemory;
80
+ }
76
81
}
77
82
78
83
// Fill the stack with a magic word for maximum usage checking
@@ -81,67 +86,118 @@ osStatus Thread::start(Callback<void()> task) {
81
86
}
82
87
#endif
83
88
_task = task;
84
- _tid = osThreadCreate (&_thread_def, &_task );
89
+ _tid = osThreadCreate (&_thread_def, this );
85
90
if (_tid == NULL ) {
86
91
if (_dynamic_stack) delete[] (_thread_def.stack_pointer );
92
+ _mutex.unlock ();
87
93
return osErrorResource;
88
94
}
95
+
96
+ _mutex.unlock ();
89
97
return osOK;
90
98
}
91
99
92
100
osStatus Thread::terminate () {
93
- return osThreadTerminate (_tid);
101
+ osStatus ret;
102
+ _mutex.lock ();
103
+
104
+ ret = osThreadTerminate (_tid);
105
+
106
+ _mutex.unlock ();
107
+ return ret;
94
108
}
95
109
96
110
osStatus Thread::join () {
97
- while (true ) {
98
- uint8_t state = get_state ();
99
- if (state == Thread::Inactive || state == osErrorParameter) {
100
- return osOK;
101
- }
102
-
103
- osStatus status = yield ();
104
- if (status != osOK) {
105
- return status;
106
- }
111
+ int32_t ret = _join_sem.wait ();
112
+ if (ret < 0 ) {
113
+ return osErrorOS;
107
114
}
115
+ // Release sem so any other threads joining this thread wake up
116
+ _join_sem.release ();
117
+ return osOK;
108
118
}
109
119
110
120
osStatus Thread::set_priority (osPriority priority) {
111
- return osThreadSetPriority (_tid, priority);
121
+ osStatus ret;
122
+ _mutex.lock ();
123
+
124
+ ret = osThreadSetPriority (_tid, priority);
125
+
126
+ _mutex.unlock ();
127
+ return ret;
112
128
}
113
129
114
130
osPriority Thread::get_priority () {
115
- return osThreadGetPriority (_tid);
131
+ osPriority ret;
132
+ _mutex.lock ();
133
+
134
+ ret = osThreadGetPriority (_tid);
135
+
136
+ _mutex.unlock ();
137
+ return ret;
116
138
}
117
139
118
140
int32_t Thread::signal_set (int32_t signals) {
141
+ // osSignalSet is thread safe as long as the underlying
142
+ // thread does not get terminated or return from main
119
143
return osSignalSet (_tid, signals);
120
144
}
121
145
122
146
int32_t Thread::signal_clr (int32_t signals) {
147
+ // osSignalClear is thread safe as long as the underlying
148
+ // thread does not get terminated or return from main
123
149
return osSignalClear (_tid, signals);
124
150
}
125
151
126
152
Thread::State Thread::get_state () {
127
153
#if !defined(__MBED_CMSIS_RTOS_CA9) && !defined(__MBED_CMSIS_RTOS_CM)
128
154
#ifdef CMSIS_OS_RTX
129
- return ((State)_thread_def.tcb .state );
155
+ State status = Deleted;
156
+ _mutex.lock ();
157
+
158
+ if (_tid != NULL ) {
159
+ status = (State)_thread_def.tcb .state ;
160
+ }
161
+
162
+ _mutex.unlock ();
163
+ return status;
130
164
#endif
131
165
#else
132
- uint8_t status;
133
- status = osThreadGetState (_tid);
134
- return ((State)status);
166
+ State status = Deleted;
167
+ _mutex.lock ();
168
+
169
+ if (_tid != NULL ) {
170
+ status = (State)osThreadGetState (_tid);
171
+ }
172
+
173
+ _mutex.unlock ();
174
+ return status;
135
175
#endif
136
176
}
137
177
138
178
uint32_t Thread::stack_size () {
139
179
#ifndef __MBED_CMSIS_RTOS_CA9
140
180
#if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
141
- return _thread_def.tcb .priv_stack ;
181
+ uint32_t size = 0 ;
182
+ _mutex.lock ();
183
+
184
+ if (_tid != NULL ) {
185
+ size = _thread_def.tcb .priv_stack ;
186
+ }
187
+
188
+ _mutex.unlock ();
189
+ return size;
142
190
#else
143
- P_TCB tcb = rt_tid2ptcb (_tid);
144
- return tcb->priv_stack ;
191
+ uint32_t size = 0 ;
192
+ _mutex.lock ();
193
+
194
+ if (_tid != NULL ) {
195
+ P_TCB tcb = rt_tid2ptcb (_tid);
196
+ size = tcb->priv_stack ;
197
+ }
198
+
199
+ _mutex.unlock ();
200
+ return size;
145
201
#endif
146
202
#else
147
203
return 0 ;
@@ -151,12 +207,28 @@ uint32_t Thread::stack_size() {
151
207
uint32_t Thread::free_stack () {
152
208
#ifndef __MBED_CMSIS_RTOS_CA9
153
209
#if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
154
- uint32_t bottom = (uint32_t )_thread_def.tcb .stack ;
155
- return _thread_def.tcb .tsk_stack - bottom;
210
+ uint32_t size = 0 ;
211
+ _mutex.lock ();
212
+
213
+ if (_tid != NULL ) {
214
+ uint32_t bottom = (uint32_t )_thread_def.tcb .stack ;
215
+ size = _thread_def.tcb .tsk_stack - bottom;
216
+ }
217
+
218
+ _mutex.unlock ();
219
+ return size;
156
220
#else
157
- P_TCB tcb = rt_tid2ptcb (_tid);
158
- uint32_t bottom = (uint32_t )tcb->stack ;
159
- return tcb->tsk_stack - bottom;
221
+ uint32_t size = 0 ;
222
+ _mutex.lock ();
223
+
224
+ if (_tid != NULL ) {
225
+ P_TCB tcb = rt_tid2ptcb (_tid);
226
+ uint32_t bottom = (uint32_t )tcb->stack ;
227
+ size = tcb->tsk_stack - bottom;
228
+ }
229
+
230
+ _mutex.unlock ();
231
+ return size;
160
232
#endif
161
233
#else
162
234
return 0 ;
@@ -166,12 +238,28 @@ uint32_t Thread::free_stack() {
166
238
uint32_t Thread::used_stack () {
167
239
#ifndef __MBED_CMSIS_RTOS_CA9
168
240
#if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
169
- uint32_t top = (uint32_t )_thread_def.tcb .stack + _thread_def.tcb .priv_stack ;
170
- return top - _thread_def.tcb .tsk_stack ;
241
+ uint32_t size = 0 ;
242
+ _mutex.lock ();
243
+
244
+ if (_tid != NULL ) {
245
+ uint32_t top = (uint32_t )_thread_def.tcb .stack + _thread_def.tcb .priv_stack ;
246
+ size = top - _thread_def.tcb .tsk_stack ;
247
+ }
248
+
249
+ _mutex.unlock ();
250
+ return size;
171
251
#else
172
- P_TCB tcb = rt_tid2ptcb (_tid);
173
- uint32_t top = (uint32_t )tcb->stack + tcb->priv_stack ;
174
- return top - tcb->tsk_stack ;
252
+ uint32_t size = 0 ;
253
+ _mutex.lock ();
254
+
255
+ if (_tid != NULL ) {
256
+ P_TCB tcb = rt_tid2ptcb (_tid);
257
+ uint32_t top = (uint32_t )tcb->stack + tcb->priv_stack ;
258
+ size = top - tcb->tsk_stack ;
259
+ }
260
+
261
+ _mutex.unlock ();
262
+ return size;
175
263
#endif
176
264
#else
177
265
return 0 ;
@@ -181,16 +269,32 @@ uint32_t Thread::used_stack() {
181
269
uint32_t Thread::max_stack () {
182
270
#ifndef __MBED_CMSIS_RTOS_CA9
183
271
#if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
184
- uint32_t high_mark = 0 ;
185
- while (_thread_def.tcb .stack [high_mark] == 0xE25A2EA5 )
186
- high_mark++;
187
- return _thread_def.tcb .priv_stack - (high_mark * 4 );
272
+ uint32_t size = 0 ;
273
+ _mutex.lock ();
274
+
275
+ if (_tid != NULL ) {
276
+ uint32_t high_mark = 0 ;
277
+ while (_thread_def.tcb .stack [high_mark] == 0xE25A2EA5 )
278
+ high_mark++;
279
+ size = _thread_def.tcb .priv_stack - (high_mark * 4 );
280
+ }
281
+
282
+ _mutex.unlock ();
283
+ return size;
188
284
#else
189
- P_TCB tcb = rt_tid2ptcb (_tid);
190
- uint32_t high_mark = 0 ;
191
- while (tcb->stack [high_mark] == 0xE25A2EA5 )
192
- high_mark++;
193
- return tcb->priv_stack - (high_mark * 4 );
285
+ uint32_t size = 0 ;
286
+ _mutex.lock ();
287
+
288
+ if (_tid != NULL ) {
289
+ P_TCB tcb = rt_tid2ptcb (_tid);
290
+ uint32_t high_mark = 0 ;
291
+ while (tcb->stack [high_mark] == 0xE25A2EA5 )
292
+ high_mark++;
293
+ size = tcb->priv_stack - (high_mark * 4 );
294
+ }
295
+
296
+ _mutex.unlock ();
297
+ return size;
194
298
#endif
195
299
#else
196
300
return 0 ;
@@ -218,6 +322,7 @@ void Thread::attach_idle_hook(void (*fptr)(void)) {
218
322
}
219
323
220
324
Thread::~Thread () {
325
+ // terminate is thread safe
221
326
terminate ();
222
327
#ifdef __MBED_CMSIS_RTOS_CM
223
328
if (_dynamic_stack) {
@@ -226,4 +331,14 @@ Thread::~Thread() {
226
331
#endif
227
332
}
228
333
334
+ void Thread::_thunk (const void * thread_ptr)
335
+ {
336
+ Thread *t = (Thread*)thread_ptr;
337
+ t->_task ();
338
+ t->_mutex .lock ();
339
+ t->_tid = (osThreadId)NULL ;
340
+ t->_join_sem .release ();
341
+ // rtos will release the mutex automatically
342
+ }
343
+
229
344
}
0 commit comments