Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Semaphore.cpp Source File

Semaphore.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/Semaphore.h"
00023 #include "rtos/Kernel.h"
00024 #include "platform/mbed_assert.h"
00025 #include "platform/mbed_critical.h"
00026 #include "platform/mbed_error.h"
00027 #include "platform/source/mbed_os_timer.h"
00028 
00029 #include <string.h>
00030 
00031 namespace rtos {
00032 
00033 Semaphore::Semaphore(int32_t count)
00034 {
00035     constructor(count, 0xffff);
00036 }
00037 
00038 Semaphore::Semaphore(int32_t count, uint16_t max_count)
00039 {
00040     constructor(count, max_count);
00041 }
00042 
00043 void Semaphore::constructor(int32_t count, uint16_t max_count)
00044 {
00045 #if MBED_CONF_RTOS_PRESENT
00046     osSemaphoreAttr_t attr = { 0 };
00047     attr.cb_mem = &_obj_mem;
00048     attr.cb_size = sizeof(_obj_mem);
00049     _id = osSemaphoreNew(max_count, count, &attr);
00050     MBED_ASSERT(_id != nullptr);
00051 #else
00052     _count = count;
00053     _max_count = max_count;
00054 #endif
00055 }
00056 
00057 #if !MBED_CONF_RTOS_PRESENT
00058 struct sem_wait_capture {
00059     Semaphore *sem;
00060     bool acquired;
00061 };
00062 
00063 bool Semaphore::semaphore_available(void *handle)
00064 {
00065     sem_wait_capture *wait = static_cast<sem_wait_capture *>(handle);
00066     return wait->acquired = wait->sem->try_acquire();
00067 }
00068 #endif
00069 
00070 bool Semaphore::try_acquire()
00071 {
00072 #if MBED_CONF_RTOS_PRESENT
00073     osStatus_t  status = osSemaphoreAcquire(_id, 0);
00074     if (status != osOK && status != osErrorResource) {
00075         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_SEMAPHORE_LOCK_FAILED), "Semaphore acquire failed", status);
00076     }
00077     return status == osOK;
00078 #else
00079     int32_t old_count = core_util_atomic_load_s32 (&_count);
00080     do {
00081         if (old_count == 0) {
00082             return false;
00083         }
00084     } while (!core_util_atomic_cas_s32 (&_count, &old_count, old_count - 1));
00085     return true;
00086 #endif
00087 }
00088 
00089 #if MBED_CONF_RTOS_PRESENT
00090 /* To sidestep deprecation warnings */
00091 int32_t Semaphore::_wait(uint32_t millisec)
00092 {
00093     osStatus_t  stat = osSemaphoreAcquire(_id, millisec);
00094     switch (stat) {
00095         case osOK:
00096             return osSemaphoreGetCount(_id) + 1;
00097         case osErrorTimeout:
00098         case osErrorResource:
00099             return 0;
00100         case osErrorParameter:
00101         default:
00102             return -1;
00103     }
00104 }
00105 #endif
00106 
00107 int32_t Semaphore::wait(uint32_t millisec)
00108 {
00109 #if MBED_CONF_RTOS_PRESENT
00110     return _wait(millisec);
00111 #else
00112     sem_wait_capture capture = { this, false };
00113     mbed::internal::do_timed_sleep_relative_or_forever(millisec, semaphore_available, &capture);
00114     if (capture.acquired) {
00115         return core_util_atomic_load_s32 (&_count) + 1;
00116     } else {
00117         return 0;
00118     }
00119 #endif
00120 }
00121 
00122 int32_t Semaphore::wait_until(uint64_t millisec)
00123 {
00124 #if MBED_CONF_RTOS_PRESENT
00125     uint64_t now = Kernel::get_ms_count();
00126 
00127     if (now >= millisec) {
00128         return _wait(0);
00129     } else if (millisec - now >= osWaitForever) {
00130         // API permits early return
00131         return _wait(osWaitForever - 1);
00132     } else {
00133         return _wait(millisec - now);
00134     }
00135 #else
00136     sem_wait_capture capture = { this, false };
00137     mbed::internal::do_timed_sleep_absolute(millisec, semaphore_available, &capture);
00138     if (capture.acquired) {
00139         return core_util_atomic_load_s32 (&_count) + 1;
00140     } else {
00141         return 0;
00142     }
00143 #endif
00144 }
00145 
00146 void Semaphore::acquire()
00147 {
00148 #if MBED_CONF_RTOS_PRESENT
00149     osStatus_t  status = osSemaphoreAcquire(_id, osWaitForever);
00150     if (status != osOK) {
00151         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_SEMAPHORE_LOCK_FAILED), "Semaphore acquire failed", status);
00152     }
00153 #else
00154     sem_wait_capture capture = { this, false };
00155     mbed::internal::do_untimed_sleep(semaphore_available, &capture);
00156     if (!capture.acquired) {
00157         MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_SEMAPHORE_LOCK_FAILED), "Semaphore acquire failed");
00158     }
00159 #endif
00160 }
00161 
00162 bool Semaphore::try_acquire_for(uint32_t millisec)
00163 {
00164 #if MBED_CONF_RTOS_PRESENT
00165     osStatus_t  status = osSemaphoreAcquire(_id, millisec);
00166     if (status == osOK) {
00167         return true;
00168     }
00169 
00170     bool success = (status == osErrorResource && millisec == 0) ||
00171                    (status == osErrorTimeout && millisec != osWaitForever);
00172 
00173     if (!success) {
00174         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_SEMAPHORE_LOCK_FAILED), "Semaphore acquire failed", status);
00175     }
00176     return false;
00177 #else
00178     sem_wait_capture capture = { this, false };
00179     mbed::internal::do_timed_sleep_relative_or_forever(millisec, semaphore_available, &capture);
00180     return capture.acquired;
00181 #endif
00182 }
00183 
00184 bool Semaphore::try_acquire_until(uint64_t millisec)
00185 {
00186 #if MBED_CONF_RTOS_PRESENT
00187     uint64_t now = Kernel::get_ms_count();
00188 
00189     if (now >= millisec) {
00190         return try_acquire();
00191     } else if (millisec - now >= osWaitForever) {
00192         // API permits early return
00193         return try_acquire_for(osWaitForever - 1);
00194     } else {
00195         return try_acquire_for(millisec - now);
00196     }
00197 #else
00198     sem_wait_capture capture = { this, false };
00199     mbed::internal::do_timed_sleep_absolute(millisec, semaphore_available, &capture);
00200     return capture.acquired;
00201 #endif
00202 }
00203 
00204 osStatus Semaphore::release(void)
00205 {
00206 #if MBED_CONF_RTOS_PRESENT
00207     return osSemaphoreRelease(_id);
00208 #else
00209     int32_t old_count = core_util_atomic_load_s32 (&_count);
00210     do {
00211         if (old_count == _max_count) {
00212             return osErrorResource;
00213         }
00214     } while (!core_util_atomic_cas_s32 (&_count, &old_count, old_count + 1));
00215 
00216     return osOK;
00217 #endif // MBED_CONF_RTOS_PRESENT
00218 }
00219 
00220 Semaphore::~Semaphore()
00221 {
00222 #if MBED_CONF_RTOS_PRESENT
00223     osSemaphoreDelete(_id);
00224 #endif
00225 }
00226 
00227 }