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: nRF51_Vdd TextLCD BME280
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 "rtos/Thread.h" 00023 #include "rtos/ThisThread.h" 00024 00025 #include "mbed.h" 00026 #include "rtos/rtos_idle.h" 00027 #include "rtos/rtos_handlers.h" 00028 #include "mbed_assert.h" 00029 00030 #define ALIGN_UP(pos, align) ((pos) % (align) ? (pos) + ((align) - (pos) % (align)) : (pos)) 00031 MBED_STATIC_ASSERT(ALIGN_UP(0, 8) == 0, "ALIGN_UP macro error"); 00032 MBED_STATIC_ASSERT(ALIGN_UP(1, 8) == 8, "ALIGN_UP macro error"); 00033 00034 #define ALIGN_DOWN(pos, align) ((pos) - ((pos) % (align))) 00035 MBED_STATIC_ASSERT(ALIGN_DOWN(7, 8) == 0, "ALIGN_DOWN macro error"); 00036 MBED_STATIC_ASSERT(ALIGN_DOWN(8, 8) == 8, "ALIGN_DOWN macro error"); 00037 00038 namespace rtos { 00039 00040 #ifndef MBED_TZ_DEFAULT_ACCESS 00041 #define MBED_TZ_DEFAULT_ACCESS 0 00042 #endif 00043 00044 void Thread::constructor(uint32_t tz_module, osPriority priority, 00045 uint32_t stack_size, unsigned char *stack_mem, const char *name) 00046 { 00047 00048 const uintptr_t unaligned_mem = reinterpret_cast<uintptr_t>(stack_mem); 00049 const uintptr_t aligned_mem = ALIGN_UP(unaligned_mem, 8); 00050 const uint32_t offset = aligned_mem - unaligned_mem; 00051 const uint32_t aligned_size = ALIGN_DOWN(stack_size - offset, 8); 00052 00053 _tid = 0; 00054 _dynamic_stack = (stack_mem == NULL); 00055 _finished = false; 00056 memset(&_obj_mem, 0, sizeof(_obj_mem)); 00057 memset(&_attr, 0, sizeof(_attr)); 00058 _attr.priority = priority; 00059 _attr.stack_size = aligned_size; 00060 _attr.name = name ? name : "application_unnamed_thread"; 00061 _attr.stack_mem = reinterpret_cast<uint32_t *>(aligned_mem); 00062 _attr.tz_module = tz_module; 00063 } 00064 00065 void Thread::constructor(osPriority priority, 00066 uint32_t stack_size, unsigned char *stack_mem, const char *name) 00067 { 00068 constructor(MBED_TZ_DEFAULT_ACCESS, priority, stack_size, stack_mem, name); 00069 } 00070 00071 void Thread::constructor(Callback<void()> task, 00072 osPriority priority, uint32_t stack_size, unsigned char *stack_mem, const char *name) 00073 { 00074 constructor(MBED_TZ_DEFAULT_ACCESS, priority, stack_size, stack_mem, name); 00075 00076 switch (start(task)) { 00077 case osErrorResource: 00078 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_RESOURCES), "OS ran out of threads!\n", task); 00079 break; 00080 case osErrorParameter: 00081 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_ALREADY_IN_USE), "Thread already running!\n", task); 00082 break; 00083 case osErrorNoMemory: 00084 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Error allocating the stack memory\n", task); 00085 default: 00086 break; 00087 } 00088 } 00089 00090 osStatus Thread::start(Callback<void()> task) 00091 { 00092 _mutex.lock(); 00093 00094 if ((_tid != 0) || _finished) { 00095 _mutex.unlock(); 00096 return osErrorParameter; 00097 } 00098 00099 if (_attr.stack_mem == NULL) { 00100 _attr.stack_mem = new uint32_t[_attr.stack_size / sizeof(uint32_t)]; 00101 MBED_ASSERT(_attr.stack_mem != NULL); 00102 } 00103 00104 //Fill the stack with a magic word for maximum usage checking 00105 for (uint32_t i = 0; i < (_attr.stack_size / sizeof(uint32_t)); i++) { 00106 ((uint32_t *)_attr.stack_mem)[i] = osRtxStackMagicWord; 00107 } 00108 00109 memset(&_obj_mem, 0, sizeof(_obj_mem)); 00110 _attr.cb_size = sizeof(_obj_mem); 00111 _attr.cb_mem = &_obj_mem; 00112 _task = task; 00113 _tid = osThreadNew(Thread::_thunk, this, &_attr); 00114 if (_tid == NULL) { 00115 if (_dynamic_stack) { 00116 delete[](uint32_t *)(_attr.stack_mem); 00117 _attr.stack_mem = (uint32_t *)NULL; 00118 } 00119 _mutex.unlock(); 00120 _join_sem.release(); 00121 return osErrorResource; 00122 } 00123 00124 _mutex.unlock(); 00125 return osOK; 00126 } 00127 00128 osStatus Thread::terminate() 00129 { 00130 osStatus_t ret = osOK; 00131 _mutex.lock(); 00132 00133 // Set the Thread's tid to NULL and 00134 // release the semaphore before terminating 00135 // since this thread could be terminating itself 00136 osThreadId_t local_id = _tid; 00137 _join_sem.release(); 00138 _tid = (osThreadId_t)NULL; 00139 if (!_finished) { 00140 _finished = true; 00141 // if local_id == 0 Thread was not started in first place 00142 // and does not have to be terminated 00143 if (local_id != 0) { 00144 ret = osThreadTerminate(local_id); 00145 } 00146 } 00147 _mutex.unlock(); 00148 return ret; 00149 } 00150 00151 osStatus Thread::join() 00152 { 00153 int32_t ret = _join_sem.wait(); 00154 if (ret < 0) { 00155 return osError; 00156 } 00157 00158 // The semaphore has been released so this thread is being 00159 // terminated or has been terminated. Once the mutex has 00160 // been locked it is ensured that the thread is deleted. 00161 _mutex.lock(); 00162 MBED_ASSERT(NULL == _tid); 00163 _mutex.unlock(); 00164 00165 // Release sem so any other threads joining this thread wake up 00166 _join_sem.release(); 00167 return osOK; 00168 } 00169 00170 osStatus Thread::set_priority(osPriority priority) 00171 { 00172 osStatus_t ret; 00173 _mutex.lock(); 00174 00175 ret = osThreadSetPriority(_tid, priority); 00176 00177 _mutex.unlock(); 00178 return ret; 00179 } 00180 00181 osPriority Thread::get_priority() const 00182 { 00183 osPriority_t ret; 00184 _mutex.lock(); 00185 00186 ret = osThreadGetPriority(_tid); 00187 00188 _mutex.unlock(); 00189 return ret; 00190 } 00191 00192 uint32_t Thread::flags_set(uint32_t flags) 00193 { 00194 flags = osThreadFlagsSet(_tid, flags); 00195 MBED_ASSERT(!(flags & osFlagsError)); 00196 return flags; 00197 } 00198 00199 int32_t Thread::signal_set(int32_t flags) 00200 { 00201 return osThreadFlagsSet(_tid, flags); 00202 } 00203 00204 Thread::State Thread::get_state() const 00205 { 00206 uint8_t state = osThreadTerminated; 00207 00208 _mutex.lock(); 00209 00210 if (_tid != NULL) { 00211 #if defined(MBED_OS_BACKEND_RTX5) 00212 state = _obj_mem.state; 00213 #else 00214 state = osThreadGetState(_tid); 00215 #endif 00216 } 00217 00218 _mutex.unlock(); 00219 00220 State user_state; 00221 00222 switch (state) { 00223 case osThreadInactive: 00224 user_state = Inactive; 00225 break; 00226 case osThreadReady: 00227 user_state = Ready; 00228 break; 00229 case osThreadRunning: 00230 user_state = Running; 00231 break; 00232 #if defined(MBED_OS_BACKEND_RTX5) 00233 case osRtxThreadWaitingDelay: 00234 user_state = WaitingDelay; 00235 break; 00236 case osRtxThreadWaitingJoin: 00237 user_state = WaitingJoin; 00238 break; 00239 case osRtxThreadWaitingThreadFlags: 00240 user_state = WaitingThreadFlag; 00241 break; 00242 case osRtxThreadWaitingEventFlags: 00243 user_state = WaitingEventFlag; 00244 break; 00245 case osRtxThreadWaitingMutex: 00246 user_state = WaitingMutex; 00247 break; 00248 case osRtxThreadWaitingSemaphore: 00249 user_state = WaitingSemaphore; 00250 break; 00251 case osRtxThreadWaitingMemoryPool: 00252 user_state = WaitingMemoryPool; 00253 break; 00254 case osRtxThreadWaitingMessageGet: 00255 user_state = WaitingMessageGet; 00256 break; 00257 case osRtxThreadWaitingMessagePut: 00258 user_state = WaitingMessagePut; 00259 break; 00260 #endif 00261 case osThreadTerminated: 00262 default: 00263 user_state = Deleted; 00264 break; 00265 } 00266 00267 return user_state; 00268 } 00269 00270 uint32_t Thread::stack_size() const 00271 { 00272 uint32_t size = 0; 00273 _mutex.lock(); 00274 00275 if (_tid != NULL) { 00276 size = osThreadGetStackSize(_tid); 00277 } 00278 00279 _mutex.unlock(); 00280 return size; 00281 } 00282 00283 uint32_t Thread::free_stack() const 00284 { 00285 uint32_t size = 0; 00286 _mutex.lock(); 00287 00288 #if defined(MBED_OS_BACKEND_RTX5) 00289 if (_tid != NULL) { 00290 mbed_rtos_storage_thread_t *thread = (mbed_rtos_storage_thread_t *)_tid; 00291 size = (uint32_t)thread->sp - (uint32_t)thread->stack_mem; 00292 } 00293 #endif 00294 00295 _mutex.unlock(); 00296 return size; 00297 } 00298 00299 uint32_t Thread::used_stack() const 00300 { 00301 uint32_t size = 0; 00302 _mutex.lock(); 00303 00304 #if defined(MBED_OS_BACKEND_RTX5) 00305 if (_tid != NULL) { 00306 mbed_rtos_storage_thread_t *thread = (mbed_rtos_storage_thread_t *)_tid; 00307 size = ((uint32_t)thread->stack_mem + thread->stack_size) - thread->sp; 00308 } 00309 #endif 00310 00311 _mutex.unlock(); 00312 return size; 00313 } 00314 00315 uint32_t Thread::max_stack() const 00316 { 00317 uint32_t size = 0; 00318 _mutex.lock(); 00319 00320 if (_tid != NULL) { 00321 #if defined(MBED_OS_BACKEND_RTX5) 00322 mbed_rtos_storage_thread_t *thread = (mbed_rtos_storage_thread_t *)_tid; 00323 uint32_t high_mark = 0; 00324 while ((((uint32_t *)(thread->stack_mem))[high_mark] == osRtxStackMagicWord) || (((uint32_t *)(thread->stack_mem))[high_mark] == osRtxStackFillPattern)) { 00325 high_mark++; 00326 } 00327 size = thread->stack_size - (high_mark * sizeof(uint32_t)); 00328 #else 00329 size = osThreadGetStackSize(_tid) - osThreadGetStackSpace(_tid); 00330 #endif 00331 } 00332 00333 _mutex.unlock(); 00334 return size; 00335 } 00336 00337 const char *Thread::get_name() const 00338 { 00339 return _attr.name; 00340 } 00341 00342 osThreadId_t Thread::get_id() const 00343 { 00344 return _tid; 00345 } 00346 00347 int32_t Thread::signal_clr(int32_t flags) 00348 { 00349 return osThreadFlagsClear(flags); 00350 } 00351 00352 osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) 00353 { 00354 uint32_t res; 00355 osEvent evt; 00356 uint32_t options = osFlagsWaitAll; 00357 if (signals == 0) { 00358 options = osFlagsWaitAny; 00359 signals = 0x7FFFFFFF; 00360 } 00361 res = osThreadFlagsWait(signals, options, millisec); 00362 if (res & osFlagsError) { 00363 switch (res) { 00364 case osFlagsErrorISR: 00365 evt.status = osErrorISR; 00366 break; 00367 case osFlagsErrorResource: 00368 evt.status = osOK; 00369 break; 00370 case osFlagsErrorTimeout: 00371 evt.status = (osStatus)osEventTimeout; 00372 break; 00373 case osFlagsErrorParameter: 00374 default: 00375 evt.status = (osStatus)osErrorValue; 00376 break; 00377 } 00378 } else { 00379 evt.status = (osStatus)osEventSignal; 00380 evt.value.signals = res; 00381 } 00382 00383 return evt; 00384 } 00385 00386 osStatus Thread::wait(uint32_t millisec) 00387 { 00388 ThisThread::sleep_for(millisec); 00389 return osOK; 00390 } 00391 00392 osStatus Thread::wait_until(uint64_t millisec) 00393 { 00394 ThisThread::sleep_until(millisec); 00395 return osOK; 00396 } 00397 00398 osStatus Thread::yield() 00399 { 00400 return osThreadYield(); 00401 } 00402 00403 osThreadId Thread::gettid() 00404 { 00405 return osThreadGetId(); 00406 } 00407 00408 void Thread::attach_idle_hook(void (*fptr)(void)) 00409 { 00410 rtos_attach_idle_hook (fptr); 00411 } 00412 00413 void Thread::attach_terminate_hook(void (*fptr)(osThreadId_t id)) 00414 { 00415 rtos_attach_thread_terminate_hook (fptr); 00416 } 00417 00418 Thread::~Thread() 00419 { 00420 // terminate is thread safe 00421 terminate(); 00422 if (_dynamic_stack) { 00423 delete[](uint32_t *)(_attr.stack_mem); 00424 _attr.stack_mem = (uint32_t *)NULL; 00425 } 00426 } 00427 00428 void Thread::_thunk(void *thread_ptr) 00429 { 00430 Thread *t = (Thread *)thread_ptr; 00431 t->_task(); 00432 t->_mutex.lock(); 00433 t->_tid = (osThreadId)NULL; 00434 t->_finished = true; 00435 t->_join_sem.release(); 00436 // rtos will release the mutex automatically 00437 } 00438 00439 }
Generated on Tue Jul 12 2022 15:16:01 by
