Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Thread.cpp Source File

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