Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ThisThread.cpp Source File

ThisThread.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 
00023 #define __STDC_LIMIT_MACROS
00024 #include "rtos/ThisThread.h"
00025 
00026 #include "platform/mbed_toolchain.h"
00027 #include "rtos/Kernel.h"
00028 #include "platform/CriticalSectionLock.h"
00029 #include "platform/mbed_assert.h"
00030 #include "platform/mbed_critical.h"
00031 #include "platform/source/mbed_os_timer.h"
00032 
00033 #if !MBED_CONF_RTOS_PRESENT
00034 /* If the RTOS is not present, we call mbed_thread.cpp to do the work */
00035 /* If the RTOS is present, mbed_thread.cpp calls us to do the work */
00036 #include "platform/mbed_thread.h"
00037 
00038 static uint32_t thread_flags;
00039 
00040 /* For the flags to be useful, need a way of setting them, but there's only the main
00041  * thread, and that has no Thread object, so Thread class is not provided. Implement
00042  * one CMSIS-RTOS function to provide access.
00043  */
00044 extern "C"
00045 uint32_t osThreadFlagsSet(osThreadId_t /*thread_id*/, uint32_t flags)
00046 {
00047     return core_util_atomic_fetch_or_u32 (&thread_flags, flags) | flags;
00048 }
00049 #endif
00050 
00051 namespace rtos {
00052 
00053 uint32_t ThisThread::flags_clear(uint32_t flags)
00054 {
00055 #if MBED_CONF_RTOS_PRESENT
00056     flags = osThreadFlagsClear(flags);
00057     MBED_ASSERT(!(flags & osFlagsError));
00058 #else
00059     flags = core_util_atomic_fetch_and_u32 (&thread_flags, ~flags);
00060 #endif
00061     return flags;
00062 }
00063 
00064 uint32_t ThisThread::flags_get()
00065 {
00066 #if MBED_CONF_RTOS_PRESENT
00067     return osThreadFlagsGet();
00068 #else
00069     return core_util_atomic_load_u32 (&thread_flags);
00070 #endif
00071 }
00072 
00073 #if !MBED_CONF_RTOS_PRESENT
00074 namespace internal {
00075 bool non_rtos_check_flags(void *handle)
00076 {
00077     flags_check_capture *check = static_cast<flags_check_capture *>(handle);
00078     uint32_t cur_flags = core_util_atomic_load_u32 (check->flags);
00079     uint32_t set_flags;
00080     do {
00081         set_flags = cur_flags & check->flags_wanted;
00082         check->result = set_flags;
00083         if ((check->options & osFlagsWaitAll) ? set_flags == check->flags_wanted : set_flags != 0) {
00084             if (check->options & osFlagsNoClear) {
00085                 break;
00086             }
00087         } else {
00088             return false;
00089         }
00090     } while (!core_util_atomic_cas_u32 (check->flags, &cur_flags, cur_flags & ~set_flags));
00091     check->match = true;
00092     return true;
00093 }
00094 }
00095 #endif
00096 
00097 static uint32_t flags_wait_for(uint32_t flags, uint32_t millisec, bool clear, uint32_t options)
00098 {
00099     if (!clear) {
00100         options |= osFlagsNoClear;
00101     }
00102 #if MBED_CONF_RTOS_PRESENT
00103     flags = osThreadFlagsWait(flags, options, millisec);
00104     if (flags & osFlagsError) {
00105         MBED_ASSERT((flags == osFlagsErrorTimeout && millisec != osWaitForever) ||
00106                     (flags == osFlagsErrorResource && millisec == 0));
00107         flags = ThisThread::flags_get();
00108     }
00109 #else
00110     rtos::internal::flags_check_capture check;
00111     check.flags = &thread_flags;
00112     check.options = options;
00113     check.flags_wanted = flags;
00114     check.result = 0;
00115     mbed::internal::do_timed_sleep_relative_or_forever(millisec, rtos::internal::non_rtos_check_flags, &check);
00116     flags = check.result;
00117 #endif
00118 
00119     return flags;
00120 }
00121 
00122 static uint32_t flags_wait(uint32_t flags, bool clear, uint32_t options)
00123 {
00124 #if MBED_CONF_RTOS_PRESENT
00125     return flags_wait_for(flags, osWaitForever, clear, options);
00126 #else
00127     /* Avoids pulling in timer if not used */
00128     if (!clear) {
00129         options |= osFlagsNoClear;
00130     }
00131     rtos::internal::flags_check_capture check;
00132     check.flags = &thread_flags;
00133     check.options = options;
00134     check.flags_wanted = flags;
00135     check.result = 0;
00136     mbed::internal::do_untimed_sleep(rtos::internal::non_rtos_check_flags, &check);
00137     flags = check.result;
00138 
00139     return flags;
00140 #endif
00141 }
00142 
00143 static uint32_t flags_wait_until(uint32_t flags, uint64_t millisec, bool clear, uint32_t options)
00144 {
00145     uint64_t now = Kernel::get_ms_count();
00146 
00147     uint32_t delay;
00148     if (now >= millisec) {
00149         delay = 0;
00150     } else if (millisec - now >= osWaitForever) {
00151         // Documentation permits early return for big offsets
00152         delay = osWaitForever - 1;
00153     } else {
00154         delay = millisec - now;
00155     }
00156     return flags_wait_for(flags, delay, clear, options);
00157 }
00158 
00159 uint32_t ThisThread::flags_wait_all(uint32_t flags, bool clear)
00160 {
00161     return flags_wait(flags, clear, osFlagsWaitAll);
00162 }
00163 
00164 uint32_t ThisThread::flags_wait_all_for(uint32_t flags, uint32_t millisec, bool clear)
00165 {
00166     return flags_wait_for(flags, millisec, clear, osFlagsWaitAll);
00167 }
00168 
00169 uint32_t ThisThread::flags_wait_all_until(uint32_t flags, uint64_t millisec, bool clear)
00170 {
00171     return flags_wait_until(flags, millisec, clear, osFlagsWaitAll);
00172 }
00173 
00174 uint32_t ThisThread::flags_wait_any(uint32_t flags, bool clear)
00175 {
00176     return flags_wait(flags, clear, osFlagsWaitAny);
00177 }
00178 
00179 uint32_t ThisThread::flags_wait_any_for(uint32_t flags, uint32_t millisec, bool clear)
00180 {
00181     return flags_wait_for(flags, millisec, clear, osFlagsWaitAny);
00182 }
00183 
00184 uint32_t ThisThread::flags_wait_any_until(uint32_t flags, uint64_t millisec, bool clear)
00185 {
00186     return flags_wait_until(flags, millisec, clear, osFlagsWaitAny);
00187 }
00188 
00189 void ThisThread::sleep_for(uint32_t millisec)
00190 {
00191 #if MBED_CONF_RTOS_PRESENT
00192     osStatus_t  status = osDelay(millisec);
00193     MBED_ASSERT(status == osOK);
00194 #else
00195     thread_sleep_for(millisec);
00196 #endif
00197 }
00198 
00199 void ThisThread::sleep_until(uint64_t millisec)
00200 {
00201 #if MBED_CONF_RTOS_PRESENT
00202     // CMSIS-RTOS 2.1.0 had 64-bit time and osDelayUntil, but that's been revoked.
00203     // Limit ourselves to manual implementation assuming a >=32-bit osDelay.
00204 
00205     // 64-bit time doesn't wrap (for half a billion years, at last)
00206     // make the effort to loop for unlimited sleep, as it doesn't cost much
00207     uint64_t now;
00208 
00209     while ((now = Kernel::get_ms_count()) < millisec) {
00210         if (millisec - now > UINT32_MAX) {
00211             sleep_for(UINT32_MAX);
00212             continue;
00213         } else {
00214             sleep_for(millisec - now);
00215             break;
00216         }
00217     }
00218 #else
00219     thread_sleep_until(millisec);
00220 #endif
00221 }
00222 
00223 void ThisThread::yield()
00224 {
00225 #if MBED_CONF_RTOS_PRESENT
00226     osThreadYield();
00227 #else
00228     asm("yield");
00229 #endif
00230 }
00231 
00232 osThreadId_t ThisThread::get_id()
00233 {
00234 #if MBED_CONF_RTOS_PRESENT
00235     return osThreadGetId();
00236 #else
00237     return (osThreadId_t) 1; // dummy non-0 value
00238 #endif
00239 }
00240 
00241 const char *get_name()
00242 {
00243 #if MBED_CONF_RTOS_PRESENT
00244     osThreadId_t id = osThreadGetId();
00245     if (id == nullptr) {
00246         return nullptr;
00247     }
00248     return osThreadGetName(id);
00249 #else
00250     return nullptr;
00251 #endif
00252 }
00253 
00254 }