-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibcpp_threading.cpp
146 lines (119 loc) · 3.65 KB
/
libcpp_threading.cpp
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright 2020 Embedded Artistry LLC
// SPDX-License-Identifier: MIT
#include <FreeRTOS.h>
#include <__external_threading>
#include <errno.h>
#include <os.hpp>
#include <task.h>
static_assert(configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0,
"libcpp requires a FreeRTOS config that supports thread local storage. "
"Set the configNUM_THREAD_LOCAL_STORAGE_POINTERS parameter.");
#pragma mark - Recursive Mutex Functions -
int std::__libcpp_recursive_mutex_init(std::__libcpp_recursive_mutex_t* __m)
{
*__m = os::Factory::createMutex(embvm::mutex::type::recursive);
return 0;
}
int std::__libcpp_recursive_mutex_destroy(std::__libcpp_recursive_mutex_t* __m)
{
os::Factory::destroy(*__m);
return 0;
}
#pragma mark - Mutex Functions -
int std::__libcpp_mutex_init(std::__libcpp_recursive_mutex_t* __m)
{
*__m = os::Factory::createMutex();
return 0;
}
int std::__libcpp_mutex_destroy(std::__libcpp_mutex_t* __m)
{
// There is the possibility that we are destroying our mutex without creating it,
// since we have to call lock, unlock, or try_lock to actually initialize a std::mutex.
// This is because the std::mutex constructor is constexpr... We don't know why.
if(*__m)
{
os::Factory::destroy(*__m);
}
return 0;
}
#pragma mark - Thread Functions -
int std::__libcpp_thread_create(std::__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg)
{
*__t = os::Factory::createThread("std::thread", reinterpret_cast<embvm::thread::func_t>(__func),
__arg);
return 0;
}
bool std::__libcpp_thread_isnull(const std::__libcpp_thread_t* __t)
{
return *__t == nullptr;
}
int std::__libcpp_thread_destroy(std::__libcpp_thread_t* __t)
{
if(__t && *__t)
{
os::Factory::destroy(*__t);
*__t = nullptr;
}
return 0;
}
#pragma mark - Condition Variable -
int std::__libcpp_condvar_create(std::__libcpp_condvar_t* __cv)
{
*__cv = os::Factory::createConditionVariable();
return 0;
}
int std::__libcpp_condvar_timedwait(std::__libcpp_condvar_t* __cv, std::__libcpp_mutex_t* __m,
timespec* __ts)
{
if(!*__cv)
{
__libcpp_condvar_create(__cv);
}
bool success = reinterpret_cast<os::freertos::ConditionVariable*>(*__cv)->wait(*__m, *__ts);
return success ? 0 : ETIMEDOUT;
}
int std::__libcpp_condvar_destroy(std::__libcpp_condvar_t* __cv)
{
// There is the possibility that we are destroying our CV without creating it,
// since we have to call a function to properly initialize it
if(*__cv)
{
os::Factory::destroy(*__cv);
}
return 0;
}
#pragma mark - Thread Local Storage -
/// This function is called once, and the primary purpose is to register the destructor function
/// which will eventually free libcpp's thread data.
/// FreeRTOS can ignore the key.
int std::__libcpp_tls_create(std::__libcpp_tls_key* __key,
void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
{
(void)__key;
os::freertos::register_threadexit_func(__at_exit);
return 0;
}
// Only one value is supported: 0, so key is ignored
// This function updates the calling thread! Call from the thread you want to store data into.
void* std::__libcpp_tls_get(std::__libcpp_tls_key __key)
{
(void)__key;
return pvTaskGetThreadLocalStoragePointer(nullptr, 0);
}
// Only one value is supported: 0, so key is ignored
// This function updates the calling thread! Call from the thread you want to store data into.
int std::__libcpp_tls_set(std::__libcpp_tls_key __key, void* __p)
{
(void)__key;
vTaskSetThreadLocalStoragePointer(nullptr, 0, __p);
return 0;
}
#pragma mark - Execute Once -
// Execute once
int std::__libcpp_execute_once(std::__libcpp_exec_once_flag* flag, void (*init_routine)(void))
{
(void)flag;
(void)init_routine;
// return pthread_once(flag, init_routine);
return -1;
}