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
ConditionVariable.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017-2017 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/ConditionVariable.h" 00023 #include "rtos/Kernel.h" 00024 #include "rtos/ThisThread.h" 00025 00026 #include "platform/mbed_error.h" 00027 #include "platform/mbed_assert.h" 00028 00029 #if MBED_CONF_RTOS_PRESENT 00030 00031 namespace rtos { 00032 00033 ConditionVariable::Waiter::Waiter(): sem(0), prev(nullptr), next(nullptr), in_list(false) 00034 { 00035 // No initialization to do 00036 } 00037 00038 ConditionVariable::ConditionVariable(Mutex &mutex): _mutex(mutex), _wait_list(nullptr) 00039 { 00040 // No initialization to do 00041 } 00042 00043 void ConditionVariable::wait() 00044 { 00045 wait_for(osWaitForever); 00046 } 00047 00048 bool ConditionVariable::wait_for(uint32_t millisec) 00049 { 00050 Waiter current_thread; 00051 MBED_ASSERT(_mutex.get_owner() == ThisThread::get_id()); 00052 MBED_ASSERT(_mutex._count == 1); 00053 _add_wait_list(&_wait_list, ¤t_thread); 00054 00055 _mutex.unlock(); 00056 00057 bool timeout = !current_thread.sem.try_acquire_for(millisec); 00058 00059 _mutex.lock(); 00060 00061 if (current_thread.in_list) { 00062 _remove_wait_list(&_wait_list, ¤t_thread); 00063 } 00064 00065 return timeout; 00066 } 00067 00068 bool ConditionVariable::wait_until(uint64_t millisec) 00069 { 00070 uint64_t now = Kernel::get_ms_count(); 00071 00072 if (now >= millisec) { 00073 // Time has already passed - standard behaviour is to 00074 // treat as a "try". 00075 return wait_for(0); 00076 } else if (millisec - now >= osWaitForever) { 00077 // Exceeds maximum delay of underlying wait_for - 00078 // spuriously wake after 49 days, indicating no timeout. 00079 wait_for(osWaitForever - 1); 00080 return false; 00081 } else { 00082 return wait_for(millisec - now); 00083 } 00084 } 00085 00086 void ConditionVariable::notify_one() 00087 { 00088 MBED_ASSERT(_mutex.get_owner() == ThisThread::get_id()); 00089 if (_wait_list != nullptr) { 00090 _wait_list->sem.release(); 00091 _remove_wait_list(&_wait_list, _wait_list); 00092 } 00093 } 00094 00095 void ConditionVariable::notify_all() 00096 { 00097 MBED_ASSERT(_mutex.get_owner() == ThisThread::get_id()); 00098 while (_wait_list != nullptr) { 00099 _wait_list->sem.release(); 00100 _remove_wait_list(&_wait_list, _wait_list); 00101 } 00102 } 00103 00104 void ConditionVariable::_add_wait_list(Waiter **wait_list, Waiter *waiter) 00105 { 00106 if (nullptr == *wait_list) { 00107 // Nothing in the list so add it directly. 00108 // Update prev and next pointer to reference self 00109 *wait_list = waiter; 00110 waiter->next = waiter; 00111 waiter->prev = waiter; 00112 } else { 00113 // Add after the last element 00114 Waiter *first = *wait_list; 00115 Waiter *last = (*wait_list)->prev; 00116 00117 // Update new entry 00118 waiter->next = first; 00119 waiter->prev = last; 00120 00121 // Insert into the list 00122 first->prev = waiter; 00123 last->next = waiter; 00124 } 00125 waiter->in_list = true; 00126 } 00127 00128 void ConditionVariable::_remove_wait_list(Waiter **wait_list, Waiter *waiter) 00129 { 00130 Waiter *prev = waiter->prev; 00131 Waiter *next = waiter->next; 00132 00133 // Remove from list 00134 prev->next = waiter->next; 00135 next->prev = waiter->prev; 00136 *wait_list = waiter->next; 00137 00138 if (*wait_list == waiter) { 00139 // This was the last element in the list 00140 *wait_list = nullptr; 00141 } 00142 00143 // Invalidate pointers 00144 waiter->next = nullptr; 00145 waiter->prev = nullptr; 00146 waiter->in_list = false; 00147 } 00148 00149 ConditionVariable::~ConditionVariable() 00150 { 00151 MBED_ASSERT(nullptr == _wait_list); 00152 } 00153 00154 } 00155 00156 #endif
Generated on Tue Jul 12 2022 13:54:13 by
