1

Committer:
valeyev
Date:
Tue Mar 13 07:17:50 2018 +0000
Revision:
0:e056ac8fecf8
looking for...

Who changed what in which revision?

UserRevisionLine numberNew contents of line
valeyev 0:e056ac8fecf8 1 /* mbed Microcontroller Library
valeyev 0:e056ac8fecf8 2 * Copyright (c) 2017-2017 ARM Limited
valeyev 0:e056ac8fecf8 3 *
valeyev 0:e056ac8fecf8 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
valeyev 0:e056ac8fecf8 5 * of this software and associated documentation files (the "Software"), to deal
valeyev 0:e056ac8fecf8 6 * in the Software without restriction, including without limitation the rights
valeyev 0:e056ac8fecf8 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
valeyev 0:e056ac8fecf8 8 * copies of the Software, and to permit persons to whom the Software is
valeyev 0:e056ac8fecf8 9 * furnished to do so, subject to the following conditions:
valeyev 0:e056ac8fecf8 10 *
valeyev 0:e056ac8fecf8 11 * The above copyright notice and this permission notice shall be included in
valeyev 0:e056ac8fecf8 12 * all copies or substantial portions of the Software.
valeyev 0:e056ac8fecf8 13 *
valeyev 0:e056ac8fecf8 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
valeyev 0:e056ac8fecf8 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
valeyev 0:e056ac8fecf8 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
valeyev 0:e056ac8fecf8 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
valeyev 0:e056ac8fecf8 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
valeyev 0:e056ac8fecf8 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
valeyev 0:e056ac8fecf8 20 * SOFTWARE.
valeyev 0:e056ac8fecf8 21 */
valeyev 0:e056ac8fecf8 22 #include "rtos/ConditionVariable.h"
valeyev 0:e056ac8fecf8 23 #include "rtos/Kernel.h"
valeyev 0:e056ac8fecf8 24 #include "rtos/Thread.h"
valeyev 0:e056ac8fecf8 25
valeyev 0:e056ac8fecf8 26 #include "mbed_error.h"
valeyev 0:e056ac8fecf8 27 #include "mbed_assert.h"
valeyev 0:e056ac8fecf8 28
valeyev 0:e056ac8fecf8 29 namespace rtos {
valeyev 0:e056ac8fecf8 30
valeyev 0:e056ac8fecf8 31 ConditionVariable::Waiter::Waiter(): sem(0), prev(NULL), next(NULL), in_list(false)
valeyev 0:e056ac8fecf8 32 {
valeyev 0:e056ac8fecf8 33 // No initialization to do
valeyev 0:e056ac8fecf8 34 }
valeyev 0:e056ac8fecf8 35
valeyev 0:e056ac8fecf8 36 ConditionVariable::ConditionVariable(Mutex &mutex): _mutex(mutex), _wait_list(NULL)
valeyev 0:e056ac8fecf8 37 {
valeyev 0:e056ac8fecf8 38 // No initialization to do
valeyev 0:e056ac8fecf8 39 }
valeyev 0:e056ac8fecf8 40
valeyev 0:e056ac8fecf8 41 void ConditionVariable::wait()
valeyev 0:e056ac8fecf8 42 {
valeyev 0:e056ac8fecf8 43 wait_for(osWaitForever);
valeyev 0:e056ac8fecf8 44 }
valeyev 0:e056ac8fecf8 45
valeyev 0:e056ac8fecf8 46 bool ConditionVariable::wait_for(uint32_t millisec)
valeyev 0:e056ac8fecf8 47 {
valeyev 0:e056ac8fecf8 48 Waiter current_thread;
valeyev 0:e056ac8fecf8 49 MBED_ASSERT(_mutex.get_owner() == Thread::gettid());
valeyev 0:e056ac8fecf8 50 MBED_ASSERT(_mutex._count == 1);
valeyev 0:e056ac8fecf8 51 _add_wait_list(&_wait_list, &current_thread);
valeyev 0:e056ac8fecf8 52
valeyev 0:e056ac8fecf8 53 _mutex.unlock();
valeyev 0:e056ac8fecf8 54
valeyev 0:e056ac8fecf8 55 int32_t sem_count = current_thread.sem.wait(millisec);
valeyev 0:e056ac8fecf8 56 bool timeout = (sem_count > 0) ? false : true;
valeyev 0:e056ac8fecf8 57
valeyev 0:e056ac8fecf8 58 _mutex.lock();
valeyev 0:e056ac8fecf8 59
valeyev 0:e056ac8fecf8 60 if (current_thread.in_list) {
valeyev 0:e056ac8fecf8 61 _remove_wait_list(&_wait_list, &current_thread);
valeyev 0:e056ac8fecf8 62 }
valeyev 0:e056ac8fecf8 63
valeyev 0:e056ac8fecf8 64 return timeout;
valeyev 0:e056ac8fecf8 65 }
valeyev 0:e056ac8fecf8 66
valeyev 0:e056ac8fecf8 67 bool ConditionVariable::wait_until(uint64_t millisec)
valeyev 0:e056ac8fecf8 68 {
valeyev 0:e056ac8fecf8 69 uint64_t now = Kernel::get_ms_count();
valeyev 0:e056ac8fecf8 70
valeyev 0:e056ac8fecf8 71 if (now >= millisec) {
valeyev 0:e056ac8fecf8 72 // Time has already passed - standard behaviour is to
valeyev 0:e056ac8fecf8 73 // treat as a "try".
valeyev 0:e056ac8fecf8 74 return wait_for(0);
valeyev 0:e056ac8fecf8 75 } else if (millisec - now >= osWaitForever) {
valeyev 0:e056ac8fecf8 76 // Exceeds maximum delay of underlying wait_for -
valeyev 0:e056ac8fecf8 77 // spuriously wake after 49 days, indicating no timeout.
valeyev 0:e056ac8fecf8 78 wait_for(osWaitForever - 1);
valeyev 0:e056ac8fecf8 79 return false;
valeyev 0:e056ac8fecf8 80 } else {
valeyev 0:e056ac8fecf8 81 return wait_for(millisec - now);
valeyev 0:e056ac8fecf8 82 }
valeyev 0:e056ac8fecf8 83 }
valeyev 0:e056ac8fecf8 84
valeyev 0:e056ac8fecf8 85 void ConditionVariable::notify_one()
valeyev 0:e056ac8fecf8 86 {
valeyev 0:e056ac8fecf8 87 MBED_ASSERT(_mutex.get_owner() == Thread::gettid());
valeyev 0:e056ac8fecf8 88 if (_wait_list != NULL) {
valeyev 0:e056ac8fecf8 89 _wait_list->sem.release();
valeyev 0:e056ac8fecf8 90 _remove_wait_list(&_wait_list, _wait_list);
valeyev 0:e056ac8fecf8 91 }
valeyev 0:e056ac8fecf8 92 }
valeyev 0:e056ac8fecf8 93
valeyev 0:e056ac8fecf8 94 void ConditionVariable::notify_all()
valeyev 0:e056ac8fecf8 95 {
valeyev 0:e056ac8fecf8 96 MBED_ASSERT(_mutex.get_owner() == Thread::gettid());
valeyev 0:e056ac8fecf8 97 while (_wait_list != NULL) {
valeyev 0:e056ac8fecf8 98 _wait_list->sem.release();
valeyev 0:e056ac8fecf8 99 _remove_wait_list(&_wait_list, _wait_list);
valeyev 0:e056ac8fecf8 100 }
valeyev 0:e056ac8fecf8 101 }
valeyev 0:e056ac8fecf8 102
valeyev 0:e056ac8fecf8 103 void ConditionVariable::_add_wait_list(Waiter **wait_list, Waiter *waiter)
valeyev 0:e056ac8fecf8 104 {
valeyev 0:e056ac8fecf8 105 if (NULL == *wait_list) {
valeyev 0:e056ac8fecf8 106 // Nothing in the list so add it directly.
valeyev 0:e056ac8fecf8 107 // Update prev and next pointer to reference self
valeyev 0:e056ac8fecf8 108 *wait_list = waiter;
valeyev 0:e056ac8fecf8 109 waiter->next = waiter;
valeyev 0:e056ac8fecf8 110 waiter->prev = waiter;
valeyev 0:e056ac8fecf8 111 } else {
valeyev 0:e056ac8fecf8 112 // Add after the last element
valeyev 0:e056ac8fecf8 113 Waiter *first = *wait_list;
valeyev 0:e056ac8fecf8 114 Waiter *last = (*wait_list)->prev;
valeyev 0:e056ac8fecf8 115
valeyev 0:e056ac8fecf8 116 // Update new entry
valeyev 0:e056ac8fecf8 117 waiter->next = first;
valeyev 0:e056ac8fecf8 118 waiter->prev = last;
valeyev 0:e056ac8fecf8 119
valeyev 0:e056ac8fecf8 120 // Insert into the list
valeyev 0:e056ac8fecf8 121 first->prev = waiter;
valeyev 0:e056ac8fecf8 122 last->next = waiter;
valeyev 0:e056ac8fecf8 123 }
valeyev 0:e056ac8fecf8 124 waiter->in_list = true;
valeyev 0:e056ac8fecf8 125 }
valeyev 0:e056ac8fecf8 126
valeyev 0:e056ac8fecf8 127 void ConditionVariable::_remove_wait_list(Waiter **wait_list, Waiter *waiter)
valeyev 0:e056ac8fecf8 128 {
valeyev 0:e056ac8fecf8 129 Waiter *prev = waiter->prev;
valeyev 0:e056ac8fecf8 130 Waiter *next = waiter->next;
valeyev 0:e056ac8fecf8 131
valeyev 0:e056ac8fecf8 132 // Remove from list
valeyev 0:e056ac8fecf8 133 prev->next = waiter->next;
valeyev 0:e056ac8fecf8 134 next->prev = waiter->prev;
valeyev 0:e056ac8fecf8 135 *wait_list = waiter->next;
valeyev 0:e056ac8fecf8 136
valeyev 0:e056ac8fecf8 137 if (*wait_list == waiter) {
valeyev 0:e056ac8fecf8 138 // This was the last element in the list
valeyev 0:e056ac8fecf8 139 *wait_list = NULL;
valeyev 0:e056ac8fecf8 140 }
valeyev 0:e056ac8fecf8 141
valeyev 0:e056ac8fecf8 142 // Invalidate pointers
valeyev 0:e056ac8fecf8 143 waiter->next = NULL;
valeyev 0:e056ac8fecf8 144 waiter->prev = NULL;
valeyev 0:e056ac8fecf8 145 waiter->in_list = false;
valeyev 0:e056ac8fecf8 146 }
valeyev 0:e056ac8fecf8 147
valeyev 0:e056ac8fecf8 148 ConditionVariable::~ConditionVariable()
valeyev 0:e056ac8fecf8 149 {
valeyev 0:e056ac8fecf8 150 MBED_ASSERT(NULL == _wait_list);
valeyev 0:e056ac8fecf8 151 }
valeyev 0:e056ac8fecf8 152
valeyev 0:e056ac8fecf8 153 }