SuperTinyKernel™ RTOS 1.06.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk_c_sync.cpp
Go to the documentation of this file.
1/*
2 * SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
3 *
4 * Source: https://github.com/SuperTinyKernel-RTOS
5 *
6 * Copyright (c) 2022-2026 Neutron Code Limited <stk@neutroncode.com>. All Rights Reserved.
7 * License: MIT License, see LICENSE for a full text.
8 */
9
10#include <cstddef> // for std::size_t
11
12#include "stk_config.h"
13#include "stk.h"
14#include "sync/stk_sync.h"
15#include "memory/stk_memory.h"
16
17#include "stk_c.h"
18
19using namespace stk;
20using namespace stk::sync;
21
22// =============================================================================
23// C-interface
24// =============================================================================
25extern "C" {
26
27// -----------------------------------------------------------------------------
28// Mutex
29// -----------------------------------------------------------------------------
31{
33};
34
35stk_mutex_t *stk_mutex_create(stk_mutex_mem_t *const membuf, uint32_t membuf_size)
36{
37 STK_ASSERT(membuf != nullptr);
38 STK_ASSERT(membuf_size >= sizeof(stk_mutex_t));
39
40 stk_mutex_t *result = nullptr;
41 if (membuf_size >= sizeof(stk_mutex_t))
42 {
43 result = new (membuf->data) stk_mutex_t();
44 }
45
46 return result;
47}
48
50{
51 if (mtx != nullptr)
52 {
53 mtx->~stk_mutex_t();
54 }
55}
56
58{
59 STK_ASSERT(mtx != nullptr);
60
61 mtx->handle.Lock();
62}
63
65{
66 STK_ASSERT(mtx != nullptr);
67
68 return mtx->handle.TryLock();
69}
70
72{
73 STK_ASSERT(mtx != nullptr);
74
75 mtx->handle.Unlock();
76}
77
79{
80 STK_ASSERT(mtx != nullptr);
81
82 return mtx->handle.TimedLock(timeout);
83}
84
85// -----------------------------------------------------------------------------
86// SpinLock
87// -----------------------------------------------------------------------------
92
93stk_spinlock_t *stk_spinlock_create(stk_spinlock_mem_t *const membuf, uint32_t membuf_size)
94{
95 STK_ASSERT(membuf != nullptr);
96 STK_ASSERT(membuf_size >= sizeof(stk_spinlock_t));
97
98 stk_spinlock_t *result = nullptr;
99 if (membuf_size >= sizeof(stk_spinlock_t))
100 {
101 result = new (membuf->data) stk_spinlock_t();
102 }
103
104 return result;
105}
106
108{
109 if (slock != nullptr)
110 {
111 slock->~stk_spinlock_t();
112 }
113}
114
116{
117 STK_ASSERT(slock != nullptr);
118 slock->handle.Lock();
119}
120
122{
123 STK_ASSERT(slock != nullptr);
124 return slock->handle.TryLock();
125}
126
128{
129 STK_ASSERT(slock != nullptr);
130 slock->handle.Unlock();
131}
132
133// -----------------------------------------------------------------------------
134// ConditionVariable
135// -----------------------------------------------------------------------------
140
141stk_cv_t *stk_cv_create(stk_cv_mem_t *const membuf, uint32_t membuf_size)
142{
143 STK_ASSERT(membuf != nullptr);
144 STK_ASSERT(membuf_size >= sizeof(stk_cv_t));
145
146 stk_cv_t *result = nullptr;
147 if (membuf_size >= sizeof(stk_cv_t))
148 {
149 result = new (membuf->data) stk_cv_t();
150 }
151
152 return result;
153}
154
156{
157 if (cv != nullptr)
158 {
159 cv->~stk_cv_t();
160 }
161}
162
164{
165 STK_ASSERT(cv != nullptr);
166 STK_ASSERT(mtx != nullptr);
167
168 return cv->handle.Wait(mtx->handle, timeout);
169}
170
172{
173 STK_ASSERT(cv != nullptr);
174
175 cv->handle.NotifyOne();
176}
177
179{
180 STK_ASSERT(cv != nullptr);
181
182 cv->handle.NotifyAll();
183}
184
185// -----------------------------------------------------------------------------
186// Event
187// -----------------------------------------------------------------------------
189{
190 stk_event_t(bool manual_reset) : handle(manual_reset)
191 {}
192
194};
195
197 uint32_t membuf_size,
198 bool manual_reset)
199{
200 STK_ASSERT(membuf != nullptr);
201 STK_ASSERT(membuf_size >= sizeof(stk_event_t));
202
203 stk_event_t *result = nullptr;
204 if (membuf_size >= sizeof(stk_event_t))
205 {
206 result = new (membuf->data) stk_event_t(manual_reset);
207 }
208
209 return result;
210}
211
213{
214 if (ev != nullptr)
215 {
216 ev->~stk_event_t();
217 }
218}
219
221{
222 STK_ASSERT(ev != nullptr);
223
224 return ev->handle.Wait(timeout);
225}
226
228{
229 STK_ASSERT(ev != nullptr);
230
231 return ev->handle.TryWait();
232}
233
235{
236 STK_ASSERT(ev != nullptr);
237
238 return ev->handle.Set();
239}
240
242{
243 STK_ASSERT(ev != nullptr);
244
245 return ev->handle.Reset();
246}
247
249{
250 STK_ASSERT(ev != nullptr);
251
252 ev->handle.Pulse();
253}
254
255// -----------------------------------------------------------------------------
256// Semaphore
257// -----------------------------------------------------------------------------
259{
260 stk_sem_t(uint32_t initial_count, uint32_t max_count)
261 : handle(static_cast<uint16_t>(initial_count),
262 static_cast<uint16_t>(max_count))
263 {}
264
266};
267
269 uint32_t membuf_size,
270 uint32_t initial_count,
271 uint32_t max_count)
272{
273 STK_ASSERT(membuf != nullptr);
274 STK_ASSERT(membuf_size >= sizeof(stk_sem_t));
275 STK_ASSERT(initial_count < (max_count == 0U ? Semaphore::COUNT_MAX : max_count));
276
277 stk_sem_t *result = nullptr;
278 if (membuf_size >= sizeof(stk_sem_t))
279 {
280 const uint32_t effective_max = ((max_count == 0U) ? Semaphore::COUNT_MAX : max_count);
281 result = new (membuf->data) stk_sem_t(initial_count, effective_max);
282 }
283
284 return result;
285}
286
288{
289 if (sem != nullptr)
290 {
291 sem->~stk_sem_t();
292 }
293}
294
296{
297 STK_ASSERT(sem != nullptr);
298
299 return sem->handle.Wait(timeout);
300}
301
303{
304 STK_ASSERT(sem != nullptr);
305
306 return sem->handle.TryWait();
307}
308
310{
311 STK_ASSERT(sem != nullptr);
312
313 sem->handle.Signal();
314}
315
316uint16_t stk_sem_get_count(const stk_sem_t *sem)
317{
318 STK_ASSERT(sem != nullptr);
319
320 return sem->handle.GetCount();
321}
322
323// -----------------------------------------------------------------------------
324// EventFlags
325// -----------------------------------------------------------------------------
327{
328 stk_ef_t(uint32_t initial_flags) : handle(initial_flags)
329 {}
330
332};
333
335 uint32_t membuf_size,
336 uint32_t initial_flags)
337{
338 STK_ASSERT(membuf != nullptr);
339 STK_ASSERT(membuf_size >= sizeof(stk_ef_t));
340
341 stk_ef_t *result = nullptr;
342 if (membuf_size >= sizeof(stk_ef_t))
343 {
344 result = new (membuf->data) stk_ef_t(initial_flags);
345 }
346
347 return result;
348}
349
351{
352 if (ef != nullptr)
353 {
354 ef->~stk_ef_t();
355 }
356}
357
358uint32_t stk_ef_set(stk_ef_t *ef, uint32_t flags)
359{
360 STK_ASSERT(ef != nullptr);
361
362 return ef->handle.Set(flags);
363}
364
365uint32_t stk_ef_clear(stk_ef_t *ef, uint32_t flags)
366{
367 STK_ASSERT(ef != nullptr);
368
369 return ef->handle.Clear(flags);
370}
371
372uint32_t stk_ef_get(stk_ef_t *ef)
373{
374 STK_ASSERT(ef != nullptr);
375
376 return ef->handle.Get();
377}
378
379uint32_t stk_ef_wait(stk_ef_t *ef, uint32_t flags, uint32_t options, stk_timeout_t timeout)
380{
381 STK_ASSERT(ef != nullptr);
382
383 return ef->handle.Wait(flags, options, timeout);
384}
385
386uint32_t stk_ef_trywait(stk_ef_t *ef, uint32_t flags, uint32_t options)
387{
388 STK_ASSERT(ef != nullptr);
389
390 return ef->handle.TryWait(flags, options);
391}
392
393// -----------------------------------------------------------------------------
394// Pipe (runtime-sized, external-buffer; wraps sync::Pipe)
395// -----------------------------------------------------------------------------
397{
399
400 stk_pipe_t(uint8_t *buf, size_t capacity, size_t element_size)
401 : handle(buf, capacity, element_size)
402 {}
403};
404
406 uint32_t membuf_size,
407 uint8_t *buf,
408 uint32_t buf_size,
409 size_t capacity,
410 size_t element_size)
411{
412 STK_ASSERT(membuf != nullptr);
413 STK_ASSERT(buf != nullptr);
414 STK_ASSERT(capacity >= 1U);
415 STK_ASSERT(element_size >= 1U);
416 STK_ASSERT(membuf_size >= sizeof(stk_pipe_t));
417 STK_ASSERT(buf_size >= capacity * element_size);
418
419 stk_pipe_t *result = nullptr;
420 if ((membuf_size >= sizeof(stk_pipe_t)) && (buf_size >= (capacity * element_size)))
421 {
422 result = new (membuf->data) stk_pipe_t(buf, capacity, element_size);
423 }
424
425 return result;
426}
427
429{
430 if (pipe != nullptr)
431 {
432 pipe->~stk_pipe_t();
433 }
434}
435
436bool stk_pipe_write(stk_pipe_t *pipe, const void *data, stk_timeout_t timeout)
437{
438 STK_ASSERT(pipe != nullptr);
439 STK_ASSERT(data != nullptr);
440
441 return pipe->handle.Write(data, timeout);
442}
443
444bool stk_pipe_trywrite(stk_pipe_t *pipe, const void *data)
445{
446 STK_ASSERT(pipe != nullptr);
447 STK_ASSERT(data != nullptr);
448
449 return pipe->handle.TryWrite(data);
450}
451
452bool stk_pipe_read(stk_pipe_t *pipe, void *data, stk_timeout_t timeout)
453{
454 STK_ASSERT(pipe != nullptr);
455 STK_ASSERT(data != nullptr);
456
457 return pipe->handle.Read(data, timeout);
458}
459
460bool stk_pipe_tryread(stk_pipe_t *pipe, void *data)
461{
462 STK_ASSERT(pipe != nullptr);
463 STK_ASSERT(data != nullptr);
464
465 return pipe->handle.TryRead(data);
466}
467
468size_t stk_pipe_write_bulk(stk_pipe_t *pipe, const void *src, size_t count, stk_timeout_t timeout)
469{
470 STK_ASSERT(pipe != nullptr);
471
472 return pipe->handle.WriteBulk(src, count, timeout);
473}
474
475size_t stk_pipe_trywrite_bulk(stk_pipe_t *pipe, const void *src, size_t count)
476{
477 STK_ASSERT(pipe != nullptr);
478
479 return pipe->handle.TryWriteBulk(src, count);
480}
481
482size_t stk_pipe_read_bulk(stk_pipe_t *pipe, void *dst, size_t count, stk_timeout_t timeout)
483{
484 STK_ASSERT(pipe != nullptr);
485
486 return pipe->handle.ReadBulk(dst, count, timeout);
487}
488
489size_t stk_pipe_tryread_bulk(stk_pipe_t *pipe, void *dst, size_t count)
490{
491 STK_ASSERT(pipe != nullptr);
492
493 return pipe->handle.TryReadBulk(dst, count);
494}
495
497 void *dst,
498 size_t trigger,
499 size_t max_count,
500 stk_timeout_t timeout)
501{
502 STK_ASSERT(pipe != nullptr);
503
504 return pipe->handle.ReadBulkTriggered(dst, trigger, max_count, timeout);
505}
506
507size_t stk_pipe_tryread_bulk_triggered(stk_pipe_t *pipe, void *dst, size_t max_count)
508{
509 STK_ASSERT(pipe != nullptr);
510
511 return pipe->handle.TryReadBulkTriggered(dst, max_count);
512}
513
515{
516 STK_ASSERT(pipe != nullptr);
517
518 pipe->handle.Reset();
519}
520
522{
523 STK_ASSERT(pipe != nullptr);
524
525 return pipe->handle.GetCapacity();
526}
527
529{
530 STK_ASSERT(pipe != nullptr);
531
532 return pipe->handle.GetElementSize();
533}
534
536{
537 STK_ASSERT(pipe != nullptr);
538
539 return pipe->handle.GetCount();
540}
541
543{
544 STK_ASSERT(pipe != nullptr);
545
546 return pipe->handle.GetSpace();
547}
548
550{
551 STK_ASSERT(pipe != nullptr);
552
553 return pipe->handle.IsEmpty();
554}
555
557{
558 STK_ASSERT(pipe != nullptr);
559
560 return pipe->handle.IsFull();
561}
562
564{
565 STK_ASSERT(pipe != nullptr);
566
567 return pipe->handle.IsStorageValid();
568}
569
570// -----------------------------------------------------------------------------
571// MessageQueue
572// -----------------------------------------------------------------------------
574{
575 stk_msgq_t(uint8_t *buf, size_t capacity, size_t msg_size)
576 : handle(buf, capacity, msg_size)
577 {}
578
580};
581
583 uint32_t membuf_size,
584 uint8_t *buf,
585 uint32_t buf_size,
586 size_t capacity,
587 size_t msg_size)
588{
589 STK_ASSERT(membuf != nullptr);
590 STK_ASSERT(buf != nullptr);
591 STK_ASSERT(capacity >= 1U);
592 STK_ASSERT(msg_size >= 1U);
593 STK_ASSERT(membuf_size >= sizeof(stk_msgq_t));
594 STK_ASSERT(buf_size >= capacity * msg_size);
595
596 stk_msgq_t *result = nullptr;
597 if ((membuf_size >= sizeof(stk_msgq_t)) && (buf_size >= (capacity * msg_size)))
598 {
599 result = new (membuf) stk_msgq_t(buf, capacity, msg_size);
600 }
601
602 return result;
603}
604
606{
607 if (mq != nullptr)
608 {
609 mq->~stk_msgq_t();
610 }
611}
612
613bool stk_msgq_put(stk_msgq_t *mq, const void *msg, stk_timeout_t timeout)
614{
615 STK_ASSERT(mq != nullptr);
616 STK_ASSERT(msg != nullptr);
617
618 return mq->handle.Put(msg, timeout);
619}
620
621bool stk_msgq_tryput(stk_msgq_t *mq, const void *msg)
622{
623 STK_ASSERT(mq != nullptr);
624 STK_ASSERT(msg != nullptr);
625
626 return mq->handle.TryPut(msg);
627}
628
629bool stk_msgq_putfront(stk_msgq_t *mq, const void *msg, stk_timeout_t timeout)
630{
631 STK_ASSERT(mq != nullptr);
632 STK_ASSERT(msg != nullptr);
633
634 return mq->handle.PutFront(msg, timeout);
635}
636
637bool stk_msgq_tryputfront(stk_msgq_t *mq, const void *msg)
638{
639 STK_ASSERT(mq != nullptr);
640 STK_ASSERT(msg != nullptr);
641
642 return mq->handle.TryPutFront(msg);
643}
644
645bool stk_msgq_get(stk_msgq_t *mq, void *msg, stk_timeout_t timeout)
646{
647 STK_ASSERT(mq != nullptr);
648 STK_ASSERT(msg != nullptr);
649
650 return mq->handle.Get(msg, timeout);
651}
652
653bool stk_msgq_tryget(stk_msgq_t *mq, void *msg)
654{
655 STK_ASSERT(mq != nullptr);
656 STK_ASSERT(msg != nullptr);
657
658 return mq->handle.TryGet(msg);
659}
660
661bool stk_msgq_peek(stk_msgq_t *mq, void *msg, stk_timeout_t timeout)
662{
663 STK_ASSERT(mq != nullptr);
664 STK_ASSERT(msg != nullptr);
665
666 return mq->handle.Peek(msg, timeout);
667}
668
669bool stk_msgq_trypeek(stk_msgq_t *mq, void *msg)
670{
671 STK_ASSERT(mq != nullptr);
672 STK_ASSERT(msg != nullptr);
673
674 return mq->handle.TryPeek(msg);
675}
676
677bool stk_msgq_peekfront(stk_msgq_t *mq, void *msg, stk_timeout_t timeout)
678{
679 STK_ASSERT(mq != nullptr);
680 STK_ASSERT(msg != nullptr);
681
682 return mq->handle.PeekFront(msg, timeout);
683}
684
686{
687 STK_ASSERT(mq != nullptr);
688 STK_ASSERT(msg != nullptr);
689
690 return mq->handle.TryPeekFront(msg);
691}
692
694{
695 STK_ASSERT(mq != nullptr);
696
697 mq->handle.Reset();
698}
699
701{
702 STK_ASSERT(mq != nullptr);
703
704 return mq->handle.GetCapacity();
705}
706
708{
709 STK_ASSERT(mq != nullptr);
710
711 return mq->handle.GetMsgSize();
712}
713
715{
716 STK_ASSERT(mq != nullptr);
717
718 return mq->handle.GetCount();
719}
720
722{
723 STK_ASSERT(mq != nullptr);
724
725 return mq->handle.GetSpace();
726}
727
729{
730 STK_ASSERT(mq != nullptr);
731
732 return mq->handle.IsEmpty();
733}
734
736{
737 STK_ASSERT(mq != nullptr);
738
739 return mq->handle.IsFull();
740}
741
743{
744 STK_ASSERT(mq != nullptr);
745
746 return mq->handle.GetBuffer();
747}
748
750{
751 STK_ASSERT(mq != nullptr);
752
753 return mq->handle.IsStorageValid();
754}
755
756// -----------------------------------------------------------------------------
757// RWMutex (Reader-Writer Lock)
758// -----------------------------------------------------------------------------
763
764stk_rwmutex_t *stk_rwmutex_create(stk_rwmutex_mem_t *const membuf, uint32_t membuf_size)
765{
766 STK_ASSERT(membuf != nullptr);
767 STK_ASSERT(membuf_size >= sizeof(stk_rwmutex_t));
768
769 stk_rwmutex_t *result = nullptr;
770 if (membuf_size >= sizeof(stk_rwmutex_t))
771 {
772 result = new (membuf->data) stk_rwmutex_t();
773 }
774
775 return result;
776}
777
779{
780 if (rw != nullptr)
781 {
782 rw->~stk_rwmutex_t();
783 }
784}
785
787{
788 STK_ASSERT(rw != nullptr);
789
790 rw->handle.ReadLock();
791}
792
794{
795 STK_ASSERT(rw != nullptr);
796
797 return rw->handle.TryReadLock();
798}
799
801{
802 STK_ASSERT(rw != nullptr);
803
804 return rw->handle.TimedReadLock(timeout);
805}
806
808{
809 STK_ASSERT(rw != nullptr);
810
811 rw->handle.ReadUnlock();
812}
813
815{
816 STK_ASSERT(rw != nullptr);
817
818 rw->handle.Lock();
819}
820
822{
823 STK_ASSERT(rw != nullptr);
824
825 return rw->handle.TryLock();
826}
827
829{
830 STK_ASSERT(rw != nullptr);
831
832 return rw->handle.TimedLock(timeout);
833}
834
836{
837 STK_ASSERT(rw != nullptr);
838
839 rw->handle.Unlock();
840}
841
842// =============================================================================
843} // extern "C"
844// =============================================================================
Collection of memory-related primitives (stk::memory namespace).
Top-level STK include. Provides the Kernel class template and all built-in task-switching strategies.
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:409
Collection of synchronization primitives (stk::sync namespace).
C language binding/interface for SuperTinyKernel RTOS.
stk_rwmutex_t * stk_rwmutex_create(stk_rwmutex_mem_t *const membuf, uint32_t membuf_size)
Create an RWMutex (using provided memory).
void stk_sem_signal(stk_sem_t *sem)
Signal/Release a semaphore resource.
size_t stk_pipe_get_capacity(const stk_pipe_t *pipe)
Get the maximum number of elements the pipe can hold.
void stk_msgq_reset(stk_msgq_t *mq)
Discard all messages and reset the queue to the empty state.
bool stk_msgq_is_full(const stk_msgq_t *mq)
Check whether the queue is currently full.
uint32_t stk_ef_set(stk_ef_t *ef, uint32_t flags)
Set one or more flags.
bool stk_event_set(stk_event_t *ev)
Set the event to signaled state.
struct stk_cv_t stk_cv_t
Opaque handle to a Condition Variable instance.
Definition stk_c.h:945
uint32_t stk_ef_clear(stk_ef_t *ef, uint32_t flags)
Clear one or more flags.
void stk_mutex_destroy(stk_mutex_t *mtx)
Destroy a Mutex.
size_t stk_pipe_get_count(const stk_pipe_t *pipe)
Get the current number of elements in the pipe.
bool stk_pipe_write(stk_pipe_t *pipe, const void *data, stk_timeout_t timeout)
Write a single element to the pipe.
size_t stk_pipe_read_bulk(stk_pipe_t *pipe, void *dst, size_t count, stk_timeout_t timeout)
Read multiple elements from the pipe.
size_t stk_pipe_trywrite_bulk(stk_pipe_t *pipe, const void *src, size_t count)
Attempt to write multiple elements to the pipe without blocking.
bool stk_rwmutex_try_read_lock(stk_rwmutex_t *rw)
Try to acquire the read lock without blocking.
size_t stk_pipe_get_space(const stk_pipe_t *pipe)
Get the number of free slots currently available.
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).
uint32_t stk_ef_wait(stk_ef_t *ef, uint32_t flags, uint32_t options, stk_timeout_t timeout)
Wait for one or more flags to be set.
void stk_ef_destroy(stk_ef_t *ef)
Destroy an EventFlags object.
bool stk_event_wait(stk_event_t *ev, stk_timeout_t timeout)
Wait for the event to become signaled.
bool stk_rwmutex_trylock(stk_rwmutex_t *rw)
Try to acquire the write lock without blocking.
bool stk_cv_wait(stk_cv_t *cv, stk_mutex_t *mtx, stk_timeout_t timeout)
Wait for a signal on the condition variable.
struct stk_ef_t stk_ef_t
Opaque handle to an EventFlags instance.
Definition stk_c.h:1142
uint32_t stk_ef_trywait(stk_ef_t *ef, uint32_t flags, uint32_t options)
Non-blocking flag poll.
void stk_spinlock_destroy(stk_spinlock_t *slock)
Destroy the SpinLock.
void stk_cv_notify_one(stk_cv_t *cv)
Wake one task waiting on the condition variable.
bool stk_spinlock_trylock(stk_spinlock_t *slock)
Attempt to acquire the SpinLock immediately.
stk_msgq_t * stk_msgq_create(stk_msgq_mem_t *const membuf, uint32_t membuf_size, uint8_t *buf, uint32_t buf_size, size_t capacity, size_t msg_size)
Create a MessageQueue (using provided memory).
bool stk_msgq_tryget(stk_msgq_t *mq, void *msg)
Attempt to get a message from the queue without blocking.
bool stk_event_trywait(stk_event_t *ev)
Wait for the event to become signaled.
size_t stk_msgq_get_space(const stk_msgq_t *mq)
Get the number of free slots currently available.
void stk_event_destroy(stk_event_t *ev)
Destroy an Event.
bool stk_pipe_is_storage_valid(const stk_pipe_t *pipe)
Verify that the backing storage is valid and the pipe is ready for use.
uint16_t stk_sem_get_count(const stk_sem_t *sem)
Get the current counter value.
stk_event_t * stk_event_create(stk_event_mem_t *const membuf, uint32_t membuf_size, bool manual_reset)
Create an Event (using provided memory).
bool stk_msgq_trypeekfront(stk_msgq_t *mq, void *msg)
Attempt to peek at the front message without blocking.
bool stk_mutex_timed_lock(stk_mutex_t *mtx, stk_timeout_t timeout)
Try to lock the mutex with a timeout.
bool stk_msgq_peekfront(stk_msgq_t *mq, void *msg, stk_timeout_t timeout)
Peek at the most recently front-inserted message without removing it.
struct stk_mutex_t stk_mutex_t
Opaque handle to a Mutex instance.
Definition stk_c.h:853
void stk_mutex_lock(stk_mutex_t *mtx)
Lock the mutex. Blocks until available.
size_t stk_pipe_write_bulk(stk_pipe_t *pipe, const void *src, size_t count, stk_timeout_t timeout)
Write multiple elements to the pipe.
void stk_rwmutex_lock(stk_rwmutex_t *rw)
Acquire the lock for exclusive writing. Blocks until available.
stk_ef_t * stk_ef_create(stk_ef_mem_t *const membuf, uint32_t membuf_size, uint32_t initial_flags)
Create an EventFlags object (using provided memory).
void stk_cv_destroy(stk_cv_t *cv)
Destroy a Condition Variable.
struct stk_event_t stk_event_t
Opaque handle to an Event instance.
Definition stk_c.h:993
bool stk_msgq_is_empty(const stk_msgq_t *mq)
Check whether the queue is currently empty.
bool stk_mutex_trylock(stk_mutex_t *mtx)
Try locking the mutex. Does not block if already locked.
void stk_rwmutex_read_lock(stk_rwmutex_t *rw)
Acquire the lock for shared reading. Blocks until available.
struct stk_sem_t stk_sem_t
Opaque handle to a Semaphore instance.
Definition stk_c.h:1056
size_t stk_msgq_get_capacity(const stk_msgq_t *mq)
Get the maximum number of messages the queue can hold.
void stk_mutex_unlock(stk_mutex_t *mtx)
Unlock the mutex.
void stk_pipe_destroy(stk_pipe_t *pipe)
Destroy a Pipe.
size_t stk_pipe_get_element_size(const stk_pipe_t *pipe)
Get the size of each element in bytes.
bool stk_sem_wait(stk_sem_t *sem, stk_timeout_t timeout)
Wait for a semaphore resource.
bool stk_msgq_putfront(stk_msgq_t *mq, const void *msg, stk_timeout_t timeout)
Put a message into the front of the queue (priority insert).
size_t stk_msgq_get_count(const stk_msgq_t *mq)
Get the current number of messages waiting in the queue.
uint8_t * stk_msgq_get_buffer(stk_msgq_t *mq)
Get a pointer to the raw message data buffer.
void stk_spinlock_lock(stk_spinlock_t *slock)
Acquire the SpinLock (recursive).
bool stk_msgq_put(stk_msgq_t *mq, const void *msg, stk_timeout_t timeout)
Put a message into the queue.
bool stk_msgq_tryput(stk_msgq_t *mq, const void *msg)
Attempt to put a message into the queue without blocking.
struct stk_spinlock_t stk_spinlock_t
Opaque handle to a SpinLock instance.
Definition stk_c.h:905
struct stk_msgq_t stk_msgq_t
Opaque handle to a MessageQueue instance.
Definition stk_c.h:1494
void stk_pipe_reset(stk_pipe_t *pipe)
Discard all elements and reset the pipe to the empty state.
struct stk_pipe_t stk_pipe_t
Opaque handle to a Pipe instance.
Definition stk_c.h:1238
void stk_sem_destroy(stk_sem_t *sem)
Destroy a Semaphore.
void stk_spinlock_unlock(stk_spinlock_t *slock)
Release the SpinLock.
size_t stk_pipe_tryread_bulk_triggered(stk_pipe_t *pipe, void *dst, size_t max_count)
Non-blocking variant of stk_pipe_read_bulk_triggered.
bool stk_sem_trywait(stk_sem_t *sem)
Poll the semaphore without blocking.
stk_pipe_t * stk_pipe_create(stk_pipe_mem_t *const membuf, uint32_t membuf_size, uint8_t *buf, uint32_t buf_size, size_t capacity, size_t element_size)
Create a Pipe (using provided memory).
void stk_rwmutex_read_unlock(stk_rwmutex_t *rw)
Release the shared reader lock.
size_t stk_msgq_get_msg_size(const stk_msgq_t *mq)
Get the size of each message in bytes.
stk_spinlock_t * stk_spinlock_create(stk_spinlock_mem_t *const membuf, uint32_t membuf_size)
Create a recursive SpinLock.
bool stk_pipe_tryread(stk_pipe_t *pipe, void *data)
Attempt to read a single element from the pipe without blocking.
uint32_t stk_ef_get(stk_ef_t *ef)
Read the current flags word without modifying it.
struct stk_rwmutex_t stk_rwmutex_t
Opaque handle to an RWMutex instance.
Definition stk_c.h:1742
size_t stk_pipe_read_bulk_triggered(stk_pipe_t *pipe, void *dst, size_t trigger, size_t max_count, stk_timeout_t timeout)
Read at least trigger elements, then drain up to max_count without blocking.
bool stk_msgq_get(stk_msgq_t *mq, void *msg, stk_timeout_t timeout)
Get a message from the queue.
void stk_event_pulse(stk_event_t *ev)
Pulse the event (signal then immediately reset).
bool stk_msgq_tryputfront(stk_msgq_t *mq, const void *msg)
Attempt to put a message into the front of the queue without blocking.
bool stk_pipe_is_full(const stk_pipe_t *pipe)
Check whether the pipe is currently full.
bool stk_pipe_is_empty(const stk_pipe_t *pipe)
Check whether the pipe is currently empty.
bool stk_pipe_read(stk_pipe_t *pipe, void *data, stk_timeout_t timeout)
Read a single element from the pipe.
stk_cv_t * stk_cv_create(stk_cv_mem_t *const membuf, uint32_t membuf_size)
Create a Condition Variable (using provided memory).
stk_mutex_t * stk_mutex_create(stk_mutex_mem_t *const membuf, uint32_t membuf_size)
Create a Mutex (using provided memory).
bool stk_event_reset(stk_event_t *ev)
Reset the event to non-signaled state.
bool stk_msgq_is_storage_valid(const stk_msgq_t *mq)
Verify that the backing storage is valid and the queue is ready for use.
bool stk_rwmutex_timed_lock(stk_rwmutex_t *rw, stk_timeout_t timeout)
Try to acquire the write lock with a timeout.
void stk_rwmutex_destroy(stk_rwmutex_t *rw)
Destroy an RWMutex.
void stk_msgq_destroy(stk_msgq_t *mq)
Destroy a MessageQueue.
bool stk_rwmutex_timed_read_lock(stk_rwmutex_t *rw, stk_timeout_t timeout)
Try to acquire the read lock with a timeout.
int32_t stk_timeout_t
Timeout value.
Definition stk_c.h:113
bool stk_msgq_peek(stk_msgq_t *mq, void *msg, stk_timeout_t timeout)
Peek at the next message to be delivered without removing it.
bool stk_msgq_trypeek(stk_msgq_t *mq, void *msg)
Attempt to peek at the next message without blocking.
void stk_cv_notify_all(stk_cv_t *cv)
Wake all tasks waiting on the condition variable.
bool stk_pipe_trywrite(stk_pipe_t *pipe, const void *data)
Attempt to write a single element to the pipe without blocking.
void stk_rwmutex_unlock(stk_rwmutex_t *rw)
Release the exclusive writer lock.
size_t stk_pipe_tryread_bulk(stk_pipe_t *pipe, void *dst, size_t count)
Attempt to read multiple elements from the pipe without blocking.
Namespace of STK package.
Synchronization primitives for task coordination and resource protection.
Condition Variable primitive for signaling between tasks based on specific predicates.
Definition stk_sync_cv.h:68
void NotifyOne()
Wake one waiting task.
bool Wait(IMutex &mutex, Timeout timeout_ticks=WAIT_INFINITE)
Wait for a signal.
void NotifyAll()
Wake all waiting tasks.
Binary synchronization event (signaled / non-signaled) primitive.
bool Set()
Set event to signaled state.
void Pulse()
Pulse event: attempt to release waiters and then reset (Win32 PulseEvent() semantics).
bool TryWait()
Poll event state without blocking.
bool Reset()
Reset event to non-signaled state.
bool Wait(Timeout timeout_ticks=WAIT_INFINITE)
Wait until event becomes signaled or the timeout expires.
32-bit event flags group for multi-flag synchronization between tasks.
uint32_t Wait(uint32_t flags, uint32_t options=OPT_WAIT_ANY, Timeout timeout_ticks=WAIT_INFINITE)
Wait for one or more flags to be set.
uint32_t Get() const
Read the current flags word without modifying it.
uint32_t TryWait(uint32_t flags, uint32_t options=OPT_WAIT_ANY)
Non-blocking flag poll.
uint32_t Clear(uint32_t flags)
Clear one or more flags.
uint32_t Set(uint32_t flags)
Set one or more flags.
Fixed-capacity, fixed-message-size FIFO queue for inter-task communication.
bool TryPeek(void *msg_ptr)
Attempt to peek at the next message without blocking.
bool TryPeekFront(void *msg_ptr)
Attempt to peek at the front message without blocking.
bool IsEmpty() const
Check whether the queue is currently empty.
bool PeekFront(void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Peek at the most recently front-inserted message (front of the FIFO) without removing it.
size_t GetCapacity() const
Get the maximum number of messages the queue can hold.
bool TryPutFront(const void *msg_ptr)
Attempt to put a message into the front of the queue without blocking.
size_t GetMsgSize() const
Get the size of each message in bytes.
bool TryPut(const void *msg_ptr)
Attempt to put a message into the back of the queue without blocking.
size_t GetSpace() const
Get the number of free slots currently available.
size_t GetCount() const
Get the current number of messages in the queue.
bool TryGet(void *msg_ptr)
Attempt to get a message from the queue without blocking.
uint8_t * GetBuffer()
Get pointer to the message buffer.
bool Peek(void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Peek at the next message to be delivered (back of the FIFO) without removing it.
bool PutFront(const void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Put a message into the front of the queue (LIFO / priority-insert order).
bool IsStorageValid() const
Verify that the backing storage is valid and the pool is ready for use.
bool Put(const void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Put a message into the back of the queue (FIFO order).
bool Get(void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Get a message from the queue.
bool IsFull() const
Check whether the queue is currently full.
void Reset()
Discard all messages and reset the queue to the empty state.
Recursive mutex primitive that allows the same thread to acquire the lock multiple times.
bool TimedLock(Timeout timeout_ticks)
Acquire lock.
bool TryLock()
Acquire the lock.
void Unlock() override
Release lock.
void Lock() override
Acquire lock.
Thread-safe FIFO communication pipe for inter-task data passing.
size_t WriteBulk(const void *src, size_t count, Timeout timeout_ticks=WAIT_INFINITE)
Write multiple elements to the pipe.
bool TryRead(void *data)
Attempt to read a single element from the pipe without blocking.
size_t TryReadBulkTriggered(void *dst, size_t max_count)
Non-blocking variant of ReadBulkTriggered.
void Reset()
Discard all elements and reset the pipe to the empty state.
bool Read(void *data, Timeout timeout_ticks=WAIT_INFINITE)
Read a single element from the pipe.
size_t ReadBulk(void *dst, size_t count, Timeout timeout_ticks=WAIT_INFINITE)
Read multiple elements from the pipe.
bool Write(const void *data, Timeout timeout_ticks=WAIT_INFINITE)
Write a single element to the pipe.
size_t GetElementSize() const
Get the size of each element in bytes.
size_t TryWriteBulk(const void *src, size_t count)
Attempt to write multiple elements to the pipe without blocking.
bool IsEmpty() const
Check if the pipe is currently empty.
size_t GetCapacity() const
Get the maximum number of elements the pipe can hold.
bool TryWrite(const void *data)
Attempt to write a single element to the pipe without blocking.
size_t GetCount() const
Get the current number of elements in the pipe.
bool IsFull() const
Check if the pipe is currently full.
size_t TryReadBulk(void *dst, size_t count)
Attempt to read multiple elements from the pipe without blocking.
size_t GetSpace() const
Get the number of free slots currently available.
size_t ReadBulkTriggered(void *dst, size_t trigger, size_t max_count, Timeout timeout_ticks=WAIT_INFINITE)
Read at least trigger elements, then drain up to max_count without blocking.
bool IsStorageValid() const
Verify that the backing storage is valid and the pipe is ready for use.
Reader-Writer Lock synchronization primitive for non-recursive shared and exclusive access.
bool TryLock()
Attempt to acquire the lock for exclusive writing without blocking.
bool TimedLock(Timeout timeout_ticks)
Acquire the lock for exclusive writing with a timeout.
void Unlock() override
Release the exclusive writer lock (IMutex interface).
void Lock() override
Acquire the lock for exclusive writing (IMutex interface).
bool TimedReadLock(Timeout timeout_ticks)
Acquire the lock for shared reading with a timeout.
void ReadUnlock()
Release the shared reader lock.
void ReadLock()
Acquire the lock for shared reading.
bool TryReadLock()
Attempt to acquire the lock for shared reading without blocking.
Counting semaphore primitive for resource management and signaling.
void Signal()
Post a signal (increment counter).
uint16_t GetCount() const
Get current counter value.
static const uint16_t COUNT_MAX
Max count value supported.
bool Wait(Timeout timeout_ticks=WAIT_INFINITE)
Wait for a signal (decrement counter).
bool TryWait()
Poll the semaphore without blocking (decrement counter if available).
Recursive spinlock.
void Unlock()
Release the lock or decrement the recursion counter.
bool TryLock()
Attempt to acquire the lock without blocking.
void Lock()
Acquire the lock.
Opaque memory container for a Mutex instance.
Definition stk_c.h:847
stk_word_t data[(10U+((0) ? 1U :0U))]
Definition stk_c.h:848
Opaque memory container for SpinLock object.
Definition stk_c.h:899
stk_word_t data[(1)]
Definition stk_c.h:900
Opaque memory container for a ConditionVariable instance.
Definition stk_c.h:939
stk_word_t data[(7U+((0) ? 1U :0U))]
Definition stk_c.h:940
Opaque memory container for an Event instance.
Definition stk_c.h:987
stk_word_t data[(8U+((0) ? 1U :0U))]
Definition stk_c.h:988
Opaque memory container for a Semaphore instance.
Definition stk_c.h:1050
stk_word_t data[(8U+((0) ? 1U :0U))]
Definition stk_c.h:1051
Opaque memory container for an EventFlags instance.
Definition stk_c.h:1136
stk_word_t data[((7U+((0) ? 1U :0U))+1U+((0) ? 1U :0U))]
Definition stk_c.h:1137
Opaque memory container for a Pipe control-block.
Definition stk_c.h:1232
stk_word_t data[(6U+(2U *(7U+((0) ? 1U :0U)))+((0) ? 1U :0U))]
Definition stk_c.h:1233
Opaque memory container for a MessageQueue instance.
Definition stk_c.h:1488
Opaque memory container for an RWMutex instance.
Definition stk_c.h:1736
stk_word_t data[(17U+((0) ? 3U :0U))]
Definition stk_c.h:1737
sync::SpinLock handle
ConditionVariable handle
stk_event_t(bool manual_reset)
stk_sem_t(uint32_t initial_count, uint32_t max_count)
Semaphore handle
EventFlags handle
stk_ef_t(uint32_t initial_flags)
stk_pipe_t(uint8_t *buf, size_t capacity, size_t element_size)
MessageQueue handle
stk_msgq_t(uint8_t *buf, size_t capacity, size_t msg_size)
sync::RWMutex handle