mdot_rtos
Fork of mbed-rtos by
Embed:
(wiki syntax)
Show/hide line numbers
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 Thu Jul 14 2022 09:48:40 by
1.7.2
