mdot_rtos

Fork of mbed-rtos by mbed official

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 "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     ret = osThreadTerminate(_tid);
00105     _tid = (osThreadId)NULL;
00106 
00107     // Wake threads joining the terminated thread
00108     _join_sem.release();
00109 
00110     _mutex.unlock();
00111     return ret;
00112 }
00113 
00114 osStatus Thread::join() {
00115     int32_t ret = _join_sem.wait();
00116     if (ret < 0) {
00117         return osErrorOS;
00118     }
00119     // Release sem so any other threads joining this thread wake up
00120     _join_sem.release();
00121     return osOK;
00122 }
00123 
00124 osStatus Thread::set_priority(osPriority priority) {
00125     osStatus ret;
00126     _mutex.lock();
00127 
00128     ret = osThreadSetPriority(_tid, priority);
00129 
00130     _mutex.unlock();
00131     return ret;
00132 }
00133 
00134 osPriority Thread::get_priority() {
00135     osPriority ret;
00136     _mutex.lock();
00137 
00138     ret = osThreadGetPriority(_tid);
00139 
00140     _mutex.unlock();
00141     return ret;
00142 }
00143 
00144 int32_t Thread::signal_set(int32_t signals) {
00145     // osSignalSet is thread safe as long as the underlying
00146     // thread does not get terminated or return from main
00147     return osSignalSet(_tid, signals);
00148 }
00149 
00150 int32_t Thread::signal_clr(int32_t signals) {
00151     // osSignalClear is thread safe as long as the underlying
00152     // thread does not get terminated or return from main
00153     return osSignalClear(_tid, signals);
00154 }
00155 
00156 Thread::State Thread::get_state() {
00157 #if !defined(__MBED_CMSIS_RTOS_CA9) && !defined(__MBED_CMSIS_RTOS_CM)
00158 #ifdef CMSIS_OS_RTX
00159     State status = Deleted;
00160     _mutex.lock();
00161 
00162     if (_tid != NULL) {
00163         status = (State)_thread_def.tcb.state;
00164     }
00165 
00166     _mutex.unlock();
00167     return status;
00168 #endif
00169 #else
00170     State status = Deleted;
00171     _mutex.lock();
00172 
00173     if (_tid != NULL) {
00174         status = (State)osThreadGetState(_tid);
00175     }
00176 
00177     _mutex.unlock();
00178     return status;
00179 #endif
00180 }
00181 
00182 uint32_t Thread::stack_size() {
00183 #ifndef __MBED_CMSIS_RTOS_CA9
00184 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
00185     uint32_t size = 0;
00186     _mutex.lock();
00187 
00188     if (_tid != NULL) {
00189         size = _thread_def.tcb.priv_stack;
00190     }
00191 
00192     _mutex.unlock();
00193     return size;
00194 #else
00195     uint32_t size = 0;
00196     _mutex.lock();
00197 
00198     if (_tid != NULL) {
00199         P_TCB tcb = rt_tid2ptcb(_tid);
00200         size = tcb->priv_stack;
00201     }
00202 
00203     _mutex.unlock();
00204     return size;
00205 #endif
00206 #else
00207     return 0;
00208 #endif
00209 }
00210 
00211 uint32_t Thread::free_stack() {
00212 #ifndef __MBED_CMSIS_RTOS_CA9
00213 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
00214     uint32_t size = 0;
00215     _mutex.lock();
00216 
00217     if (_tid != NULL) {
00218         uint32_t bottom = (uint32_t)_thread_def.tcb.stack;
00219         size = _thread_def.tcb.tsk_stack - bottom;
00220     }
00221 
00222     _mutex.unlock();
00223     return size;
00224 #else
00225     uint32_t size = 0;
00226     _mutex.lock();
00227 
00228     if (_tid != NULL) {
00229         P_TCB tcb = rt_tid2ptcb(_tid);
00230         uint32_t bottom = (uint32_t)tcb->stack;
00231         size = tcb->tsk_stack - bottom;
00232     }
00233 
00234     _mutex.unlock();
00235     return size;
00236 #endif
00237 #else
00238     return 0;
00239 #endif
00240 }
00241 
00242 uint32_t Thread::used_stack() {
00243 #ifndef __MBED_CMSIS_RTOS_CA9
00244 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
00245     uint32_t size = 0;
00246     _mutex.lock();
00247 
00248     if (_tid != NULL) {
00249         uint32_t top = (uint32_t)_thread_def.tcb.stack + _thread_def.tcb.priv_stack;
00250         size = top - _thread_def.tcb.tsk_stack;
00251     }
00252 
00253     _mutex.unlock();
00254     return size;
00255 #else
00256     uint32_t size = 0;
00257     _mutex.lock();
00258 
00259     if (_tid != NULL) {
00260         P_TCB tcb = rt_tid2ptcb(_tid);
00261         uint32_t top = (uint32_t)tcb->stack + tcb->priv_stack;
00262         size =  top - tcb->tsk_stack;
00263     }
00264 
00265     _mutex.unlock();
00266     return size;
00267 #endif
00268 #else
00269     return 0;
00270 #endif
00271 }
00272 
00273 uint32_t Thread::max_stack() {
00274 #ifndef __MBED_CMSIS_RTOS_CA9
00275 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
00276     uint32_t size = 0;
00277     _mutex.lock();
00278 
00279     if (_tid != NULL) {
00280         uint32_t high_mark = 0;
00281         while (_thread_def.tcb.stack[high_mark] == 0xE25A2EA5)
00282             high_mark++;
00283         size = _thread_def.tcb.priv_stack - (high_mark * 4);
00284     }
00285 
00286     _mutex.unlock();
00287     return size;
00288 #else
00289     uint32_t size = 0;
00290     _mutex.lock();
00291 
00292     if (_tid != NULL) {
00293         P_TCB tcb = rt_tid2ptcb(_tid);
00294         uint32_t high_mark = 0;
00295         while (tcb->stack[high_mark] == 0xE25A2EA5)
00296             high_mark++;
00297         size = tcb->priv_stack - (high_mark * 4);
00298     }
00299 
00300     _mutex.unlock();
00301     return size;
00302 #endif
00303 #else
00304     return 0;
00305 #endif
00306 }
00307 
00308 osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) {
00309     return osSignalWait(signals, millisec);
00310 }
00311 
00312 osStatus Thread::wait(uint32_t millisec) {
00313     return osDelay(millisec);
00314 }
00315 
00316 osStatus Thread::yield() {
00317     return osThreadYield();
00318 }
00319 
00320 osThreadId Thread::gettid() {
00321     return osThreadGetId();
00322 }
00323 
00324 void Thread::attach_idle_hook(void (*fptr)(void)) {
00325     rtos_attach_idle_hook(fptr);
00326 }
00327 
00328 Thread::~Thread() {
00329     // terminate is thread safe
00330     terminate();
00331 #ifdef __MBED_CMSIS_RTOS_CM
00332     if (_dynamic_stack) {
00333         delete[] (_thread_def.stack_pointer);
00334     }
00335 #endif
00336 }
00337 
00338 void Thread::_thunk(const void * thread_ptr)
00339 {
00340     Thread *t = (Thread*)thread_ptr;
00341     t->_task();
00342     t->_mutex.lock();
00343     t->_tid = (osThreadId)NULL;
00344     t->_join_sem.release();
00345     // rtos will release the mutex automatically
00346 }
00347 
00348 }