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.
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo 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 // 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 12:28:55 by
