Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Thread.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2012 ARM Limited 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00020 * SOFTWARE. 00021 */ 00022 #include "Thread.h" 00023 00024 #include "mbed.h" 00025 #include "rtos_idle.h" 00026 00027 // rt_tid2ptcb is an internal function which we exposed to get TCB for thread id 00028 #undef NULL //Workaround for conflicting macros in rt_TypeDef.h and stdio.h 00029 #include "rt_TypeDef.h" 00030 00031 extern "C" P_TCB rt_tid2ptcb(osThreadId thread_id); 00032 00033 namespace rtos { 00034 00035 void Thread::constructor(osPriority priority, 00036 uint32_t stack_size, unsigned char *stack_pointer) { 00037 _tid = 0; 00038 _dynamic_stack = (stack_pointer == NULL); 00039 00040 #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) 00041 _thread_def.tpriority = priority; 00042 _thread_def.stacksize = stack_size; 00043 _thread_def.stack_pointer = (uint32_t*)stack_pointer; 00044 #endif 00045 } 00046 00047 void Thread::constructor(Callback<void()> task, 00048 osPriority priority, uint32_t stack_size, unsigned char *stack_pointer) { 00049 constructor(priority, stack_size, stack_pointer); 00050 00051 switch (start(task)) { 00052 case osErrorResource: 00053 error("OS ran out of threads!\n"); 00054 break; 00055 case osErrorParameter: 00056 error("Thread already running!\n"); 00057 break; 00058 case osErrorNoMemory: 00059 error("Error allocating the stack memory\n"); 00060 default: 00061 break; 00062 } 00063 } 00064 00065 osStatus Thread::start(Callback<void()> task) { 00066 _mutex.lock(); 00067 00068 if (_tid != 0) { 00069 _mutex.unlock(); 00070 return osErrorParameter; 00071 } 00072 00073 #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) 00074 _thread_def.pthread = Thread::_thunk; 00075 if (_thread_def.stack_pointer == NULL) { 00076 _thread_def.stack_pointer = new uint32_t[_thread_def.stacksize/sizeof(uint32_t)]; 00077 if (_thread_def.stack_pointer == NULL) { 00078 _mutex.unlock(); 00079 return osErrorNoMemory; 00080 } 00081 } 00082 00083 //Fill the stack with a magic word for maximum usage checking 00084 for (uint32_t i = 0; i < (_thread_def.stacksize / sizeof(uint32_t)); i++) { 00085 _thread_def.stack_pointer[i] = 0xE25A2EA5; 00086 } 00087 #endif 00088 _task = task; 00089 _tid = osThreadCreate(&_thread_def, this); 00090 if (_tid == NULL) { 00091 if (_dynamic_stack) delete[] (_thread_def.stack_pointer); 00092 _mutex.unlock(); 00093 return osErrorResource; 00094 } 00095 00096 _mutex.unlock(); 00097 return osOK; 00098 } 00099 00100 osStatus Thread::terminate() { 00101 osStatus ret; 00102 _mutex.lock(); 00103 00104 // Set the Thread's tid to NULL and 00105 // release the semaphore before terminating 00106 // since this thread could be terminating itself 00107 osThreadId local_id = _tid; 00108 _join_sem.release(); 00109 _tid = (osThreadId)NULL; 00110 00111 ret = osThreadTerminate(local_id); 00112 00113 _mutex.unlock(); 00114 return ret; 00115 } 00116 00117 osStatus Thread::join() { 00118 int32_t ret = _join_sem.wait(); 00119 if (ret < 0) { 00120 return osErrorOS; 00121 } 00122 00123 // The semaphore has been released so this thread is being 00124 // terminated or has been terminated. Once the mutex has 00125 // been locked it is ensured that the thread is deleted. 00126 _mutex.lock(); 00127 MBED_ASSERT(NULL == _tid); 00128 _mutex.unlock(); 00129 00130 // Release sem so any other threads joining this thread wake up 00131 _join_sem.release(); 00132 return osOK; 00133 } 00134 00135 osStatus Thread::set_priority(osPriority priority) { 00136 osStatus ret; 00137 _mutex.lock(); 00138 00139 ret = osThreadSetPriority(_tid, priority); 00140 00141 _mutex.unlock(); 00142 return ret; 00143 } 00144 00145 osPriority Thread::get_priority() { 00146 osPriority ret; 00147 _mutex.lock(); 00148 00149 ret = osThreadGetPriority(_tid); 00150 00151 _mutex.unlock(); 00152 return ret; 00153 } 00154 00155 int32_t Thread::signal_set(int32_t signals) { 00156 // osSignalSet is thread safe as long as the underlying 00157 // thread does not get terminated or return from main 00158 return osSignalSet(_tid, signals); 00159 } 00160 00161 int32_t Thread::signal_clr(int32_t signals) { 00162 // osSignalClear is thread safe as long as the underlying 00163 // thread does not get terminated or return from main 00164 return osSignalClear(_tid, signals); 00165 } 00166 00167 Thread::State Thread::get_state() { 00168 #if !defined(__MBED_CMSIS_RTOS_CA9) && !defined(__MBED_CMSIS_RTOS_CM) 00169 #ifdef CMSIS_OS_RTX 00170 State status = Deleted; 00171 _mutex.lock(); 00172 00173 if (_tid != NULL) { 00174 status = (State)_thread_def.tcb.state; 00175 } 00176 00177 _mutex.unlock(); 00178 return status; 00179 #endif 00180 #else 00181 State status = Deleted; 00182 _mutex.lock(); 00183 00184 if (_tid != NULL) { 00185 status = (State)osThreadGetState(_tid); 00186 } 00187 00188 _mutex.unlock(); 00189 return status; 00190 #endif 00191 } 00192 00193 uint32_t Thread::stack_size() { 00194 #ifndef __MBED_CMSIS_RTOS_CA9 00195 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00196 uint32_t size = 0; 00197 _mutex.lock(); 00198 00199 if (_tid != NULL) { 00200 size = _thread_def.tcb.priv_stack; 00201 } 00202 00203 _mutex.unlock(); 00204 return size; 00205 #else 00206 uint32_t size = 0; 00207 _mutex.lock(); 00208 00209 if (_tid != NULL) { 00210 P_TCB tcb = rt_tid2ptcb(_tid); 00211 size = tcb->priv_stack; 00212 } 00213 00214 _mutex.unlock(); 00215 return size; 00216 #endif 00217 #else 00218 return 0; 00219 #endif 00220 } 00221 00222 uint32_t Thread::free_stack() { 00223 #ifndef __MBED_CMSIS_RTOS_CA9 00224 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00225 uint32_t size = 0; 00226 _mutex.lock(); 00227 00228 if (_tid != NULL) { 00229 uint32_t bottom = (uint32_t)_thread_def.tcb.stack; 00230 size = _thread_def.tcb.tsk_stack - bottom; 00231 } 00232 00233 _mutex.unlock(); 00234 return size; 00235 #else 00236 uint32_t size = 0; 00237 _mutex.lock(); 00238 00239 if (_tid != NULL) { 00240 P_TCB tcb = rt_tid2ptcb(_tid); 00241 uint32_t bottom = (uint32_t)tcb->stack; 00242 size = tcb->tsk_stack - bottom; 00243 } 00244 00245 _mutex.unlock(); 00246 return size; 00247 #endif 00248 #else 00249 return 0; 00250 #endif 00251 } 00252 00253 uint32_t Thread::used_stack() { 00254 #ifndef __MBED_CMSIS_RTOS_CA9 00255 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00256 uint32_t size = 0; 00257 _mutex.lock(); 00258 00259 if (_tid != NULL) { 00260 uint32_t top = (uint32_t)_thread_def.tcb.stack + _thread_def.tcb.priv_stack; 00261 size = top - _thread_def.tcb.tsk_stack; 00262 } 00263 00264 _mutex.unlock(); 00265 return size; 00266 #else 00267 uint32_t size = 0; 00268 _mutex.lock(); 00269 00270 if (_tid != NULL) { 00271 P_TCB tcb = rt_tid2ptcb(_tid); 00272 uint32_t top = (uint32_t)tcb->stack + tcb->priv_stack; 00273 size = top - tcb->tsk_stack; 00274 } 00275 00276 _mutex.unlock(); 00277 return size; 00278 #endif 00279 #else 00280 return 0; 00281 #endif 00282 } 00283 00284 uint32_t Thread::max_stack() { 00285 #ifndef __MBED_CMSIS_RTOS_CA9 00286 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00287 uint32_t size = 0; 00288 _mutex.lock(); 00289 00290 if (_tid != NULL) { 00291 uint32_t high_mark = 0; 00292 while (_thread_def.tcb.stack[high_mark] == 0xE25A2EA5) 00293 high_mark++; 00294 size = _thread_def.tcb.priv_stack - (high_mark * 4); 00295 } 00296 00297 _mutex.unlock(); 00298 return size; 00299 #else 00300 uint32_t size = 0; 00301 _mutex.lock(); 00302 00303 if (_tid != NULL) { 00304 P_TCB tcb = rt_tid2ptcb(_tid); 00305 uint32_t high_mark = 0; 00306 while (tcb->stack[high_mark] == 0xE25A2EA5) 00307 high_mark++; 00308 size = tcb->priv_stack - (high_mark * 4); 00309 } 00310 00311 _mutex.unlock(); 00312 return size; 00313 #endif 00314 #else 00315 return 0; 00316 #endif 00317 } 00318 00319 osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) { 00320 return osSignalWait(signals, millisec); 00321 } 00322 00323 osStatus Thread::wait(uint32_t millisec) { 00324 return osDelay(millisec); 00325 } 00326 00327 osStatus Thread::yield() { 00328 return osThreadYield(); 00329 } 00330 00331 osThreadId Thread::gettid() { 00332 return osThreadGetId(); 00333 } 00334 00335 void Thread::attach_idle_hook(void (*fptr)(void)) { 00336 rtos_attach_idle_hook(fptr); 00337 } 00338 00339 Thread::~Thread() { 00340 // terminate is thread safe 00341 terminate(); 00342 #ifdef __MBED_CMSIS_RTOS_CM 00343 if (_dynamic_stack) { 00344 delete[] (_thread_def.stack_pointer); 00345 } 00346 #endif 00347 } 00348 00349 void Thread::_thunk(const void * thread_ptr) 00350 { 00351 Thread *t = (Thread*)thread_ptr; 00352 t->_task(); 00353 t->_mutex.lock(); 00354 t->_tid = (osThreadId)NULL; 00355 t->_join_sem.release(); 00356 // rtos will release the mutex automatically 00357 } 00358 00359 }
Generated on Tue Jul 12 2022 13:05:44 by
1.7.2