Entrega 3er corte - sistemas embebidos

Committer:
Bethory
Date:
Wed May 30 04:46:28 2018 +0000
Revision:
1:fcdb45ee95b9
Parent:
0:6ad07c9019fd
Entrega Final

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bethory 0:6ad07c9019fd 1 /* mbed Microcontroller Library
Bethory 0:6ad07c9019fd 2 * Copyright (c) 2017-2017 ARM Limited
Bethory 0:6ad07c9019fd 3 *
Bethory 0:6ad07c9019fd 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
Bethory 0:6ad07c9019fd 5 * of this software and associated documentation files (the "Software"), to deal
Bethory 0:6ad07c9019fd 6 * in the Software without restriction, including without limitation the rights
Bethory 0:6ad07c9019fd 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Bethory 0:6ad07c9019fd 8 * copies of the Software, and to permit persons to whom the Software is
Bethory 0:6ad07c9019fd 9 * furnished to do so, subject to the following conditions:
Bethory 0:6ad07c9019fd 10 *
Bethory 0:6ad07c9019fd 11 * The above copyright notice and this permission notice shall be included in
Bethory 0:6ad07c9019fd 12 * all copies or substantial portions of the Software.
Bethory 0:6ad07c9019fd 13 *
Bethory 0:6ad07c9019fd 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Bethory 0:6ad07c9019fd 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Bethory 0:6ad07c9019fd 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Bethory 0:6ad07c9019fd 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Bethory 0:6ad07c9019fd 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Bethory 0:6ad07c9019fd 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Bethory 0:6ad07c9019fd 20 * SOFTWARE.
Bethory 0:6ad07c9019fd 21 */
Bethory 0:6ad07c9019fd 22 #ifndef CONDITIONVARIABLE_H
Bethory 0:6ad07c9019fd 23 #define CONDITIONVARIABLE_H
Bethory 0:6ad07c9019fd 24
Bethory 0:6ad07c9019fd 25 #include <stdint.h>
Bethory 0:6ad07c9019fd 26 #include "cmsis_os.h"
Bethory 0:6ad07c9019fd 27 #include "rtos/Mutex.h"
Bethory 0:6ad07c9019fd 28 #include "rtos/Semaphore.h"
Bethory 0:6ad07c9019fd 29
Bethory 0:6ad07c9019fd 30 #include "platform/NonCopyable.h"
Bethory 0:6ad07c9019fd 31
Bethory 0:6ad07c9019fd 32 namespace rtos {
Bethory 0:6ad07c9019fd 33 /** \addtogroup rtos */
Bethory 0:6ad07c9019fd 34 /** @{*/
Bethory 0:6ad07c9019fd 35
Bethory 0:6ad07c9019fd 36 struct Waiter;
Bethory 0:6ad07c9019fd 37
Bethory 0:6ad07c9019fd 38 /** This class provides a safe way to wait for or send notifications of condition changes
Bethory 0:6ad07c9019fd 39 *
Bethory 0:6ad07c9019fd 40 * This class is used in conjunction with a mutex to safely wait for or
Bethory 0:6ad07c9019fd 41 * notify waiters of condition changes to a resource accessible by multiple
Bethory 0:6ad07c9019fd 42 * threads.
Bethory 0:6ad07c9019fd 43 *
Bethory 0:6ad07c9019fd 44 * # Defined behavior
Bethory 0:6ad07c9019fd 45 * - All threads waiting on the condition variable wake when
Bethory 0:6ad07c9019fd 46 * ConditionVariable::notify_all is called.
Bethory 0:6ad07c9019fd 47 * - If one or more threads are waiting on the condition variable at least
Bethory 0:6ad07c9019fd 48 * one of them wakes when ConditionVariable::notify is called.
Bethory 0:6ad07c9019fd 49 *
Bethory 0:6ad07c9019fd 50 * # Undefined behavior
Bethory 0:6ad07c9019fd 51 * - The thread which is unblocked on ConditionVariable::notify_one is
Bethory 0:6ad07c9019fd 52 * undefined if there are multiple waiters.
Bethory 0:6ad07c9019fd 53 * - The order which in which waiting threads acquire the condition variable's
Bethory 0:6ad07c9019fd 54 * mutex after ConditionVariable::notify_all is called is undefined.
Bethory 0:6ad07c9019fd 55 * - When ConditionVariable::notify_one or ConditionVariable::notify_all is
Bethory 0:6ad07c9019fd 56 * called and there are one or more waiters and one or more threads attempting
Bethory 0:6ad07c9019fd 57 * to acquire the condition variable's mutex the order in which the mutex is
Bethory 0:6ad07c9019fd 58 * acquired is undefined.
Bethory 0:6ad07c9019fd 59 * - The behavior of ConditionVariable::wait and ConditionVariable::wait_for
Bethory 0:6ad07c9019fd 60 * is undefined if the condition variable's mutex is locked more than once by
Bethory 0:6ad07c9019fd 61 * the calling thread.
Bethory 0:6ad07c9019fd 62 * - Spurious notifications (not triggered by the application) can occur
Bethory 0:6ad07c9019fd 63 * and it is not defined when these occur.
Bethory 0:6ad07c9019fd 64 *
Bethory 0:6ad07c9019fd 65 * @note Synchronization level: Thread safe
Bethory 0:6ad07c9019fd 66 *
Bethory 0:6ad07c9019fd 67 * Example:
Bethory 0:6ad07c9019fd 68 * @code
Bethory 0:6ad07c9019fd 69 * #include "mbed.h"
Bethory 0:6ad07c9019fd 70 *
Bethory 0:6ad07c9019fd 71 * Mutex mutex;
Bethory 0:6ad07c9019fd 72 * ConditionVariable cond(mutex);
Bethory 0:6ad07c9019fd 73 *
Bethory 0:6ad07c9019fd 74 * // These variables are protected by locking mutex
Bethory 0:6ad07c9019fd 75 * uint32_t count = 0;
Bethory 0:6ad07c9019fd 76 * bool done = false;
Bethory 0:6ad07c9019fd 77 *
Bethory 0:6ad07c9019fd 78 * void worker_thread()
Bethory 0:6ad07c9019fd 79 * {
Bethory 0:6ad07c9019fd 80 * mutex.lock();
Bethory 0:6ad07c9019fd 81 * do {
Bethory 0:6ad07c9019fd 82 * printf("Worker: Count %lu\r\n", count);
Bethory 0:6ad07c9019fd 83 *
Bethory 0:6ad07c9019fd 84 * // Wait for a condition to change
Bethory 0:6ad07c9019fd 85 * cond.wait();
Bethory 0:6ad07c9019fd 86 *
Bethory 0:6ad07c9019fd 87 * } while (!done);
Bethory 0:6ad07c9019fd 88 * printf("Worker: Exiting\r\n");
Bethory 0:6ad07c9019fd 89 * mutex.unlock();
Bethory 0:6ad07c9019fd 90 * }
Bethory 0:6ad07c9019fd 91 *
Bethory 0:6ad07c9019fd 92 * int main() {
Bethory 0:6ad07c9019fd 93 * Thread thread;
Bethory 0:6ad07c9019fd 94 * thread.start(worker_thread);
Bethory 0:6ad07c9019fd 95 *
Bethory 0:6ad07c9019fd 96 * for (int i = 0; i < 5; i++) {
Bethory 0:6ad07c9019fd 97 *
Bethory 0:6ad07c9019fd 98 * mutex.lock();
Bethory 0:6ad07c9019fd 99 * // Change count and notify waiters of this
Bethory 0:6ad07c9019fd 100 * count++;
Bethory 0:6ad07c9019fd 101 * printf("Main: Set count to %lu\r\n", count);
Bethory 0:6ad07c9019fd 102 * cond.notify_all();
Bethory 0:6ad07c9019fd 103 * mutex.unlock();
Bethory 0:6ad07c9019fd 104 *
Bethory 0:6ad07c9019fd 105 * wait(1.0);
Bethory 0:6ad07c9019fd 106 * }
Bethory 0:6ad07c9019fd 107 *
Bethory 0:6ad07c9019fd 108 * mutex.lock();
Bethory 0:6ad07c9019fd 109 * // Change done and notify waiters of this
Bethory 0:6ad07c9019fd 110 * done = true;
Bethory 0:6ad07c9019fd 111 * printf("Main: Set done\r\n");
Bethory 0:6ad07c9019fd 112 * cond.notify_all();
Bethory 0:6ad07c9019fd 113 * mutex.unlock();
Bethory 0:6ad07c9019fd 114 *
Bethory 0:6ad07c9019fd 115 * thread.join();
Bethory 0:6ad07c9019fd 116 * }
Bethory 0:6ad07c9019fd 117 * @endcode
Bethory 0:6ad07c9019fd 118 */
Bethory 0:6ad07c9019fd 119 class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
Bethory 0:6ad07c9019fd 120 public:
Bethory 0:6ad07c9019fd 121 /** Create and Initialize a ConditionVariable object
Bethory 0:6ad07c9019fd 122 *
Bethory 0:6ad07c9019fd 123 * @note You cannot call this function from ISR context.
Bethory 0:6ad07c9019fd 124 */
Bethory 0:6ad07c9019fd 125 ConditionVariable(Mutex &mutex);
Bethory 0:6ad07c9019fd 126
Bethory 0:6ad07c9019fd 127 /** Wait for a notification
Bethory 0:6ad07c9019fd 128 *
Bethory 0:6ad07c9019fd 129 * Wait until a notification occurs.
Bethory 0:6ad07c9019fd 130 *
Bethory 0:6ad07c9019fd 131 * @note - The thread calling this function must be the owner of the
Bethory 0:6ad07c9019fd 132 * ConditionVariable's mutex and it must be locked exactly once
Bethory 0:6ad07c9019fd 133 * @note - Spurious notifications can occur so the caller of this API
Bethory 0:6ad07c9019fd 134 * should check to make sure the condition they are waiting on has
Bethory 0:6ad07c9019fd 135 * been met
Bethory 0:6ad07c9019fd 136 *
Bethory 0:6ad07c9019fd 137 * Example:
Bethory 0:6ad07c9019fd 138 * @code
Bethory 0:6ad07c9019fd 139 * mutex.lock();
Bethory 0:6ad07c9019fd 140 * while (!condition_met) {
Bethory 0:6ad07c9019fd 141 * cond.wait();
Bethory 0:6ad07c9019fd 142 * }
Bethory 0:6ad07c9019fd 143 *
Bethory 0:6ad07c9019fd 144 * function_to_handle_condition();
Bethory 0:6ad07c9019fd 145 *
Bethory 0:6ad07c9019fd 146 * mutex.unlock();
Bethory 0:6ad07c9019fd 147 * @endcode
Bethory 0:6ad07c9019fd 148 *
Bethory 0:6ad07c9019fd 149 * @note You cannot call this function from ISR context.
Bethory 0:6ad07c9019fd 150 */
Bethory 0:6ad07c9019fd 151 void wait();
Bethory 0:6ad07c9019fd 152
Bethory 0:6ad07c9019fd 153 /** Wait for a notification until specified time
Bethory 0:6ad07c9019fd 154 *
Bethory 0:6ad07c9019fd 155 * @param millisec absolute end time referenced to Kernel::get_ms_count()
Bethory 0:6ad07c9019fd 156 * @return true if a timeout occurred, false otherwise.
Bethory 0:6ad07c9019fd 157 *
Bethory 0:6ad07c9019fd 158 * @note - The thread calling this function must be the owner of the
Bethory 0:6ad07c9019fd 159 * ConditionVariable's mutex and it must be locked exactly once
Bethory 0:6ad07c9019fd 160 * @note - Spurious notifications can occur so the caller of this API
Bethory 0:6ad07c9019fd 161 * should check to make sure the condition they are waiting on has
Bethory 0:6ad07c9019fd 162 * been met
Bethory 0:6ad07c9019fd 163 *
Bethory 0:6ad07c9019fd 164 * Example:
Bethory 0:6ad07c9019fd 165 * @code
Bethory 0:6ad07c9019fd 166 * mutex.lock();
Bethory 0:6ad07c9019fd 167 * uint64_t end_time = Kernel::get_ms_count() + COND_WAIT_TIMEOUT;
Bethory 0:6ad07c9019fd 168 *
Bethory 0:6ad07c9019fd 169 * while (!condition_met) {
Bethory 0:6ad07c9019fd 170 * if (cond.wait_until(end_time)) {
Bethory 0:6ad07c9019fd 171 * break;
Bethory 0:6ad07c9019fd 172 * }
Bethory 0:6ad07c9019fd 173 * }
Bethory 0:6ad07c9019fd 174 *
Bethory 0:6ad07c9019fd 175 * if (condition_met) {
Bethory 0:6ad07c9019fd 176 * function_to_handle_condition();
Bethory 0:6ad07c9019fd 177 * }
Bethory 0:6ad07c9019fd 178 *
Bethory 0:6ad07c9019fd 179 * mutex.unlock();
Bethory 0:6ad07c9019fd 180 * @endcode
Bethory 0:6ad07c9019fd 181 *
Bethory 0:6ad07c9019fd 182 * @note You cannot call this function from ISR context.
Bethory 0:6ad07c9019fd 183 */
Bethory 0:6ad07c9019fd 184 bool wait_until(uint64_t millisec);
Bethory 0:6ad07c9019fd 185
Bethory 0:6ad07c9019fd 186 /** Wait for a notification or timeout
Bethory 0:6ad07c9019fd 187 *
Bethory 0:6ad07c9019fd 188 * @param millisec timeout value or osWaitForever in case of no time-out.
Bethory 0:6ad07c9019fd 189 * @return true if a timeout occurred, false otherwise.
Bethory 0:6ad07c9019fd 190 *
Bethory 0:6ad07c9019fd 191 * @note - The thread calling this function must be the owner of the
Bethory 0:6ad07c9019fd 192 * ConditionVariable's mutex and it must be locked exactly once
Bethory 0:6ad07c9019fd 193 * @note - Spurious notifications can occur so the caller of this API
Bethory 0:6ad07c9019fd 194 * should check to make sure the condition they are waiting on has
Bethory 0:6ad07c9019fd 195 * been met
Bethory 0:6ad07c9019fd 196 *
Bethory 0:6ad07c9019fd 197 * Example:
Bethory 0:6ad07c9019fd 198 * @code
Bethory 0:6ad07c9019fd 199 * mutex.lock();
Bethory 0:6ad07c9019fd 200 *
Bethory 0:6ad07c9019fd 201 * while (!condition_met) {
Bethory 0:6ad07c9019fd 202 * cond.wait_for(MAX_SLEEP_TIME);
Bethory 0:6ad07c9019fd 203 * if (!condition_met) {
Bethory 0:6ad07c9019fd 204 * do_other_work_while_condition_false();
Bethory 0:6ad07c9019fd 205 * }
Bethory 0:6ad07c9019fd 206 * }
Bethory 0:6ad07c9019fd 207 *
Bethory 0:6ad07c9019fd 208 * if (condition_met) {
Bethory 0:6ad07c9019fd 209 * function_to_handle_condition();
Bethory 0:6ad07c9019fd 210 * }
Bethory 0:6ad07c9019fd 211 *
Bethory 0:6ad07c9019fd 212 * mutex.unlock();
Bethory 0:6ad07c9019fd 213 * @endcode
Bethory 0:6ad07c9019fd 214 *
Bethory 0:6ad07c9019fd 215 * @note You cannot call this function from ISR context.
Bethory 0:6ad07c9019fd 216 */
Bethory 0:6ad07c9019fd 217 bool wait_for(uint32_t millisec);
Bethory 0:6ad07c9019fd 218
Bethory 0:6ad07c9019fd 219 /** Notify one waiter on this condition variable that a condition changed.
Bethory 0:6ad07c9019fd 220 *
Bethory 0:6ad07c9019fd 221 * @note - The thread calling this function must be the owner of the ConditionVariable's mutex
Bethory 0:6ad07c9019fd 222 *
Bethory 0:6ad07c9019fd 223 * @note You cannot call this function from ISR context.
Bethory 0:6ad07c9019fd 224 */
Bethory 0:6ad07c9019fd 225 void notify_one();
Bethory 0:6ad07c9019fd 226
Bethory 0:6ad07c9019fd 227 /** Notify all waiters on this condition variable that a condition changed.
Bethory 0:6ad07c9019fd 228 *
Bethory 0:6ad07c9019fd 229 * @note - The thread calling this function must be the owner of the ConditionVariable's mutex
Bethory 0:6ad07c9019fd 230 *
Bethory 0:6ad07c9019fd 231 * @note You cannot call this function from ISR context.
Bethory 0:6ad07c9019fd 232 */
Bethory 0:6ad07c9019fd 233 void notify_all();
Bethory 0:6ad07c9019fd 234
Bethory 0:6ad07c9019fd 235 /** ConditionVariable destructor
Bethory 0:6ad07c9019fd 236 *
Bethory 0:6ad07c9019fd 237 * @note You cannot call this function from ISR context.
Bethory 0:6ad07c9019fd 238 */
Bethory 0:6ad07c9019fd 239 ~ConditionVariable();
Bethory 0:6ad07c9019fd 240
Bethory 0:6ad07c9019fd 241 protected:
Bethory 0:6ad07c9019fd 242 struct Waiter {
Bethory 0:6ad07c9019fd 243 Waiter();
Bethory 0:6ad07c9019fd 244 Semaphore sem;
Bethory 0:6ad07c9019fd 245 Waiter *prev;
Bethory 0:6ad07c9019fd 246 Waiter *next;
Bethory 0:6ad07c9019fd 247 bool in_list;
Bethory 0:6ad07c9019fd 248 };
Bethory 0:6ad07c9019fd 249
Bethory 0:6ad07c9019fd 250 static void _add_wait_list(Waiter **wait_list, Waiter *waiter);
Bethory 0:6ad07c9019fd 251 static void _remove_wait_list(Waiter **wait_list, Waiter *waiter);
Bethory 0:6ad07c9019fd 252 Mutex &_mutex;
Bethory 0:6ad07c9019fd 253 Waiter *_wait_list;
Bethory 0:6ad07c9019fd 254 };
Bethory 0:6ad07c9019fd 255
Bethory 0:6ad07c9019fd 256 }
Bethory 0:6ad07c9019fd 257 #endif
Bethory 0:6ad07c9019fd 258
Bethory 0:6ad07c9019fd 259 /** @}*/