@@ -63,16 +63,21 @@ void Thread::constructor(Callback<void()> task,
6363}
6464
6565osStatus Thread::start (Callback<void ()> task) {
66+ _mutex.lock ();
67+
6668 if (_tid != 0 ) {
69+ _mutex.unlock ();
6770 return osErrorParameter;
6871 }
6972
7073#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 ;
7275 if (_thread_def.stack_pointer == NULL ) {
7376 _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 ();
7579 return osErrorNoMemory;
80+ }
7681 }
7782
7883 // Fill the stack with a magic word for maximum usage checking
@@ -81,67 +86,118 @@ osStatus Thread::start(Callback<void()> task) {
8186 }
8287#endif
8388 _task = task;
84- _tid = osThreadCreate (&_thread_def, &_task );
89+ _tid = osThreadCreate (&_thread_def, this );
8590 if (_tid == NULL ) {
8691 if (_dynamic_stack) delete[] (_thread_def.stack_pointer );
92+ _mutex.unlock ();
8793 return osErrorResource;
8894 }
95+
96+ _mutex.unlock ();
8997 return osOK;
9098}
9199
92100osStatus Thread::terminate () {
93- return osThreadTerminate (_tid);
101+ osStatus ret;
102+ _mutex.lock ();
103+
104+ ret = osThreadTerminate (_tid);
105+
106+ _mutex.unlock ();
107+ return ret;
94108}
95109
96110osStatus 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;
107114 }
115+ // Release sem so any other threads joining this thread wake up
116+ _join_sem.release ();
117+ return osOK;
108118}
109119
110120osStatus 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;
112128}
113129
114130osPriority 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;
116138}
117139
118140int32_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
119143 return osSignalSet (_tid, signals);
120144}
121145
122146int32_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
123149 return osSignalClear (_tid, signals);
124150}
125151
126152Thread::State Thread::get_state () {
127153#if !defined(__MBED_CMSIS_RTOS_CA9) && !defined(__MBED_CMSIS_RTOS_CM)
128154#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;
130164#endif
131165#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;
135175#endif
136176}
137177
138178uint32_t Thread::stack_size () {
139179#ifndef __MBED_CMSIS_RTOS_CA9
140180#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;
142190#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;
145201#endif
146202#else
147203 return 0 ;
@@ -151,12 +207,28 @@ uint32_t Thread::stack_size() {
151207uint32_t Thread::free_stack () {
152208#ifndef __MBED_CMSIS_RTOS_CA9
153209#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;
156220#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;
160232#endif
161233#else
162234 return 0 ;
@@ -166,12 +238,28 @@ uint32_t Thread::free_stack() {
166238uint32_t Thread::used_stack () {
167239#ifndef __MBED_CMSIS_RTOS_CA9
168240#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;
171251#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;
175263#endif
176264#else
177265 return 0 ;
@@ -181,16 +269,32 @@ uint32_t Thread::used_stack() {
181269uint32_t Thread::max_stack () {
182270#ifndef __MBED_CMSIS_RTOS_CA9
183271#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;
188284#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;
194298#endif
195299#else
196300 return 0 ;
@@ -218,6 +322,7 @@ void Thread::attach_idle_hook(void (*fptr)(void)) {
218322}
219323
220324Thread::~Thread () {
325+ // terminate is thread safe
221326 terminate ();
222327#ifdef __MBED_CMSIS_RTOS_CM
223328 if (_dynamic_stack) {
@@ -226,4 +331,14 @@ Thread::~Thread() {
226331#endif
227332}
228333
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+
229344}
0 commit comments