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.
Fork of mbed-rtos by
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 ret = osThreadTerminate(_tid); 00105 _tid = (osThreadId)NULL; 00106 00107 // Wake threads joining the terminated thread 00108 _join_sem.release(); 00109 00110 _mutex.unlock(); 00111 return ret; 00112 } 00113 00114 osStatus Thread::join() { 00115 int32_t ret = _join_sem.wait(); 00116 if (ret < 0) { 00117 return osErrorOS; 00118 } 00119 // Release sem so any other threads joining this thread wake up 00120 _join_sem.release(); 00121 return osOK; 00122 } 00123 00124 osStatus Thread::set_priority(osPriority priority) { 00125 osStatus ret; 00126 _mutex.lock(); 00127 00128 ret = osThreadSetPriority(_tid, priority); 00129 00130 _mutex.unlock(); 00131 return ret; 00132 } 00133 00134 osPriority Thread::get_priority() { 00135 osPriority ret; 00136 _mutex.lock(); 00137 00138 ret = osThreadGetPriority(_tid); 00139 00140 _mutex.unlock(); 00141 return ret; 00142 } 00143 00144 int32_t Thread::signal_set(int32_t signals) { 00145 // osSignalSet is thread safe as long as the underlying 00146 // thread does not get terminated or return from main 00147 return osSignalSet(_tid, signals); 00148 } 00149 00150 int32_t Thread::signal_clr(int32_t signals) { 00151 // osSignalClear is thread safe as long as the underlying 00152 // thread does not get terminated or return from main 00153 return osSignalClear(_tid, signals); 00154 } 00155 00156 Thread::State Thread::get_state() { 00157 #if !defined(__MBED_CMSIS_RTOS_CA9) && !defined(__MBED_CMSIS_RTOS_CM) 00158 #ifdef CMSIS_OS_RTX 00159 State status = Deleted; 00160 _mutex.lock(); 00161 00162 if (_tid != NULL) { 00163 status = (State)_thread_def.tcb.state; 00164 } 00165 00166 _mutex.unlock(); 00167 return status; 00168 #endif 00169 #else 00170 State status = Deleted; 00171 _mutex.lock(); 00172 00173 if (_tid != NULL) { 00174 status = (State)osThreadGetState(_tid); 00175 } 00176 00177 _mutex.unlock(); 00178 return status; 00179 #endif 00180 } 00181 00182 uint32_t Thread::stack_size() { 00183 #ifndef __MBED_CMSIS_RTOS_CA9 00184 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00185 uint32_t size = 0; 00186 _mutex.lock(); 00187 00188 if (_tid != NULL) { 00189 size = _thread_def.tcb.priv_stack; 00190 } 00191 00192 _mutex.unlock(); 00193 return size; 00194 #else 00195 uint32_t size = 0; 00196 _mutex.lock(); 00197 00198 if (_tid != NULL) { 00199 P_TCB tcb = rt_tid2ptcb(_tid); 00200 size = tcb->priv_stack; 00201 } 00202 00203 _mutex.unlock(); 00204 return size; 00205 #endif 00206 #else 00207 return 0; 00208 #endif 00209 } 00210 00211 uint32_t Thread::free_stack() { 00212 #ifndef __MBED_CMSIS_RTOS_CA9 00213 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00214 uint32_t size = 0; 00215 _mutex.lock(); 00216 00217 if (_tid != NULL) { 00218 uint32_t bottom = (uint32_t)_thread_def.tcb.stack; 00219 size = _thread_def.tcb.tsk_stack - bottom; 00220 } 00221 00222 _mutex.unlock(); 00223 return size; 00224 #else 00225 uint32_t size = 0; 00226 _mutex.lock(); 00227 00228 if (_tid != NULL) { 00229 P_TCB tcb = rt_tid2ptcb(_tid); 00230 uint32_t bottom = (uint32_t)tcb->stack; 00231 size = tcb->tsk_stack - bottom; 00232 } 00233 00234 _mutex.unlock(); 00235 return size; 00236 #endif 00237 #else 00238 return 0; 00239 #endif 00240 } 00241 00242 uint32_t Thread::used_stack() { 00243 #ifndef __MBED_CMSIS_RTOS_CA9 00244 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00245 uint32_t size = 0; 00246 _mutex.lock(); 00247 00248 if (_tid != NULL) { 00249 uint32_t top = (uint32_t)_thread_def.tcb.stack + _thread_def.tcb.priv_stack; 00250 size = top - _thread_def.tcb.tsk_stack; 00251 } 00252 00253 _mutex.unlock(); 00254 return size; 00255 #else 00256 uint32_t size = 0; 00257 _mutex.lock(); 00258 00259 if (_tid != NULL) { 00260 P_TCB tcb = rt_tid2ptcb(_tid); 00261 uint32_t top = (uint32_t)tcb->stack + tcb->priv_stack; 00262 size = top - tcb->tsk_stack; 00263 } 00264 00265 _mutex.unlock(); 00266 return size; 00267 #endif 00268 #else 00269 return 0; 00270 #endif 00271 } 00272 00273 uint32_t Thread::max_stack() { 00274 #ifndef __MBED_CMSIS_RTOS_CA9 00275 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00276 uint32_t size = 0; 00277 _mutex.lock(); 00278 00279 if (_tid != NULL) { 00280 uint32_t high_mark = 0; 00281 while (_thread_def.tcb.stack[high_mark] == 0xE25A2EA5) 00282 high_mark++; 00283 size = _thread_def.tcb.priv_stack - (high_mark * 4); 00284 } 00285 00286 _mutex.unlock(); 00287 return size; 00288 #else 00289 uint32_t size = 0; 00290 _mutex.lock(); 00291 00292 if (_tid != NULL) { 00293 P_TCB tcb = rt_tid2ptcb(_tid); 00294 uint32_t high_mark = 0; 00295 while (tcb->stack[high_mark] == 0xE25A2EA5) 00296 high_mark++; 00297 size = tcb->priv_stack - (high_mark * 4); 00298 } 00299 00300 _mutex.unlock(); 00301 return size; 00302 #endif 00303 #else 00304 return 0; 00305 #endif 00306 } 00307 00308 osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) { 00309 return osSignalWait(signals, millisec); 00310 } 00311 00312 osStatus Thread::wait(uint32_t millisec) { 00313 return osDelay(millisec); 00314 } 00315 00316 osStatus Thread::yield() { 00317 return osThreadYield(); 00318 } 00319 00320 osThreadId Thread::gettid() { 00321 return osThreadGetId(); 00322 } 00323 00324 void Thread::attach_idle_hook(void (*fptr)(void)) { 00325 rtos_attach_idle_hook(fptr); 00326 } 00327 00328 Thread::~Thread() { 00329 // terminate is thread safe 00330 terminate(); 00331 #ifdef __MBED_CMSIS_RTOS_CM 00332 if (_dynamic_stack) { 00333 delete[] (_thread_def.stack_pointer); 00334 } 00335 #endif 00336 } 00337 00338 void Thread::_thunk(const void * thread_ptr) 00339 { 00340 Thread *t = (Thread*)thread_ptr; 00341 t->_task(); 00342 t->_mutex.lock(); 00343 t->_tid = (osThreadId)NULL; 00344 t->_join_sem.release(); 00345 // rtos will release the mutex automatically 00346 } 00347 00348 }
Generated on Sun Jul 17 2022 17:03:25 by
1.7.2
