Daiki Kato / mbed-os-lychee

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

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 
00024 #include "mbed.h"
00025 #include "rtos/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 
00034 static void (*terminate_hook)(osThreadId id) = 0;
00035 extern "C" void thread_terminate_hook(osThreadId id)
00036 {
00037     if (terminate_hook != (void (*)(osThreadId))NULL) {
00038         terminate_hook(id);
00039     }
00040 }
00041 
00042 namespace rtos {
00043 
00044 void Thread::constructor(osPriority priority,
00045         uint32_t stack_size, unsigned char *stack_pointer) {
00046     _tid = 0;
00047     _finished = false;
00048     _dynamic_stack = (stack_pointer == NULL);
00049 
00050 #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM)
00051     _thread_def.tpriority = priority;
00052     _thread_def.stacksize = stack_size;
00053     _thread_def.stack_pointer = (uint32_t*)stack_pointer;
00054 #endif
00055 }
00056 
00057 void Thread::constructor(Callback<void()> task,
00058         osPriority priority, uint32_t stack_size, unsigned char *stack_pointer) {
00059     constructor(priority, stack_size, stack_pointer);
00060 
00061     switch (start(task)) {
00062         case osErrorResource:
00063             error("OS ran out of threads!\n");
00064             break;
00065         case osErrorParameter:
00066             error("Thread already running!\n");
00067             break;
00068         case osErrorNoMemory:
00069             error("Error allocating the stack memory\n");
00070         default:
00071             break;
00072     }
00073 }
00074 
00075 osStatus Thread::start(Callback<void()> task) {
00076     _mutex.lock();
00077 
00078     if ((_tid != 0) || _finished) {
00079         _mutex.unlock();
00080         return osErrorParameter;
00081     }
00082 
00083 #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM)
00084     _thread_def.pthread = Thread::_thunk;
00085     if (_thread_def.stack_pointer == NULL) {
00086         _thread_def.stack_pointer = new uint32_t[_thread_def.stacksize/sizeof(uint32_t)];
00087         MBED_ASSERT(_thread_def.stack_pointer != NULL);
00088     }
00089 
00090     //Fill the stack with a magic word for maximum usage checking
00091     for (uint32_t i = 0; i < (_thread_def.stacksize / sizeof(uint32_t)); i++) {
00092         _thread_def.stack_pointer[i] = 0xE25A2EA5;
00093     }
00094 #endif
00095     _task = task;
00096     _tid = osThreadCreate(&_thread_def, this);
00097     if (_tid == NULL) {
00098         if (_dynamic_stack) {
00099             delete[] (_thread_def.stack_pointer);
00100             _thread_def.stack_pointer = (uint32_t*)NULL;
00101         }
00102         _mutex.unlock();
00103         _join_sem.release();
00104         return osErrorResource;
00105     }
00106 
00107     _mutex.unlock();
00108     return osOK;
00109 }
00110 
00111 osStatus Thread::terminate() {
00112     osStatus ret;
00113     _mutex.lock();
00114 
00115     // Set the Thread's tid to NULL and
00116     // release the semaphore before terminating
00117     // since this thread could be terminating itself
00118     osThreadId local_id = _tid;
00119     _join_sem.release();
00120     _tid = (osThreadId)NULL;
00121     _finished = true;
00122 
00123     ret = osThreadTerminate(local_id);
00124 
00125     _mutex.unlock();
00126     return ret;
00127 }
00128 
00129 osStatus Thread::join() {
00130     int32_t ret = _join_sem.wait();
00131     if (ret < 0) {
00132         return osErrorOS;
00133     }
00134 
00135     // The semaphore has been released so this thread is being
00136     // terminated or has been terminated. Once the mutex has
00137     // been locked it is ensured that the thread is deleted.
00138     _mutex.lock();
00139     MBED_ASSERT(NULL == _tid);
00140     _mutex.unlock();
00141 
00142     // Release sem so any other threads joining this thread wake up
00143     _join_sem.release();
00144     return osOK;
00145 }
00146 
00147 osStatus Thread::set_priority(osPriority priority) {
00148     osStatus ret;
00149     _mutex.lock();
00150 
00151     ret = osThreadSetPriority(_tid, priority);
00152 
00153     _mutex.unlock();
00154     return ret;
00155 }
00156 
00157 osPriority Thread::get_priority() {
00158     osPriority ret;
00159     _mutex.lock();
00160 
00161     ret = osThreadGetPriority(_tid);
00162 
00163     _mutex.unlock();
00164     return ret;
00165 }
00166 
00167 int32_t Thread::signal_set(int32_t signals) {
00168     // osSignalSet is thread safe as long as the underlying
00169     // thread does not get terminated or return from main
00170     return osSignalSet(_tid, signals);
00171 }
00172 
00173 int32_t Thread::signal_clr(int32_t signals) {
00174     // osSignalClear is thread safe as long as the underlying
00175     // thread does not get terminated or return from main
00176     return osSignalClear(_tid, signals);
00177 }
00178 
00179 Thread::State Thread::get_state() {
00180 #if !defined(__MBED_CMSIS_RTOS_CA9) && !defined(__MBED_CMSIS_RTOS_CM)
00181 #ifdef CMSIS_OS_RTX
00182     State status;
00183     _mutex.lock();
00184 
00185     if (_tid != NULL) {
00186         status = (State)_thread_def.tcb.state;
00187     } else if (_finished) {
00188         status = Deleted;
00189     } else {
00190         status = Inactive;
00191     }
00192 
00193     _mutex.unlock();
00194     return status;
00195 #endif
00196 #else
00197     State status = Deleted;
00198     _mutex.lock();
00199 
00200     if (_tid != NULL) {
00201         status = (State)osThreadGetState(_tid);
00202     }
00203 
00204     _mutex.unlock();
00205     return status;
00206 #endif
00207 }
00208 
00209 uint32_t Thread::stack_size() {
00210 #ifndef __MBED_CMSIS_RTOS_CA9
00211 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
00212     uint32_t size = 0;
00213     _mutex.lock();
00214 
00215     if (_tid != NULL) {
00216         size = _thread_def.tcb.priv_stack;
00217     }
00218 
00219     _mutex.unlock();
00220     return size;
00221 #else
00222     uint32_t size = 0;
00223     _mutex.lock();
00224 
00225     if (_tid != NULL) {
00226         P_TCB tcb = rt_tid2ptcb(_tid);
00227         size = tcb->priv_stack;
00228     }
00229 
00230     _mutex.unlock();
00231     return size;
00232 #endif
00233 #else
00234     return 0;
00235 #endif
00236 }
00237 
00238 uint32_t Thread::free_stack() {
00239 #ifndef __MBED_CMSIS_RTOS_CA9
00240 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
00241     uint32_t size = 0;
00242     _mutex.lock();
00243 
00244     if (_tid != NULL) {
00245         uint32_t bottom = (uint32_t)_thread_def.tcb.stack;
00246         size = _thread_def.tcb.tsk_stack - bottom;
00247     }
00248 
00249     _mutex.unlock();
00250     return size;
00251 #else
00252     uint32_t size = 0;
00253     _mutex.lock();
00254 
00255     if (_tid != NULL) {
00256         P_TCB tcb = rt_tid2ptcb(_tid);
00257         uint32_t bottom = (uint32_t)tcb->stack;
00258         size = tcb->tsk_stack - bottom;
00259     }
00260 
00261     _mutex.unlock();
00262     return size;
00263 #endif
00264 #else
00265     return 0;
00266 #endif
00267 }
00268 
00269 uint32_t Thread::used_stack() {
00270 #ifndef __MBED_CMSIS_RTOS_CA9
00271 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
00272     uint32_t size = 0;
00273     _mutex.lock();
00274 
00275     if (_tid != NULL) {
00276         uint32_t top = (uint32_t)_thread_def.tcb.stack + _thread_def.tcb.priv_stack;
00277         size = top - _thread_def.tcb.tsk_stack;
00278     }
00279 
00280     _mutex.unlock();
00281     return size;
00282 #else
00283     uint32_t size = 0;
00284     _mutex.lock();
00285 
00286     if (_tid != NULL) {
00287         P_TCB tcb = rt_tid2ptcb(_tid);
00288         uint32_t top = (uint32_t)tcb->stack + tcb->priv_stack;
00289         size =  top - tcb->tsk_stack;
00290     }
00291 
00292     _mutex.unlock();
00293     return size;
00294 #endif
00295 #else
00296     return 0;
00297 #endif
00298 }
00299 
00300 uint32_t Thread::max_stack() {
00301 #ifndef __MBED_CMSIS_RTOS_CA9
00302 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
00303     uint32_t size = 0;
00304     _mutex.lock();
00305 
00306     if (_tid != NULL) {
00307         uint32_t high_mark = 0;
00308         while (_thread_def.tcb.stack[high_mark] == 0xE25A2EA5)
00309             high_mark++;
00310         size = _thread_def.tcb.priv_stack - (high_mark * 4);
00311     }
00312 
00313     _mutex.unlock();
00314     return size;
00315 #else
00316     uint32_t size = 0;
00317     _mutex.lock();
00318 
00319     if (_tid != NULL) {
00320         P_TCB tcb = rt_tid2ptcb(_tid);
00321         uint32_t high_mark = 0;
00322         while (tcb->stack[high_mark] == 0xE25A2EA5)
00323             high_mark++;
00324         size = tcb->priv_stack - (high_mark * 4);
00325     }
00326 
00327     _mutex.unlock();
00328     return size;
00329 #endif
00330 #else
00331     return 0;
00332 #endif
00333 }
00334 
00335 osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) {
00336     return osSignalWait(signals, millisec);
00337 }
00338 
00339 osStatus Thread::wait(uint32_t millisec) {
00340     return osDelay(millisec);
00341 }
00342 
00343 osStatus Thread::yield() {
00344     return osThreadYield();
00345 }
00346 
00347 osThreadId Thread::gettid() {
00348     return osThreadGetId();
00349 }
00350 
00351 void Thread::attach_idle_hook(void (*fptr)(void)) {
00352     rtos_attach_idle_hook(fptr);
00353 }
00354 
00355 void Thread::attach_terminate_hook(void (*fptr)(osThreadId id)) {
00356     terminate_hook = fptr;
00357 }
00358 
00359 Thread::~Thread() {
00360     // terminate is thread safe
00361     terminate();
00362 #ifdef __MBED_CMSIS_RTOS_CM
00363     if (_dynamic_stack) {
00364         delete[] (_thread_def.stack_pointer);
00365         _thread_def.stack_pointer = (uint32_t*)NULL;
00366     }
00367 #endif
00368 }
00369 
00370 void Thread::_thunk(const void * thread_ptr)
00371 {
00372     Thread *t = (Thread*)thread_ptr;
00373     t->_task();
00374     t->_mutex.lock();
00375     t->_tid = (osThreadId)NULL;
00376     t->_finished = true;
00377     t->_join_sem.release();
00378     // rtos will release the mutex automatically
00379 }
00380 
00381 }