-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfreertos_condition_variable.cpp
More file actions
78 lines (66 loc) · 1.9 KB
/
freertos_condition_variable.cpp
File metadata and controls
78 lines (66 loc) · 1.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Copyright 2020 Embedded Artistry LLC
// SPDX-License-Identifier: MIT
#include "freertos_condition_variable.hpp"
#include "freertos_os_helpers.hpp"
#include "rtos/thread.hpp"
#include <FreeRTOS.h>
#include <cassert>
#include <task.h>
using namespace os::freertos;
ConditionVariable::~ConditionVariable() noexcept
{
assert(q_.empty()); // We can't destruct if threads have not been notified!
}
bool ConditionVariable::freertos_wait(embvm::VirtualMutex* mutex, uint32_t ticks_timeout) noexcept
{
// We add our function to the waiting queue
sem_.take();
q_.push(embvm::this_thread::get_handle());
sem_.give();
// Tell FreeRTOS to sleep this thread until a notification occurs
mutex->unlock();
auto r = ulTaskNotifyTake(pdTRUE, ticks_timeout);
mutex->lock();
return r > 0; // 0 indicates we had no notifications
}
bool ConditionVariable::wait(embvm::VirtualMutex* mutex) noexcept
{
return freertos_wait(mutex, portMAX_DELAY);
}
bool ConditionVariable::wait(embvm::VirtualMutex* mutex,
const embvm::os_timeout_t& timeout) noexcept
{
auto timeout_ticks = frameworkTimeoutToTicks(timeout);
return freertos_wait(mutex, timeout_ticks);
}
bool ConditionVariable::wait(embvm::VirtualMutex* mutex, const timespec& timeout) noexcept
{
// TODO: improve this approach. it's stupid to go from duration->timespec->duration->uint32_t
// Stupid standard implementation.
auto timeout_ticks = frameworkTimeoutToTicks(embutil::timespecToDuration(timeout));
return freertos_wait(mutex, timeout_ticks);
}
void ConditionVariable::signal() noexcept
{
sem_.take();
if(!q_.empty())
{
pop_and_notify();
}
sem_.give();
}
void ConditionVariable::broadcast() noexcept
{
sem_.take();
while(!q_.empty())
{
pop_and_notify();
}
sem_.give();
}
void ConditionVariable::pop_and_notify() noexcept
{
embvm::thread::handle_t thread_handle = q_.front();
q_.pop();
xTaskNotifyGive((reinterpret_cast<TaskHandle_t>(thread_handle)));
}