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