SuperTinyKernel™ RTOS 1.08.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
anonymous_namespace{stk_c_pthread.cpp} Namespace Reference

Classes

struct  KeyEntry

Typedefs

using ThreadCtrl = pthread_stk_ctrl_t

Functions

 STK_BLOCKPOOL_STORAGE_DECL (s_PthreadStackStorage,(8U), kDefaultStackBytes)
stk_blockpool_tEnsureStackPool ()
void ReleaseThreadResources (ThreadCtrl *ctrl)
void WaitForTaskGone (stk_task_t *task)
void ReaperEntry (void *arg)
void EnsureReaper ()
void EnqueueReap (ThreadCtrl *ctrl)
ThreadCtrlDequeueReap ()
void MaybeReap (ThreadCtrl *ctrl)
ThreadCtrlAcquireThreadSlot ()
void PthreadTrampoline (void *arg)
stk_timeout_t TimespecToRelativeTimeout (const struct timespec *abstime)
stk_mutex_tEnsureMutex (pthread_mutex_t *m)
stk_cv_tEnsureCond (pthread_cond_t *c)
stk_rwmutex_tEnsureRWLock (pthread_rwlock_t *rw)
stk_mutex_tEnsureOnceMutex (pthread_once_t *o)
void RunKeyDestructors (ThreadCtrl *ctrl)

Variables

constexpr std::size_t kDefaultStackBytes
ThreadCtrl s_Threads [(8U)]
stk_kernel_ts_BoundKernel = nullptr
stk_blockpool_ts_StackPool = nullptr
ThreadCtrls_ReapQueue [(8U)]
std::size_t s_ReapHead = 0U
std::size_t s_ReapCount = 0U
stk_sem_ts_ReapSem = nullptr
stk_sem_mem_t s_ReapSemMem
stk_task_ts_ReaperTask = nullptr
stk_word_t s_ReaperStack [(256U)]
KeyEntry s_Keys [(8U)]

Typedef Documentation

◆ ThreadCtrl

using anonymous_namespace{stk_c_pthread.cpp}::ThreadCtrl = pthread_stk_ctrl_t

Definition at line 58 of file stk_c_pthread.cpp.

Function Documentation

◆ AcquireThreadSlot()

ThreadCtrl * anonymous_namespace{stk_c_pthread.cpp}::AcquireThreadSlot ( )

Definition at line 209 of file stk_c_pthread.cpp.

210{
211 ThreadCtrl *result = nullptr;
212
214 for (std::size_t i = 0U; i < STK_C_PTHREAD_MAX_THREADS; ++i)
215 {
216 if (!s_Threads[i].busy)
217 {
218 s_Threads[i] = ThreadCtrl();
219 s_Threads[i].busy = true;
220 result = &s_Threads[i];
221 break;
222 }
223 }
225
226 return result;
227}
void stk_critical_section_enter()
Enter global critical section - disable context switches on current core.
Definition stk_c.cpp:682
void stk_critical_section_exit()
Leave global critical section - re-enable context switches.
Definition stk_c.cpp:687
#define STK_C_PTHREAD_MAX_THREADS
Maximum number of concurrently-alive pthread_t's (default: 8).

References s_Threads, STK_C_PTHREAD_MAX_THREADS, stk_critical_section_enter(), and stk_critical_section_exit().

Referenced by pthread_create().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DequeueReap()

ThreadCtrl * anonymous_namespace{stk_c_pthread.cpp}::DequeueReap ( )

Definition at line 151 of file stk_c_pthread.cpp.

152{
153 ThreadCtrl *result = nullptr;
154
156 if (s_ReapCount > 0U)
157 {
158 result = s_ReapQueue[s_ReapHead];
160 --s_ReapCount;
161 }
163
164 return result;
165}

References s_ReapCount, s_ReapHead, s_ReapQueue, STK_C_PTHREAD_MAX_THREADS, stk_critical_section_enter(), and stk_critical_section_exit().

Referenced by ReaperEntry().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EnqueueReap()

void anonymous_namespace{stk_c_pthread.cpp}::EnqueueReap ( ThreadCtrl * ctrl)

Definition at line 138 of file stk_c_pthread.cpp.

139{
143 {
144 const std::size_t tail = (s_ReapHead + s_ReapCount) % STK_C_PTHREAD_MAX_THREADS;
145 s_ReapQueue[tail] = ctrl;
146 ++s_ReapCount;
147 }
149}
#define STK_C_ASSERT(e)
Assertion macro used inside STK C bindings.
Definition stk_c.h:75

References s_ReapCount, s_ReapHead, s_ReapQueue, STK_C_ASSERT, STK_C_PTHREAD_MAX_THREADS, stk_critical_section_enter(), and stk_critical_section_exit().

Referenced by MaybeReap().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EnsureCond()

stk_cv_t * anonymous_namespace{stk_c_pthread.cpp}::EnsureCond ( pthread_cond_t * c)

Definition at line 352 of file stk_c_pthread.cpp.

353{
354 if (c->__handle == nullptr)
355 {
357 if (c->__handle == nullptr)
358 {
359 c->__handle = stk_cv_create(&c->__mem, sizeof(c->__mem));
360 }
362 }
363
364 return c->__handle;
365}
stk_cv_t * stk_cv_create(stk_cv_mem_t *const membuf, uint32_t membuf_size)
Create a Condition Variable (using provided memory).
stk_cv_t * __handle
stk_cv_mem_t __mem

References pthread_cond_t::__handle, pthread_cond_t::__mem, stk_critical_section_enter(), stk_critical_section_exit(), and stk_cv_create().

Referenced by pthread_cond_broadcast(), pthread_cond_signal(), pthread_cond_timedwait(), and pthread_cond_wait().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EnsureMutex()

stk_mutex_t * anonymous_namespace{stk_c_pthread.cpp}::EnsureMutex ( pthread_mutex_t * m)

Definition at line 337 of file stk_c_pthread.cpp.

338{
339 if (m->__handle == nullptr)
340 {
342 if (m->__handle == nullptr)
343 {
344 m->__handle = stk_mutex_create(&m->__mem, sizeof(m->__mem));
345 }
347 }
348
349 return m->__handle;
350}
stk_mutex_t * stk_mutex_create(stk_mutex_mem_t *const membuf, uint32_t membuf_size)
Create a Mutex (using provided memory).
stk_mutex_mem_t __mem
stk_mutex_t * __handle

References pthread_mutex_t::__handle, pthread_mutex_t::__mem, stk_critical_section_enter(), stk_critical_section_exit(), and stk_mutex_create().

Referenced by pthread_mutex_lock(), pthread_mutex_timedlock(), and pthread_mutex_trylock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EnsureOnceMutex()

stk_mutex_t * anonymous_namespace{stk_c_pthread.cpp}::EnsureOnceMutex ( pthread_once_t * o)

Definition at line 382 of file stk_c_pthread.cpp.

383{
384 if (o->__handle == nullptr)
385 {
387 if (o->__handle == nullptr)
388 {
389 o->__handle = stk_mutex_create(&o->__mem, sizeof(o->__mem));
390 }
392 }
393
394 return o->__handle;
395}
stk_mutex_mem_t __mem
stk_mutex_t * __handle

References pthread_once_t::__handle, pthread_once_t::__mem, stk_critical_section_enter(), stk_critical_section_exit(), and stk_mutex_create().

Referenced by pthread_once().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EnsureReaper()

void anonymous_namespace{stk_c_pthread.cpp}::EnsureReaper ( )

Definition at line 112 of file stk_c_pthread.cpp.

113{
114 if (s_ReaperTask == nullptr)
115 {
117 if (s_ReaperTask == nullptr)
118 {
119 STK_C_ASSERT(s_BoundKernel != nullptr);
120
121 if (s_ReapSem == nullptr)
122 {
124 }
125
128 if (s_ReaperTask != nullptr)
129 {
130 stk_task_set_name(s_ReaperTask, "pthread_reaper");
132 }
133 }
135 }
136}
stk_task_t * stk_task_create_user(stk_task_entry_t entry, void *arg, stk_word_t *stack, uint32_t stack_size)
Create user-mode task.
Definition stk_c.cpp:568
void stk_task_set_name(stk_task_t *tsk, const char *tname)
Assign human-readable task name (for tracing/debugging).
Definition stk_c.cpp:596
stk_sem_t * stk_sem_create(stk_sem_mem_t *const membuf, uint32_t membuf_size, uint32_t initial_count, uint32_t max_count)
Create a Semaphore (using provided memory).
void stk_kernel_add_task(stk_kernel_t *k, stk_task_t *tsk)
Add task to non-HRT kernel (static or dynamic).
Definition stk_c.cpp:429
#define STK_C_PTHREAD_REAPER_STACK_WORDS
Stack size (in stk_word_t units) for the internal reaper task that reclaims detached-thread resources...

References ReaperEntry(), s_BoundKernel, s_ReaperStack, s_ReaperTask, s_ReapSem, s_ReapSemMem, STK_C_ASSERT, STK_C_PTHREAD_REAPER_STACK_WORDS, stk_critical_section_enter(), stk_critical_section_exit(), stk_kernel_add_task(), stk_sem_create(), stk_task_create_user(), and stk_task_set_name().

Referenced by MaybeReap(), and pthread_create().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EnsureRWLock()

stk_rwmutex_t * anonymous_namespace{stk_c_pthread.cpp}::EnsureRWLock ( pthread_rwlock_t * rw)

Definition at line 367 of file stk_c_pthread.cpp.

368{
369 if (rw->__handle == nullptr)
370 {
372 if (rw->__handle == nullptr)
373 {
374 rw->__handle = stk_rwmutex_create(&rw->__mem, sizeof(rw->__mem));
375 }
377 }
378
379 return rw->__handle;
380}
stk_rwmutex_t * stk_rwmutex_create(stk_rwmutex_mem_t *const membuf, uint32_t membuf_size)
Create an RWMutex (using provided memory).
stk_rwmutex_t * __handle
stk_rwmutex_mem_t __mem

References pthread_rwlock_t::__handle, pthread_rwlock_t::__mem, stk_critical_section_enter(), stk_critical_section_exit(), and stk_rwmutex_create().

Referenced by pthread_rwlock_rdlock(), pthread_rwlock_timedrdlock(), pthread_rwlock_timedwrlock(), pthread_rwlock_tryrdlock(), pthread_rwlock_trywrlock(), and pthread_rwlock_wrlock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EnsureStackPool()

stk_blockpool_t * anonymous_namespace{stk_c_pthread.cpp}::EnsureStackPool ( )

Definition at line 76 of file stk_c_pthread.cpp.

77{
78 if (s_StackPool == nullptr)
79 {
81 if (s_StackPool == nullptr)
82 {
86 reinterpret_cast<uint8_t *>(s_PthreadStackStorage),
87 sizeof(s_PthreadStackStorage),
88 "pthread_stacks");
89 }
91 }
92
93 return s_StackPool;
94}
stk_blockpool_t * stk_blockpool_create_static(size_t capacity, size_t raw_block_size, uint8_t *storage, size_t storage_size, const char *name)
Create a block pool backed by caller-supplied (external) storage.

References kDefaultStackBytes, s_StackPool, stk_blockpool_create_static(), STK_C_PTHREAD_MAX_THREADS, stk_critical_section_enter(), and stk_critical_section_exit().

Referenced by pthread_create().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ MaybeReap()

void anonymous_namespace{stk_c_pthread.cpp}::MaybeReap ( ThreadCtrl * ctrl)

Definition at line 186 of file stk_c_pthread.cpp.

187{
188 bool do_reap = false;
189
191 if (ctrl->finished && ctrl->detached && !ctrl->reclaimed)
192 {
193 ctrl->reclaimed = true;
194 do_reap = true;
195 }
197
198 if (do_reap)
199 {
200 EnsureReaper();
201 EnqueueReap(ctrl);
203 }
204}
void stk_sem_signal(stk_sem_t *sem)
Signal/Release a semaphore resource.

References pthread_stk_ctrl_t::detached, EnqueueReap(), EnsureReaper(), pthread_stk_ctrl_t::finished, pthread_stk_ctrl_t::reclaimed, s_ReapSem, stk_critical_section_enter(), stk_critical_section_exit(), and stk_sem_signal().

Referenced by pthread_detach(), pthread_exit(), and PthreadTrampoline().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ PthreadTrampoline()

void anonymous_namespace{stk_c_pthread.cpp}::PthreadTrampoline ( void * arg)

Definition at line 288 of file stk_c_pthread.cpp.

289{
290 ThreadCtrl *const ctrl = static_cast<ThreadCtrl *>(arg);
291
292 stk_tls_set(ctrl);
293
294 void *const result = ctrl->start_routine(ctrl->arg);
295
296 RunKeyDestructors(ctrl);
297
299 ctrl->retval = result;
300 ctrl->finished = true;
302
304 MaybeReap(ctrl);
305
306 // Natural return: STK finishes/frees the underlying dynamic task automatically.
307 // A joiner (or the reaper, for detached threads) reclaims *our* resources
308 // (stack, control block) only after confirming via WaitForTaskGone() that this
309 // task has fully left the kernel's task list.
310}
bool stk_event_set(stk_event_t *ev)
Set the event to signaled state.
void stk_tls_set(void *ptr)
Set thread-local pointer.
stk_event_t * done_event
void *(* start_routine)(void *)

References pthread_stk_ctrl_t::arg, pthread_stk_ctrl_t::done_event, pthread_stk_ctrl_t::finished, MaybeReap(), pthread_stk_ctrl_t::retval, RunKeyDestructors(), pthread_stk_ctrl_t::start_routine, stk_critical_section_enter(), stk_critical_section_exit(), stk_event_set(), and stk_tls_set().

Referenced by pthread_create().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReaperEntry()

void anonymous_namespace{stk_c_pthread.cpp}::ReaperEntry ( void * arg)

Definition at line 167 of file stk_c_pthread.cpp.

168{
169 for (;;)
170 {
171 STK_C_ASSERT(s_ReapSem != nullptr);
173
174 ThreadCtrl *ctrl = DequeueReap();
175 if (ctrl != nullptr)
176 {
177 WaitForTaskGone(ctrl->task);
179 }
180 }
181}
#define STK_WAIT_INFINITE
Infinite timeout constant.
Definition stk_c.h:147
bool stk_sem_wait(stk_sem_t *sem, stk_timeout_t timeout)
Wait for a semaphore resource.
void ReleaseThreadResources(ThreadCtrl *ctrl)

References DequeueReap(), ReleaseThreadResources(), s_ReapSem, STK_C_ASSERT, stk_sem_wait(), STK_WAIT_INFINITE, pthread_stk_ctrl_t::task, and WaitForTaskGone().

Referenced by EnsureReaper().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReleaseThreadResources()

void anonymous_namespace{stk_c_pthread.cpp}::ReleaseThreadResources ( ThreadCtrl * ctrl)

Definition at line 259 of file stk_c_pthread.cpp.

260{
261 if (ctrl->done_event != nullptr)
262 {
264 ctrl->done_event = nullptr;
265 }
266
267 if (ctrl->stack_owned && (ctrl->stack != nullptr))
268 {
269 if (ctrl->stack_from_pool)
270 {
272 }
273 else
274 {
275 free(ctrl->stack);
276 }
277 }
278 ctrl->stack = nullptr;
279
281 ctrl->busy = false;
283}
void free(void *ptr)
void stk_event_destroy(stk_event_t *ev)
Destroy an Event.
bool stk_blockpool_free(stk_blockpool_t *pool, void *ptr)
Return a previously allocated block to the pool.

References pthread_stk_ctrl_t::busy, pthread_stk_ctrl_t::done_event, free(), s_StackPool, pthread_stk_ctrl_t::stack, pthread_stk_ctrl_t::stack_from_pool, pthread_stk_ctrl_t::stack_owned, stk_blockpool_free(), stk_critical_section_enter(), stk_critical_section_exit(), and stk_event_destroy().

Referenced by pthread_join(), and ReaperEntry().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ RunKeyDestructors()

void anonymous_namespace{stk_c_pthread.cpp}::RunKeyDestructors ( ThreadCtrl * ctrl)

Definition at line 415 of file stk_c_pthread.cpp.

416{
417 for (int iter = 0; iter < PTHREAD_DESTRUCTOR_ITERATIONS; ++iter)
418 {
419 bool any_ran = false;
420
421 for (std::size_t i = 0U; i < STK_C_PTHREAD_KEYS_MAX; ++i)
422 {
423 void *const value = ctrl->tsd[i];
424 if (value == nullptr) { continue; }
425
426 void (*destructor)(void *) = nullptr;
428 if (s_Keys[i].used) { destructor = s_Keys[i].destructor; }
430
431 ctrl->tsd[i] = nullptr; // clear before calling, per POSIX
432 if (destructor != nullptr)
433 {
434 destructor(value);
435 any_ran = true;
436 }
437 }
438
439 if (!any_ran) { break; }
440 }
441}
#define PTHREAD_DESTRUCTOR_ITERATIONS
Maximum number of passes over a finishing thread's keys made while destructors keep setting new non-N...
#define STK_C_PTHREAD_KEYS_MAX
Maximum number of concurrently-alive pthread_key_t's (default: 8).

References PTHREAD_DESTRUCTOR_ITERATIONS, s_Keys, STK_C_PTHREAD_KEYS_MAX, stk_critical_section_enter(), stk_critical_section_exit(), and pthread_stk_ctrl_t::tsd.

Referenced by pthread_exit(), and PthreadTrampoline().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ STK_BLOCKPOOL_STORAGE_DECL()

anonymous_namespace{stk_c_pthread.cpp}::STK_BLOCKPOOL_STORAGE_DECL ( s_PthreadStackStorage ,
(8U) ,
kDefaultStackBytes  )

◆ TimespecToRelativeTimeout()

stk_timeout_t anonymous_namespace{stk_c_pthread.cpp}::TimespecToRelativeTimeout ( const struct timespec * abstime)

Definition at line 318 of file stk_c_pthread.cpp.

319{
320 const stk_time_t now_ms = stk_time_now_ms();
321 const stk_time_t target_ms = (static_cast<stk_time_t>(abstime->tv_sec) * 1000LL) +
322 (static_cast<stk_time_t>(abstime->tv_nsec) / 1000000LL);
323
324 stk_time_t rel_ms = target_ms - now_ms;
325 if (rel_ms < 0LL)
326 {
327 rel_ms = 0LL;
328 }
329 if (rel_ms > static_cast<stk_time_t>(INT32_MAX))
330 {
331 rel_ms = static_cast<stk_time_t>(INT32_MAX);
332 }
333
334 return stk_ticks_from_ms_clamped_to_timeout(static_cast<stk_timeout_t>(rel_ms));
335}
stk_timeout_t stk_ticks_from_ms_clamped_to_timeout(stk_timeout_t ms)
Get ticks from milliseconds using current kernel tick resolution, clamped to the maximum value repres...
Definition stk_c.cpp:639
int64_t stk_time_t
Time value.
Definition stk_c.h:108
stk_time_t stk_time_now_ms(void)
Returns current time in milliseconds since kernel start.
Definition stk_c.cpp:637
int32_t stk_timeout_t
Timeout value.
Definition stk_c.h:113

References stk_ticks_from_ms_clamped_to_timeout(), and stk_time_now_ms().

Referenced by pthread_cond_timedwait(), pthread_mutex_timedlock(), pthread_rwlock_timedrdlock(), and pthread_rwlock_timedwrlock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ WaitForTaskGone()

void anonymous_namespace{stk_c_pthread.cpp}::WaitForTaskGone ( stk_task_t * task)

Definition at line 232 of file stk_c_pthread.cpp.

233{
235
236 for (;;)
237 {
239
240 bool found = false;
241 for (std::size_t i = 0U; i < n; ++i)
242 {
243 if (buf[i] == task)
244 {
245 found = true;
246 break;
247 }
248 }
249
250 if (!found)
251 {
252 break;
253 }
254
255 stk_sleep_ms(1);
256 }
257}
#define STK_C_KERNEL_MAX_TASKS
Maximum number of tasks per kernel instance (default: 4).
Definition stk_c.h:52
void stk_sleep_ms(stk_timeout_t ms)
Put current task to sleep (non-HRT kernels only).
Definition stk_c.cpp:648
size_t stk_kernel_enumerate_tasks(stk_kernel_t *k, stk_task_t **tasks, size_t max_count)
Enumerate all currently active tasks.
Definition stk_c.cpp:478

References s_BoundKernel, STK_C_KERNEL_MAX_TASKS, stk_kernel_enumerate_tasks(), and stk_sleep_ms().

Referenced by pthread_join(), and ReaperEntry().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ kDefaultStackBytes

std::size_t anonymous_namespace{stk_c_pthread.cpp}::kDefaultStackBytes
constexpr
Initial value:
=
static_cast<std::size_t>( (1024U) ) * sizeof(stk_word_t)
uintptr_t stk_word_t
CPU register type.
Definition stk_c.h:94

Definition at line 60 of file stk_c_pthread.cpp.

Referenced by EnsureStackPool(), pthread_attr_getstacksize(), pthread_create(), and STK_BLOCKPOOL_STORAGE_DECL().

◆ s_BoundKernel

stk_kernel_t* anonymous_namespace{stk_c_pthread.cpp}::s_BoundKernel = nullptr

◆ s_Keys

KeyEntry anonymous_namespace{stk_c_pthread.cpp}::s_Keys[(8U)]

◆ s_ReapCount

std::size_t anonymous_namespace{stk_c_pthread.cpp}::s_ReapCount = 0U

Definition at line 101 of file stk_c_pthread.cpp.

Referenced by DequeueReap(), and EnqueueReap().

◆ s_ReaperStack

stk_word_t anonymous_namespace{stk_c_pthread.cpp}::s_ReaperStack[(256U)]

Definition at line 106 of file stk_c_pthread.cpp.

Referenced by EnsureReaper().

◆ s_ReaperTask

stk_task_t* anonymous_namespace{stk_c_pthread.cpp}::s_ReaperTask = nullptr

Definition at line 105 of file stk_c_pthread.cpp.

Referenced by EnsureReaper().

◆ s_ReapHead

std::size_t anonymous_namespace{stk_c_pthread.cpp}::s_ReapHead = 0U

Definition at line 100 of file stk_c_pthread.cpp.

Referenced by DequeueReap(), and EnqueueReap().

◆ s_ReapQueue

ThreadCtrl* anonymous_namespace{stk_c_pthread.cpp}::s_ReapQueue[(8U)]

Definition at line 99 of file stk_c_pthread.cpp.

Referenced by DequeueReap(), and EnqueueReap().

◆ s_ReapSem

stk_sem_t* anonymous_namespace{stk_c_pthread.cpp}::s_ReapSem = nullptr

Definition at line 103 of file stk_c_pthread.cpp.

Referenced by EnsureReaper(), MaybeReap(), and ReaperEntry().

◆ s_ReapSemMem

stk_sem_mem_t anonymous_namespace{stk_c_pthread.cpp}::s_ReapSemMem

Definition at line 104 of file stk_c_pthread.cpp.

Referenced by EnsureReaper().

◆ s_StackPool

stk_blockpool_t* anonymous_namespace{stk_c_pthread.cpp}::s_StackPool = nullptr

Definition at line 74 of file stk_c_pthread.cpp.

Referenced by EnsureStackPool(), pthread_create(), and ReleaseThreadResources().

◆ s_Threads

ThreadCtrl anonymous_namespace{stk_c_pthread.cpp}::s_Threads[(8U)]

Definition at line 63 of file stk_c_pthread.cpp.

Referenced by AcquireThreadSlot().