Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 }
Generated on Tue Jul 12 2022 13:54:49 by
