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
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));
40 "stk_mutex_mem_t is too small to hold stk_mutex_t");
41
42 stk_mutex_t *result = nullptr;
43 if (membuf_size >= sizeof(stk_mutex_t))
44 {
45 result = new (membuf->data) stk_mutex_t();
46 }
47
48 return result;
49}
50
52{
53 if (mtx != nullptr)
54 {
55 mtx->~stk_mutex_t();
56 }
57}
58
60{
61 STK_ASSERT(mtx != nullptr);
62
63 mtx->handle.Lock();
64}
65
67{
68 STK_ASSERT(mtx != nullptr);
69
70 return mtx->handle.TryLock();
71}
72
74{
75 STK_ASSERT(mtx != nullptr);
76
77 mtx->handle.Unlock();
78}
79
81{
82 STK_ASSERT(mtx != nullptr);
83
84 return mtx->handle.TimedLock(timeout);
85}
86
88{
89 STK_ASSERT(mtx != nullptr);
90
91 return &mtx->handle;
92}
93
94// -----------------------------------------------------------------------------
95// SpinLock
96// -----------------------------------------------------------------------------
101
102stk_spinlock_t *stk_spinlock_create(stk_spinlock_mem_t *const membuf, uint32_t membuf_size)
103{
104 STK_ASSERT(membuf != nullptr);
105 STK_ASSERT(membuf_size >= sizeof(stk_spinlock_t));
107 "stk_spinlock_mem_t is too small to hold stk_spinlock_t");
108
109 stk_spinlock_t *result = nullptr;
110 if (membuf_size >= sizeof(stk_spinlock_t))
111 {
112 result = new (membuf->data) stk_spinlock_t();
113 }
114
115 return result;
116}
117
119{
120 if (slock != nullptr)
121 {
122 slock->~stk_spinlock_t();
123 }
124}
125
127{
128 STK_ASSERT(slock != nullptr);
129 slock->handle.Lock();
130}
131
133{
134 STK_ASSERT(slock != nullptr);
135 return slock->handle.TryLock();
136}
137
139{
140 STK_ASSERT(slock != nullptr);
141 slock->handle.Unlock();
142}
143
145{
146 STK_ASSERT(slock != nullptr);
147
148 return &slock->handle;
149}
150
151// -----------------------------------------------------------------------------
152// ConditionVariable
153// -----------------------------------------------------------------------------
158
159stk_cv_t *stk_cv_create(stk_cv_mem_t *const membuf, uint32_t membuf_size)
160{
161 STK_ASSERT(membuf != nullptr);
162 STK_ASSERT(membuf_size >= sizeof(stk_cv_t));
163 STK_STATIC_ASSERT_N((sizeof(stk_cv_t) <= sizeof(stk_cv_mem_t)),
164 "stk_cv_mem_t is too small to hold stk_cv_t");
165
166 stk_cv_t *result = nullptr;
167 if (membuf_size >= sizeof(stk_cv_t))
168 {
169 result = new (membuf->data) stk_cv_t();
170 }
171
172 return result;
173}
174
176{
177 if (cv != nullptr)
178 {
179 cv->~stk_cv_t();
180 }
181}
182
184{
185 STK_ASSERT(cv != nullptr);
186 STK_ASSERT(mtx != nullptr);
187
188 return cv->handle.Wait(mtx->handle, timeout);
189}
190
192{
193 STK_ASSERT(cv != nullptr);
194
195 cv->handle.NotifyOne();
196}
197
199{
200 STK_ASSERT(cv != nullptr);
201
202 cv->handle.NotifyAll();
203}
204
206{
207 STK_ASSERT(cv != nullptr);
208
209 return &cv->handle;
210}
211
212// -----------------------------------------------------------------------------
213// Event
214// -----------------------------------------------------------------------------
216{
217 stk_event_t(bool manual_reset) : handle(manual_reset)
218 {}
219
221};
222
224 uint32_t membuf_size,
225 bool manual_reset)
226{
227 STK_ASSERT(membuf != nullptr);
228 STK_ASSERT(membuf_size >= sizeof(stk_event_t));
230 "stk_event_mem_t is too small to hold stk_event_t");
231
232 stk_event_t *result = nullptr;
233 if (membuf_size >= sizeof(stk_event_t))
234 {
235 result = new (membuf->data) stk_event_t(manual_reset);
236 }
237
238 return result;
239}
240
242{
243 if (ev != nullptr)
244 {
245 ev->~stk_event_t();
246 }
247}
248
250{
251 STK_ASSERT(ev != nullptr);
252
253 return ev->handle.Wait(timeout);
254}
255
257{
258 STK_ASSERT(ev != nullptr);
259
260 return ev->handle.TryWait();
261}
262
264{
265 STK_ASSERT(ev != nullptr);
266
267 return ev->handle.Set();
268}
269
271{
272 STK_ASSERT(ev != nullptr);
273
274 return ev->handle.Reset();
275}
276
278{
279 STK_ASSERT(ev != nullptr);
280
281 ev->handle.Pulse();
282}
283
285{
286 STK_ASSERT(ev != nullptr);
287
288 return &ev->handle;
289}
290
291// -----------------------------------------------------------------------------
292// Semaphore
293// -----------------------------------------------------------------------------
295{
296 stk_sem_t(uint32_t initial_count, uint32_t max_count)
297 : handle(static_cast<uint16_t>(initial_count),
298 static_cast<uint16_t>(max_count))
299 {}
300
302};
303
305 uint32_t membuf_size,
306 uint32_t initial_count,
307 uint32_t max_count)
308{
309 STK_ASSERT(membuf != nullptr);
310 STK_ASSERT(membuf_size >= sizeof(stk_sem_t));
311 STK_STATIC_ASSERT_N((sizeof(stk_sem_t) <= sizeof(stk_sem_mem_t)),
312 "stk_sem_mem_t is too small to hold stk_sem_t");
313
314 stk_sem_t *result = nullptr;
315 if (membuf_size >= sizeof(stk_sem_t))
316 {
317 const uint32_t effective_max = ((max_count == 0U) ? Semaphore::COUNT_MAX : max_count);
318 result = new (membuf->data) stk_sem_t(initial_count, effective_max);
319 }
320
321 return result;
322}
323
325{
326 if (sem != nullptr)
327 {
328 sem->~stk_sem_t();
329 }
330}
331
333{
334 STK_ASSERT(sem != nullptr);
335
336 return sem->handle.Wait(timeout);
337}
338
340{
341 STK_ASSERT(sem != nullptr);
342
343 return sem->handle.TryWait();
344}
345
347{
348 STK_ASSERT(sem != nullptr);
349
350 sem->handle.Signal();
351}
352
354{
355 STK_ASSERT(sem != nullptr);
356
357 return sem->handle.TrySignal();
358}
359
360uint16_t stk_sem_get_count(const stk_sem_t *sem)
361{
362 STK_ASSERT(sem != nullptr);
363
364 return sem->handle.GetCount();
365}
366
368{
369 STK_ASSERT(sem != nullptr);
370
371 return &sem->handle;
372}
373
374// -----------------------------------------------------------------------------
375// EventFlags
376// -----------------------------------------------------------------------------
378{
379 stk_ef_t(uint32_t initial_flags) : handle(initial_flags)
380 {}
381
383};
384
386 uint32_t membuf_size,
387 uint32_t initial_flags)
388{
389 STK_ASSERT(membuf != nullptr);
390 STK_ASSERT(membuf_size >= sizeof(stk_ef_t));
391 STK_STATIC_ASSERT_N((sizeof(stk_ef_t) <= sizeof(stk_ef_mem_t)),
392 "stk_ef_mem_t is too small to hold stk_ef_t");
393
394 stk_ef_t *result = nullptr;
395 if (membuf_size >= sizeof(stk_ef_t))
396 {
397 result = new (membuf->data) stk_ef_t(initial_flags);
398 }
399
400 return result;
401}
402
404{
405 if (ef != nullptr)
406 {
407 ef->~stk_ef_t();
408 }
409}
410
411uint32_t stk_ef_set(stk_ef_t *ef, uint32_t flags)
412{
413 STK_ASSERT(ef != nullptr);
414
415 return ef->handle.Set(flags);
416}
417
418uint32_t stk_ef_clear(stk_ef_t *ef, uint32_t flags)
419{
420 STK_ASSERT(ef != nullptr);
421
422 return ef->handle.Clear(flags);
423}
424
425uint32_t stk_ef_get(stk_ef_t *ef)
426{
427 STK_ASSERT(ef != nullptr);
428
429 return ef->handle.Get();
430}
431
432uint32_t stk_ef_wait(stk_ef_t *ef, uint32_t flags, uint32_t options, stk_timeout_t timeout)
433{
434 STK_ASSERT(ef != nullptr);
435
436 return ef->handle.Wait(flags, options, timeout);
437}
438
439uint32_t stk_ef_trywait(stk_ef_t *ef, uint32_t flags, uint32_t options)
440{
441 STK_ASSERT(ef != nullptr);
442
443 return ef->handle.TryWait(flags, options);
444}
445
447{
448 STK_ASSERT(ef != nullptr);
449
450 return &ef->handle;
451}
452
453// -----------------------------------------------------------------------------
454// Pipe (runtime-sized, external-buffer; wraps sync::Pipe)
455// -----------------------------------------------------------------------------
457{
459
460 stk_pipe_t(uint8_t *buf, size_t capacity, size_t element_size)
461 : handle(buf, capacity, element_size)
462 {}
463};
464
466 uint32_t membuf_size,
467 uint8_t *buf,
468 uint32_t buf_size,
469 size_t capacity,
470 size_t element_size)
471{
472 STK_ASSERT(membuf != nullptr);
473 STK_ASSERT(buf != nullptr);
474 STK_ASSERT(capacity >= 1U);
475 STK_ASSERT(element_size >= 1U);
476 STK_ASSERT(membuf_size >= sizeof(stk_pipe_t));
477 STK_ASSERT(buf_size >= capacity * element_size);
478 STK_STATIC_ASSERT_N((sizeof(stk_pipe_t) <= sizeof(stk_pipe_mem_t)),
479 "stk_pipe_mem_t is too small to hold stk_pipe_t");
480
481 stk_pipe_t *result = nullptr;
482 if ((membuf_size >= sizeof(stk_pipe_t)) && (buf_size >= (capacity * element_size)))
483 {
484 result = new (membuf->data) stk_pipe_t(buf, capacity, element_size);
485 }
486
487 return result;
488}
489
491{
492 if (pipe != nullptr)
493 {
494 pipe->~stk_pipe_t();
495 }
496}
497
498bool stk_pipe_write(stk_pipe_t *pipe, const void *data, stk_timeout_t timeout)
499{
500 STK_ASSERT(pipe != nullptr);
501 STK_ASSERT(data != nullptr);
502
503 return pipe->handle.Write(data, timeout);
504}
505
506bool stk_pipe_trywrite(stk_pipe_t *pipe, const void *data)
507{
508 STK_ASSERT(pipe != nullptr);
509 STK_ASSERT(data != nullptr);
510
511 return pipe->handle.TryWrite(data);
512}
513
514bool stk_pipe_read(stk_pipe_t *pipe, void *data, stk_timeout_t timeout)
515{
516 STK_ASSERT(pipe != nullptr);
517 STK_ASSERT(data != nullptr);
518
519 return pipe->handle.Read(data, timeout);
520}
521
522bool stk_pipe_tryread(stk_pipe_t *pipe, void *data)
523{
524 STK_ASSERT(pipe != nullptr);
525 STK_ASSERT(data != nullptr);
526
527 return pipe->handle.TryRead(data);
528}
529
530size_t stk_pipe_write_bulk(stk_pipe_t *pipe, const void *src, size_t count, stk_timeout_t timeout)
531{
532 STK_ASSERT(pipe != nullptr);
533
534 return pipe->handle.WriteBulk(src, count, timeout);
535}
536
537size_t stk_pipe_trywrite_bulk(stk_pipe_t *pipe, const void *src, size_t count)
538{
539 STK_ASSERT(pipe != nullptr);
540
541 return pipe->handle.TryWriteBulk(src, count);
542}
543
544size_t stk_pipe_read_bulk(stk_pipe_t *pipe, void *dst, size_t count, stk_timeout_t timeout)
545{
546 STK_ASSERT(pipe != nullptr);
547
548 return pipe->handle.ReadBulk(dst, count, timeout);
549}
550
551size_t stk_pipe_tryread_bulk(stk_pipe_t *pipe, void *dst, size_t count)
552{
553 STK_ASSERT(pipe != nullptr);
554
555 return pipe->handle.TryReadBulk(dst, count);
556}
557
559 void *dst,
560 size_t trigger,
561 size_t max_count,
562 stk_timeout_t timeout)
563{
564 STK_ASSERT(pipe != nullptr);
565
566 return pipe->handle.ReadBulkTriggered(dst, trigger, max_count, timeout);
567}
568
569size_t stk_pipe_tryread_bulk_triggered(stk_pipe_t *pipe, void *dst, size_t max_count)
570{
571 STK_ASSERT(pipe != nullptr);
572
573 return pipe->handle.TryReadBulkTriggered(dst, max_count);
574}
575
577{
578 STK_ASSERT(pipe != nullptr);
579
580 pipe->handle.Reset();
581}
582
584{
585 STK_ASSERT(pipe != nullptr);
586
587 return pipe->handle.GetCapacity();
588}
589
591{
592 STK_ASSERT(pipe != nullptr);
593
594 return pipe->handle.GetElementSize();
595}
596
598{
599 STK_ASSERT(pipe != nullptr);
600
601 return pipe->handle.GetCount();
602}
603
605{
606 STK_ASSERT(pipe != nullptr);
607
608 return pipe->handle.GetSpace();
609}
610
612{
613 STK_ASSERT(pipe != nullptr);
614
615 return pipe->handle.IsEmpty();
616}
617
619{
620 STK_ASSERT(pipe != nullptr);
621
622 return pipe->handle.IsFull();
623}
624
626{
627 STK_ASSERT(pipe != nullptr);
628
629 return pipe->handle.IsStorageValid();
630}
631
633{
634 STK_ASSERT(pipe != nullptr);
635
636 return &pipe->handle;
637}
638
639// -----------------------------------------------------------------------------
640// MessageQueue
641// -----------------------------------------------------------------------------
643{
644 stk_msgq_t(uint8_t *buf, size_t capacity, size_t msg_size)
645 : handle(buf, capacity, msg_size)
646 {}
647
649};
650
652 uint32_t membuf_size,
653 uint8_t *buf,
654 uint32_t buf_size,
655 size_t capacity,
656 size_t msg_size)
657{
658 STK_ASSERT(membuf != nullptr);
659 STK_ASSERT(buf != nullptr);
660 STK_ASSERT(capacity >= 1U);
661 STK_ASSERT(msg_size >= 1U);
662 STK_ASSERT(membuf_size >= sizeof(stk_msgq_t));
663 STK_ASSERT(buf_size >= capacity * msg_size);
664 STK_STATIC_ASSERT_N((sizeof(stk_msgq_t) <= sizeof(stk_msgq_mem_t)),
665 "stk_msgq_mem_t is too small to hold stk_msgq_t");
666
667 stk_msgq_t *result = nullptr;
668 if ((membuf_size >= sizeof(stk_msgq_t)) && (buf_size >= (capacity * msg_size)))
669 {
670 result = new (membuf) stk_msgq_t(buf, capacity, msg_size);
671 }
672
673 return result;
674}
675
677{
678 if (mq != nullptr)
679 {
680 mq->~stk_msgq_t();
681 }
682}
683
684bool stk_msgq_put(stk_msgq_t *mq, const void *msg, stk_timeout_t timeout)
685{
686 STK_ASSERT(mq != nullptr);
687 STK_ASSERT(msg != nullptr);
688
689 return mq->handle.Put(msg, timeout);
690}
691
692bool stk_msgq_tryput(stk_msgq_t *mq, const void *msg)
693{
694 STK_ASSERT(mq != nullptr);
695 STK_ASSERT(msg != nullptr);
696
697 return mq->handle.TryPut(msg);
698}
699
700bool stk_msgq_putfront(stk_msgq_t *mq, const void *msg, stk_timeout_t timeout)
701{
702 STK_ASSERT(mq != nullptr);
703 STK_ASSERT(msg != nullptr);
704
705 return mq->handle.PutFront(msg, timeout);
706}
707
708bool stk_msgq_tryputfront(stk_msgq_t *mq, const void *msg)
709{
710 STK_ASSERT(mq != nullptr);
711 STK_ASSERT(msg != nullptr);
712
713 return mq->handle.TryPutFront(msg);
714}
715
716bool stk_msgq_get(stk_msgq_t *mq, void *msg, stk_timeout_t timeout)
717{
718 STK_ASSERT(mq != nullptr);
719 STK_ASSERT(msg != nullptr);
720
721 return mq->handle.Get(msg, timeout);
722}
723
724bool stk_msgq_tryget(stk_msgq_t *mq, void *msg)
725{
726 STK_ASSERT(mq != nullptr);
727 STK_ASSERT(msg != nullptr);
728
729 return mq->handle.TryGet(msg);
730}
731
732bool stk_msgq_peek(stk_msgq_t *mq, void *msg, stk_timeout_t timeout)
733{
734 STK_ASSERT(mq != nullptr);
735 STK_ASSERT(msg != nullptr);
736
737 return mq->handle.Peek(msg, timeout);
738}
739
740bool stk_msgq_trypeek(stk_msgq_t *mq, void *msg)
741{
742 STK_ASSERT(mq != nullptr);
743 STK_ASSERT(msg != nullptr);
744
745 return mq->handle.TryPeek(msg);
746}
747
748bool stk_msgq_peekfront(stk_msgq_t *mq, void *msg, stk_timeout_t timeout)
749{
750 STK_ASSERT(mq != nullptr);
751 STK_ASSERT(msg != nullptr);
752
753 return mq->handle.PeekFront(msg, timeout);
754}
755
757{
758 STK_ASSERT(mq != nullptr);
759 STK_ASSERT(msg != nullptr);
760
761 return mq->handle.TryPeekFront(msg);
762}
763
765{
766 STK_ASSERT(mq != nullptr);
767
768 mq->handle.Reset();
769}
770
772{
773 STK_ASSERT(mq != nullptr);
774
775 return mq->handle.GetCapacity();
776}
777
779{
780 STK_ASSERT(mq != nullptr);
781
782 return mq->handle.GetMsgSize();
783}
784
786{
787 STK_ASSERT(mq != nullptr);
788
789 return mq->handle.GetCount();
790}
791
793{
794 STK_ASSERT(mq != nullptr);
795
796 return mq->handle.GetSpace();
797}
798
800{
801 STK_ASSERT(mq != nullptr);
802
803 return mq->handle.IsEmpty();
804}
805
807{
808 STK_ASSERT(mq != nullptr);
809
810 return mq->handle.IsFull();
811}
812
814{
815 STK_ASSERT(mq != nullptr);
816
817 return mq->handle.GetBuffer();
818}
819
821{
822 STK_ASSERT(mq != nullptr);
823
824 return mq->handle.IsStorageValid();
825}
826
828{
829 STK_ASSERT(mq != nullptr);
830
831 return &mq->handle;
832}
833
834// -----------------------------------------------------------------------------
835// RWMutex (Reader-Writer Lock)
836// -----------------------------------------------------------------------------
841
842stk_rwmutex_t *stk_rwmutex_create(stk_rwmutex_mem_t *const membuf, uint32_t membuf_size)
843{
844 STK_ASSERT(membuf != nullptr);
845 STK_ASSERT(membuf_size >= sizeof(stk_rwmutex_t));
847 "stk_rwmutex_mem_t is too small to hold stk_rwmutex_t");
848
849 stk_rwmutex_t *result = nullptr;
850 if (membuf_size >= sizeof(stk_rwmutex_t))
851 {
852 result = new (membuf->data) stk_rwmutex_t();
853 }
854
855 return result;
856}
857
859{
860 if (rw != nullptr)
861 {
862 rw->~stk_rwmutex_t();
863 }
864}
865
867{
868 STK_ASSERT(rw != nullptr);
869
870 rw->handle.ReadLock();
871}
872
874{
875 STK_ASSERT(rw != nullptr);
876
877 return rw->handle.TryReadLock();
878}
879
881{
882 STK_ASSERT(rw != nullptr);
883
884 return rw->handle.TimedReadLock(timeout);
885}
886
888{
889 STK_ASSERT(rw != nullptr);
890
891 rw->handle.ReadUnlock();
892}
893
895{
896 STK_ASSERT(rw != nullptr);
897
898 rw->handle.Lock();
899}
900
902{
903 STK_ASSERT(rw != nullptr);
904
905 return rw->handle.TryLock();
906}
907
909{
910 STK_ASSERT(rw != nullptr);
911
912 return rw->handle.TimedLock(timeout);
913}
914
916{
917 STK_ASSERT(rw != nullptr);
918
919 rw->handle.Unlock();
920}
921
923{
924 STK_ASSERT(rw != nullptr);
925
926 return &rw->handle;
927}
928
929// -----------------------------------------------------------------------------
930// Barrier
931// -----------------------------------------------------------------------------
933{
934 explicit stk_barrier_t(uint32_t count) : handle(count)
935 {}
936
938};
939
940stk_barrier_t *stk_barrier_create(stk_barrier_mem_t *const membuf, uint32_t membuf_size, uint32_t count)
941{
942 STK_ASSERT(membuf != nullptr);
943 STK_ASSERT(membuf_size >= sizeof(stk_barrier_t));
944 STK_ASSERT(count != 0U);
946 "stk_barrier_mem_t is too small to hold stk_barrier_t");
947
948 stk_barrier_t *result = nullptr;
949 if ((membuf_size >= sizeof(stk_barrier_t)) && (count != 0U))
950 {
951 result = new (membuf->data) stk_barrier_t(count);
952 }
953
954 return result;
955}
956
958{
959 if (barrier != nullptr)
960 {
961 barrier->~stk_barrier_t();
962 }
963}
964
966{
967 STK_ASSERT(barrier != nullptr);
968
969 return barrier->handle.Wait();
970}
971
973{
974 STK_ASSERT(barrier != nullptr);
975
976 return barrier->handle.GetThreshold();
977}
978
980{
981 STK_ASSERT(barrier != nullptr);
982
983 return &barrier->handle;
984}
985
986// =============================================================================
987} // extern "C"
988// =============================================================================
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_STATIC_ASSERT_N(NAME, X)
Compile-time assertion with a user-defined name suffix.
Definition stk_defs.h:545
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:516
Collection of synchronization primitives (stk::sync namespace).
C language binding/interface for SuperTinyKernel RTOS.
Barrier * stk_barrier_get_instance(stk_barrier_t *barrier)
Get the underlying C++ stk::sync::Barrier object wrapped by a stk_barrier_t handle.
stk_rwmutex_t * stk_rwmutex_create(stk_rwmutex_mem_t *const membuf, uint32_t membuf_size)
Create an RWMutex (using provided memory).
EventFlags * stk_ef_get_instance(stk_ef_t *ef)
Get the underlying C++ stk::sync::EventFlags object wrapped by a stk_ef_t handle.
void stk_barrier_destroy(stk_barrier_t *barrier)
Destroy a Barrier.
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:1039
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_sem_trysignal(stk_sem_t *sem)
Try to signal/release a semaphore resource without exceeding max_count.
stk_barrier_t * stk_barrier_create(stk_barrier_mem_t *const membuf, uint32_t membuf_size, uint32_t count)
Create a Barrier (using provided memory).
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:1297
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.
sync::SpinLock * stk_spinlock_get_instance(stk_spinlock_t *slock)
Get the underlying C++ stk::sync::SpinLock object wrapped by a stk_spinlock_t handle.
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.
Semaphore * stk_sem_get_instance(stk_sem_t *sem)
Get the underlying C++ stk::sync::Semaphore object wrapped by a stk_sem_t handle.
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:922
void stk_mutex_lock(stk_mutex_t *mtx)
Lock the mutex. Blocks until available.
Pipe * stk_pipe_get_instance(stk_pipe_t *pipe)
Get the underlying C++ stk::sync::Pipe object wrapped by a stk_pipe_t handle.
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:1101
bool stk_msgq_is_empty(const stk_msgq_t *mq)
Check whether the queue is currently empty.
uint32_t stk_barrier_get_threshold(const stk_barrier_t *barrier)
Get the number of tasks required to trip the barrier.
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:1178
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.
Event * stk_event_get_instance(stk_event_t *ev)
Get the underlying C++ stk::sync::Event object wrapped by a stk_event_t handle.
struct stk_spinlock_t stk_spinlock_t
Opaque handle to a SpinLock instance.
Definition stk_c.h:988
struct stk_msgq_t stk_msgq_t
Opaque handle to a MessageQueue instance.
Definition stk_c.h:1689
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:1407
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).
sync::RWMutex * stk_rwmutex_get_instance(stk_rwmutex_t *rw)
Get the underlying C++ stk::sync::RWMutex object wrapped by a stk_rwmutex_t handle.
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.
ConditionVariable * stk_cv_get_instance(stk_cv_t *cv)
Get the underlying C++ stk::sync::ConditionVariable object wrapped by a stk_cv_t handle.
struct stk_rwmutex_t stk_rwmutex_t
Opaque handle to an RWMutex instance.
Definition stk_c.h:1963
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).
struct stk_barrier_t stk_barrier_t
Opaque handle to a Barrier instance.
Definition stk_c.h:2066
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
Mutex * stk_mutex_get_instance(stk_mutex_t *mtx)
Get the underlying C++ stk::sync::Mutex object wrapped by a stk_mutex_t handle.
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.
MessageQueue * stk_msgq_get_instance(stk_msgq_t *mq)
Get the underlying C++ stk::sync::MessageQueue object wrapped by a stk_msgq_t handle.
bool stk_barrier_wait(stk_barrier_t *barrier)
Block the calling task until count tasks have called stk_barrier_wait().
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.
Cyclic barrier that blocks a fixed-size group of tasks until all of them have arrived.
uint32_t GetThreshold() const
Get the number of tasks required to trip the barrier.
bool Wait()
Block the calling task until count tasks have called Wait().
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 TrySignal()
Try to post a signal without exceeding max_count.
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:916
stk_word_t data[(10U+((0) ? 1U :0U))]
Definition stk_c.h:917
Opaque memory container for SpinLock object.
Definition stk_c.h:982
stk_word_t data[(1)]
Definition stk_c.h:983
Opaque memory container for a ConditionVariable instance.
Definition stk_c.h:1033
stk_word_t data[(7U+((0) ? 1U :0U))]
Definition stk_c.h:1034
Opaque memory container for an Event instance.
Definition stk_c.h:1095
stk_word_t data[(8U+((0) ? 1U :0U))]
Definition stk_c.h:1096
Opaque memory container for a Semaphore instance.
Definition stk_c.h:1172
stk_word_t data[(8U+((0) ? 1U :0U))]
Definition stk_c.h:1173
Opaque memory container for an EventFlags instance.
Definition stk_c.h:1291
stk_word_t data[((7U+((0) ? 1U :0U))+1U+((0) ? 1U :0U))]
Definition stk_c.h:1292
Opaque memory container for a Pipe control-block.
Definition stk_c.h:1401
stk_word_t data[(6U+(2U *(7U+((0) ? 1U :0U)))+((0) ? 1U :0U))]
Definition stk_c.h:1402
Opaque memory container for a MessageQueue instance.
Definition stk_c.h:1683
Opaque memory container for an RWMutex instance.
Definition stk_c.h:1957
stk_word_t data[(17U+((0) ? 3U :0U))]
Definition stk_c.h:1958
Opaque memory container for a Barrier instance.
Definition stk_c.h:2060
stk_word_t data[((10U+((0) ? 1U :0U))+(7U+((0) ? 1U :0U))+4U+((0) ? 1U :0U))]
Definition stk_c.h:2061
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
stk_barrier_t(uint32_t count)