mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #3648 from c1728p9/condition_variable
Add ConditionVariable to mbed rtospull/5471/head
						commit
						c45dd269f5
					
				| 
						 | 
				
			
			@ -0,0 +1,111 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2017 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "utest.h"
 | 
			
		||||
#include "rtos.h"
 | 
			
		||||
 | 
			
		||||
#if defined(MBED_RTOS_SINGLE_THREAD)
 | 
			
		||||
  #error [NOT_SUPPORTED] test not supported
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
#define TEST_STACK_SIZE 512
 | 
			
		||||
#define TEST_DELAY 10
 | 
			
		||||
 | 
			
		||||
static int change_counter = 0;
 | 
			
		||||
static Mutex mutex;
 | 
			
		||||
static ConditionVariable cond(mutex);
 | 
			
		||||
 | 
			
		||||
void increment_on_signal()
 | 
			
		||||
{
 | 
			
		||||
    mutex.lock();
 | 
			
		||||
 | 
			
		||||
    cond.wait();
 | 
			
		||||
    change_counter++;
 | 
			
		||||
 | 
			
		||||
    mutex.unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_notify_one()
 | 
			
		||||
{
 | 
			
		||||
    Thread t1(osPriorityNormal, TEST_STACK_SIZE);
 | 
			
		||||
    Thread t2(osPriorityNormal, TEST_STACK_SIZE);
 | 
			
		||||
 | 
			
		||||
    change_counter = 0;
 | 
			
		||||
    t1.start(increment_on_signal);
 | 
			
		||||
    t2.start(increment_on_signal);
 | 
			
		||||
 | 
			
		||||
    wait_ms(TEST_DELAY);
 | 
			
		||||
    TEST_ASSERT_EQUAL(0, change_counter);
 | 
			
		||||
 | 
			
		||||
    mutex.lock();
 | 
			
		||||
    cond.notify_one();
 | 
			
		||||
    mutex.unlock();
 | 
			
		||||
 | 
			
		||||
    wait_ms(TEST_DELAY);
 | 
			
		||||
    TEST_ASSERT_EQUAL(1, change_counter);
 | 
			
		||||
 | 
			
		||||
    mutex.lock();
 | 
			
		||||
    cond.notify_one();
 | 
			
		||||
    mutex.unlock();
 | 
			
		||||
 | 
			
		||||
    t1.join();
 | 
			
		||||
    t2.join();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_notify_all()
 | 
			
		||||
{
 | 
			
		||||
    Thread t1(osPriorityNormal, TEST_STACK_SIZE);
 | 
			
		||||
    Thread t2(osPriorityNormal, TEST_STACK_SIZE);
 | 
			
		||||
 | 
			
		||||
    change_counter = 0;
 | 
			
		||||
    t1.start(increment_on_signal);
 | 
			
		||||
    t2.start(increment_on_signal);
 | 
			
		||||
 | 
			
		||||
    wait_ms(TEST_DELAY);
 | 
			
		||||
    TEST_ASSERT_EQUAL(0, change_counter);
 | 
			
		||||
 | 
			
		||||
    mutex.lock();
 | 
			
		||||
    cond.notify_all();
 | 
			
		||||
    mutex.unlock();
 | 
			
		||||
 | 
			
		||||
    wait_ms(TEST_DELAY);
 | 
			
		||||
    TEST_ASSERT_EQUAL(2, change_counter);
 | 
			
		||||
 | 
			
		||||
    t1.join();
 | 
			
		||||
    t2.join();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t test_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
    GREENTEA_SETUP(10, "default_auto");
 | 
			
		||||
    return verbose_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Case cases[] = {
 | 
			
		||||
    Case("Test notify one", test_notify_one),
 | 
			
		||||
    Case("Test notify all", test_notify_all),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Specification specification(test_setup, cases);
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    return !Harness::run(specification);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,136 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2017-2017 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
#include "rtos/ConditionVariable.h"
 | 
			
		||||
#include "rtos/Semaphore.h"
 | 
			
		||||
#include "rtos/Thread.h"
 | 
			
		||||
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
#include "mbed_assert.h"
 | 
			
		||||
 | 
			
		||||
namespace rtos {
 | 
			
		||||
 | 
			
		||||
#define RESUME_SIGNAL      (1 << 15)
 | 
			
		||||
 | 
			
		||||
struct Waiter {
 | 
			
		||||
    Waiter();
 | 
			
		||||
    Semaphore sem;
 | 
			
		||||
    Waiter *prev;
 | 
			
		||||
    Waiter *next;
 | 
			
		||||
    bool in_list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Waiter::Waiter(): sem(0), prev(NULL), next(NULL), in_list(false)
 | 
			
		||||
{
 | 
			
		||||
    // No initialization to do
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ConditionVariable::ConditionVariable(Mutex &mutex): _mutex(mutex), _wait_list(NULL)
 | 
			
		||||
{
 | 
			
		||||
    // No initialization to do
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConditionVariable::wait()
 | 
			
		||||
{
 | 
			
		||||
    wait_for(osWaitForever);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ConditionVariable::wait_for(uint32_t millisec)
 | 
			
		||||
{
 | 
			
		||||
    Waiter current_thread;
 | 
			
		||||
    MBED_ASSERT(_mutex.get_owner() == Thread::gettid());
 | 
			
		||||
    MBED_ASSERT(_mutex._count == 1);
 | 
			
		||||
    _add_wait_list(¤t_thread);
 | 
			
		||||
 | 
			
		||||
    _mutex.unlock();
 | 
			
		||||
 | 
			
		||||
    int32_t sem_count = current_thread.sem.wait(millisec);
 | 
			
		||||
    bool timeout = (sem_count > 0) ? false : true;
 | 
			
		||||
 | 
			
		||||
    _mutex.lock();
 | 
			
		||||
 | 
			
		||||
    if (current_thread.in_list) {
 | 
			
		||||
        _remove_wait_list(¤t_thread);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return timeout;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConditionVariable::notify_one()
 | 
			
		||||
{
 | 
			
		||||
    MBED_ASSERT(_mutex.get_owner() == Thread::gettid());
 | 
			
		||||
    if (_wait_list != NULL) {
 | 
			
		||||
        _wait_list->sem.release();
 | 
			
		||||
        _remove_wait_list(_wait_list);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConditionVariable::notify_all()
 | 
			
		||||
{
 | 
			
		||||
    MBED_ASSERT(_mutex.get_owner() == Thread::gettid());
 | 
			
		||||
    while (_wait_list != NULL) {
 | 
			
		||||
        _wait_list->sem.release();
 | 
			
		||||
        _remove_wait_list(_wait_list);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConditionVariable::_add_wait_list(Waiter * waiter)
 | 
			
		||||
{
 | 
			
		||||
    if (NULL == _wait_list) {
 | 
			
		||||
        // Nothing in the list so add it directly.
 | 
			
		||||
        // Update prev pointer to reference self
 | 
			
		||||
        _wait_list = waiter;
 | 
			
		||||
        waiter->prev = waiter;
 | 
			
		||||
    } else {
 | 
			
		||||
        // Add after the last element
 | 
			
		||||
        Waiter *last = _wait_list->prev;
 | 
			
		||||
        last->next = waiter;
 | 
			
		||||
        waiter->prev = last;
 | 
			
		||||
        _wait_list->prev = waiter;
 | 
			
		||||
    }
 | 
			
		||||
    waiter->in_list = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConditionVariable::_remove_wait_list(Waiter * waiter)
 | 
			
		||||
{
 | 
			
		||||
    // Remove this element from the start of the list
 | 
			
		||||
    Waiter * next = waiter->next;
 | 
			
		||||
    if (waiter == _wait_list) {
 | 
			
		||||
        _wait_list = next;
 | 
			
		||||
    }
 | 
			
		||||
    if (next != NULL) {
 | 
			
		||||
        next = waiter->prev;
 | 
			
		||||
    }
 | 
			
		||||
    Waiter * prev = waiter->prev;
 | 
			
		||||
    if (prev != NULL) {
 | 
			
		||||
        prev = waiter->next;
 | 
			
		||||
    }
 | 
			
		||||
    waiter->next = NULL;
 | 
			
		||||
    waiter->prev = NULL;
 | 
			
		||||
    waiter->in_list = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ConditionVariable::~ConditionVariable()
 | 
			
		||||
{
 | 
			
		||||
    MBED_ASSERT(NULL == _wait_list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,205 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2017-2017 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef CONDITIONVARIABLE_H
 | 
			
		||||
#define CONDITIONVARIABLE_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "cmsis_os.h"
 | 
			
		||||
#include "rtos/Mutex.h"
 | 
			
		||||
 | 
			
		||||
#include "platform/NonCopyable.h"
 | 
			
		||||
 | 
			
		||||
namespace rtos {
 | 
			
		||||
/** \addtogroup rtos */
 | 
			
		||||
/** @{*/
 | 
			
		||||
 | 
			
		||||
struct Waiter;
 | 
			
		||||
 | 
			
		||||
/** This class provides a safe way to wait for or send notifications of condition changes
 | 
			
		||||
 *
 | 
			
		||||
 * This class is used in conjunction with a mutex to safely wait for or
 | 
			
		||||
 * notify waiters of condition changes to a resource accessible by multiple
 | 
			
		||||
 * threads.
 | 
			
		||||
 *
 | 
			
		||||
 * # Defined behavior
 | 
			
		||||
 * - All threads waiting on the condition variable wake when
 | 
			
		||||
 *   ConditionVariable::notify_all is called.
 | 
			
		||||
 * - If one or more threads are waiting on the condition variable at least
 | 
			
		||||
 *   one of them wakes when ConditionVariable::notify is called.
 | 
			
		||||
 *
 | 
			
		||||
 * # Undefined behavior
 | 
			
		||||
 * - The thread which is unblocked on ConditionVariable::notify_one is
 | 
			
		||||
 *   undefined if there are multiple waiters.
 | 
			
		||||
 * - The order which in which waiting threads acquire the condition variable's
 | 
			
		||||
 *   mutex after ConditionVariable::notify_all is called is undefined.
 | 
			
		||||
 * - When ConditionVariable::notify_one or ConditionVariable::notify_all is
 | 
			
		||||
 *   called and there are one or more waiters and one or more threads attempting
 | 
			
		||||
 *   to acquire the condition variable's mutex the order in which the mutex is
 | 
			
		||||
 *   acquired is undefined.
 | 
			
		||||
 * - The behavior of ConditionVariable::wait and ConditionVariable::wait_for
 | 
			
		||||
 *   is undefined if the condition variable's mutex is locked more than once by
 | 
			
		||||
 *   the calling thread.
 | 
			
		||||
 * - Spurious notifications (not triggered by the application) can occur
 | 
			
		||||
 *   and it is not defined when these occur.
 | 
			
		||||
 *
 | 
			
		||||
 * @note Synchronization level: Thread safe
 | 
			
		||||
 *
 | 
			
		||||
 * Example:
 | 
			
		||||
 * @code
 | 
			
		||||
 * #include "mbed.h"
 | 
			
		||||
 *
 | 
			
		||||
 * Mutex mutex;
 | 
			
		||||
 * ConditionVariable cond(mutex);
 | 
			
		||||
 *
 | 
			
		||||
 * // These variables are protected by locking mutex
 | 
			
		||||
 * uint32_t count = 0;
 | 
			
		||||
 * bool done = false;
 | 
			
		||||
 *
 | 
			
		||||
 * void worker_thread()
 | 
			
		||||
 * {
 | 
			
		||||
 *     mutex.lock();
 | 
			
		||||
 *     do {
 | 
			
		||||
 *         printf("Worker: Count %lu\r\n", count);
 | 
			
		||||
 *
 | 
			
		||||
 *         // Wait for a condition to change
 | 
			
		||||
 *         cond.wait();
 | 
			
		||||
 *
 | 
			
		||||
 *     } while (!done);
 | 
			
		||||
 *     printf("Worker: Exiting\r\n");
 | 
			
		||||
 *     mutex.unlock();
 | 
			
		||||
 * }
 | 
			
		||||
 *
 | 
			
		||||
 * int main() {
 | 
			
		||||
 *     Thread thread;
 | 
			
		||||
 *     thread.start(worker_thread);
 | 
			
		||||
 *
 | 
			
		||||
 *     for (int i = 0; i < 5; i++) {
 | 
			
		||||
 *
 | 
			
		||||
 *         mutex.lock();
 | 
			
		||||
 *         // Change count and notify waiters of this
 | 
			
		||||
 *         count++;
 | 
			
		||||
 *         printf("Main: Set count to %lu\r\n", count);
 | 
			
		||||
 *         cond.notify_all();
 | 
			
		||||
 *         mutex.unlock();
 | 
			
		||||
 *
 | 
			
		||||
 *         wait(1.0);
 | 
			
		||||
 *     }
 | 
			
		||||
 *
 | 
			
		||||
 *     mutex.lock();
 | 
			
		||||
 *     // Change done and notify waiters of this
 | 
			
		||||
 *     done = true;
 | 
			
		||||
 *     printf("Main: Set done\r\n");
 | 
			
		||||
 *     cond.notify_all();
 | 
			
		||||
 *     mutex.unlock();
 | 
			
		||||
 *
 | 
			
		||||
 *     thread.join();
 | 
			
		||||
 * }
 | 
			
		||||
 * @endcode
 | 
			
		||||
 */
 | 
			
		||||
class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
 | 
			
		||||
public:
 | 
			
		||||
    /** Create and Initialize a ConditionVariable object */
 | 
			
		||||
    ConditionVariable(Mutex &mutex);
 | 
			
		||||
 | 
			
		||||
    /** Wait for a notification
 | 
			
		||||
     *
 | 
			
		||||
     * Wait until a notification occurs.
 | 
			
		||||
     *
 | 
			
		||||
     * @note - The thread calling this function must be the owner of the
 | 
			
		||||
     * ConditionVariable's mutex and it must be locked exactly once
 | 
			
		||||
     * @note - Spurious notifications can occur so the caller of this API
 | 
			
		||||
     * should check to make sure the condition they are waiting on has
 | 
			
		||||
     * been met
 | 
			
		||||
     *
 | 
			
		||||
     * Example:
 | 
			
		||||
     * @code
 | 
			
		||||
     * mutex.lock();
 | 
			
		||||
     * while (!condition_met) {
 | 
			
		||||
     *     cond.wait();
 | 
			
		||||
     * }
 | 
			
		||||
     *
 | 
			
		||||
     * function_to_handle_condition();
 | 
			
		||||
     *
 | 
			
		||||
     * mutex.unlock();
 | 
			
		||||
     * @endcode
 | 
			
		||||
     */
 | 
			
		||||
    void wait();
 | 
			
		||||
 | 
			
		||||
    /** Wait for a notification or timeout
 | 
			
		||||
     *
 | 
			
		||||
     * @param   millisec  timeout value or osWaitForever in case of no time-out.
 | 
			
		||||
     * @return  true if a timeout occurred, false otherwise.
 | 
			
		||||
     *
 | 
			
		||||
     * @note - The thread calling this function must be the owner of the
 | 
			
		||||
     * ConditionVariable's mutex and it must be locked exactly once
 | 
			
		||||
     * @note - Spurious notifications can occur so the caller of this API
 | 
			
		||||
     * should check to make sure the condition they are waiting on has
 | 
			
		||||
     * been met
 | 
			
		||||
     *
 | 
			
		||||
     * Example:
 | 
			
		||||
     * @code
 | 
			
		||||
     * mutex.lock();
 | 
			
		||||
     * Timer timer;
 | 
			
		||||
     * timer.start();
 | 
			
		||||
     *
 | 
			
		||||
     * bool timed_out = false;
 | 
			
		||||
     * uint32_t time_left = TIMEOUT;
 | 
			
		||||
     * while (!condition_met && !timed_out) {
 | 
			
		||||
     *     timed_out = cond.wait_for(time_left);
 | 
			
		||||
     *     uint32_t elapsed = timer.read_ms();
 | 
			
		||||
     *     time_left = elapsed > TIMEOUT ? 0 : TIMEOUT - elapsed;
 | 
			
		||||
     * }
 | 
			
		||||
     *
 | 
			
		||||
     * if (condition_met) {
 | 
			
		||||
     *     function_to_handle_condition();
 | 
			
		||||
     * }
 | 
			
		||||
     *
 | 
			
		||||
     * mutex.unlock();
 | 
			
		||||
     * @endcode
 | 
			
		||||
     */
 | 
			
		||||
    bool wait_for(uint32_t millisec);
 | 
			
		||||
 | 
			
		||||
    /** Notify one waiter on this condition variable that a condition changed.
 | 
			
		||||
     *
 | 
			
		||||
     * @note - The thread calling this function must be the owner of the ConditionVariable's mutex
 | 
			
		||||
     */
 | 
			
		||||
    void notify_one();
 | 
			
		||||
 | 
			
		||||
    /** Notify all waiters on this condition variable that a condition changed.
 | 
			
		||||
     *
 | 
			
		||||
     * @note - The thread calling this function must be the owner of the ConditionVariable's mutex
 | 
			
		||||
     */
 | 
			
		||||
    void notify_all();
 | 
			
		||||
 | 
			
		||||
    ~ConditionVariable();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void _add_wait_list(Waiter * waiter);
 | 
			
		||||
    void _remove_wait_list(Waiter * waiter);
 | 
			
		||||
    Mutex &_mutex;
 | 
			
		||||
    Waiter *_wait_list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @}*/
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +27,7 @@
 | 
			
		|||
 | 
			
		||||
namespace rtos {
 | 
			
		||||
 | 
			
		||||
Mutex::Mutex()
 | 
			
		||||
Mutex::Mutex(): _count(0)
 | 
			
		||||
{
 | 
			
		||||
    constructor();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -50,17 +50,31 @@ void Mutex::constructor(const char *name)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
osStatus Mutex::lock(uint32_t millisec) {
 | 
			
		||||
    return osMutexAcquire(_id, millisec);
 | 
			
		||||
    osStatus status = osMutexAcquire(_id, millisec);
 | 
			
		||||
    if (osOK == status) {
 | 
			
		||||
        _count++;
 | 
			
		||||
    }
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Mutex::trylock() {
 | 
			
		||||
    return (osMutexAcquire(_id, 0) == osOK);
 | 
			
		||||
    if (osMutexAcquire(_id, 0) == osOK) {
 | 
			
		||||
        _count++;
 | 
			
		||||
        return true;
 | 
			
		||||
    } else {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
osStatus Mutex::unlock() {
 | 
			
		||||
    _count--;
 | 
			
		||||
    return osMutexRelease(_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
osThreadId Mutex::get_owner() {
 | 
			
		||||
    return osMutexGetOwner(_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mutex::~Mutex() {
 | 
			
		||||
    osMutexDelete(_id);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,13 +76,20 @@ public:
 | 
			
		|||
     */
 | 
			
		||||
    osStatus unlock();
 | 
			
		||||
 | 
			
		||||
    /** Get the owner the this mutex
 | 
			
		||||
      @return  the current owner of this mutex.
 | 
			
		||||
     */
 | 
			
		||||
    osThreadId get_owner();
 | 
			
		||||
 | 
			
		||||
    ~Mutex();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void constructor(const char *name = NULL);
 | 
			
		||||
    friend class ConditionVariable;
 | 
			
		||||
 | 
			
		||||
    osMutexId_t               _id;
 | 
			
		||||
    mbed_rtos_storage_mutex_t _obj_mem;
 | 
			
		||||
    uint32_t                  _count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,7 @@
 | 
			
		|||
#include "rtos/MemoryPool.h"
 | 
			
		||||
#include "rtos/Queue.h"
 | 
			
		||||
#include "rtos/EventFlags.h"
 | 
			
		||||
#include "rtos/ConditionVariable.h"
 | 
			
		||||
 | 
			
		||||
using namespace rtos;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue