![]() |
SuperTinyKernel™ RTOS 1.08.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
|
A minimal, POSIX-named pthreads-style API for STK. The public interface needs only stk_c.h / stk_c_memory.h (no C++ headers), so it can be used from C. The implementation (stk_c_pthread.cpp) calls the STK C++ API directly for thread/task control, TLS, critical sections, sleep/yield/time and the synchronization primitives; the stk_*_mem_t blobs embedded in the pthread_* types are used as in-place storage for those C++ objects. More...
Go to the source code of this file.
Classes | |
| struct | pthread_attr_t |
| Thread creation attributes. More... | |
| struct | pthread_mutexattr_t |
| Mutex attributes. More... | |
| struct | pthread_mutex_t |
| A pthread mutex. More... | |
| struct | pthread_condattr_t |
| Condition variable attributes (currently no settable properties). More... | |
| struct | pthread_cond_t |
| A pthread condition variable. More... | |
| struct | pthread_rwlockattr_t |
| Read-write lock attributes (currently no settable properties). More... | |
| struct | pthread_rwlock_t |
| A pthread read-write lock. More... | |
| struct | pthread_spinlock_t |
| A pthread spinlock. More... | |
| struct | pthread_barrierattr_t |
| Barrier attributes (currently no settable properties). More... | |
| struct | pthread_barrier_t |
| A pthread barrier. More... | |
| struct | pthread_once_t |
| A pthread_once() control object. More... | |
Macros | |
| #define | _SYS__PTHREADTYPES_H_ |
| #define | STK_C_PTHREAD_VERSION (0x20261004) |
| Interface version. | |
| #define | STK_C_PTHREAD_MAX_THREADS (8U) |
| Maximum number of concurrently-alive pthread_t's (default: 8). | |
| #define | STK_C_PTHREAD_DEFAULT_STACK_WORDS (1024U) |
| Default per-thread stack size in stk_word_t units, used when pthread_attr_t does not specify a stack size or an external stack (default: 1024 words). | |
| #define | STK_C_PTHREAD_REAPER_STACK_WORDS (256U) |
| Stack size (in stk_word_t units) for the internal reaper task that reclaims detached-thread resources (default: 256 words). | |
| #define | STK_C_PTHREAD_KEYS_MAX (8U) |
| Maximum number of concurrently-alive pthread_key_t's (default: 8). | |
| #define | PTHREAD_CREATE_JOINABLE (0) |
| #define | PTHREAD_CREATE_DETACHED (1) |
| #define | PTHREAD_CREATE_USER_NP (0) |
| #define | PTHREAD_CREATE_PRIVILEGED_NP (1) |
| #define | PTHREAD_MUTEX_NORMAL (0) |
| #define | PTHREAD_MUTEX_DEFAULT (PTHREAD_MUTEX_NORMAL) |
| #define | PTHREAD_MUTEX_ERRORCHECK (1) |
| #define | PTHREAD_MUTEX_RECURSIVE (2) |
| #define | PTHREAD_MUTEX_INITIALIZER {0} |
| #define | PTHREAD_COND_INITIALIZER {0} |
| #define | PTHREAD_RWLOCK_INITIALIZER {0} |
| #define | PTHREAD_PROCESS_PRIVATE (0) |
| #define | PTHREAD_PROCESS_SHARED (1) |
| #define | PTHREAD_BARRIER_SERIAL_THREAD (-1) |
| Returned by pthread_barrier_wait() to exactly one arbitrary caller per round; all others receive 0. See "pthread_barrier_wait() note" in the file-level docs. | |
| #define | PTHREAD_ONCE_INIT {0} |
| #define | PTHREAD_KEYS_MAX (STK_C_PTHREAD_KEYS_MAX) |
| POSIX-standard name for STK_C_PTHREAD_KEYS_MAX (this file). | |
| #define | PTHREAD_DESTRUCTOR_ITERATIONS (4) |
| Maximum number of passes over a finishing thread's keys made while destructors keep setting new non-NULL values for their own key. See "pthread_key_t / thread-specific data" in the file-level docs. | |
Typedefs | |
| typedef struct pthread_stk_ctrl_t * | pthread_t |
| Opaque thread handle. | |
| typedef struct pthread_attr_t | pthread_attr_t |
| Thread creation attributes. | |
| typedef struct pthread_mutexattr_t | pthread_mutexattr_t |
| Mutex attributes. | |
| typedef struct pthread_mutex_t | pthread_mutex_t |
| A pthread mutex. | |
| typedef struct pthread_condattr_t | pthread_condattr_t |
| Condition variable attributes (currently no settable properties). | |
| typedef struct pthread_cond_t | pthread_cond_t |
| A pthread condition variable. | |
| typedef struct pthread_rwlockattr_t | pthread_rwlockattr_t |
| Read-write lock attributes (currently no settable properties). | |
| typedef struct pthread_rwlock_t | pthread_rwlock_t |
| A pthread read-write lock. | |
| typedef struct pthread_spinlock_t | pthread_spinlock_t |
| A pthread spinlock. | |
| typedef struct pthread_barrierattr_t | pthread_barrierattr_t |
| Barrier attributes (currently no settable properties). | |
| typedef struct pthread_barrier_t | pthread_barrier_t |
| A pthread barrier. | |
| typedef struct pthread_once_t | pthread_once_t |
| A pthread_once() control object. | |
| typedef unsigned int | pthread_key_t |
| A thread-specific data key. | |
Functions | |
| void | stk_pthread_bind_kernel (stk_kernel_t *kernel) |
| Bind the STK kernel instance that pthread_create() will add new threads to. | |
| int | pthread_attr_init (pthread_attr_t *attr) |
| Initialize a thread attributes object with default values (default stack size, no external stack, joinable). | |
| int | pthread_attr_destroy (pthread_attr_t *attr) |
| Destroy a thread attributes object (no-op; no owned resources). | |
| int | pthread_attr_setstacksize (pthread_attr_t *attr, size_t stacksize) |
| Set the requested stack size in bytes. | |
| int | pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *stacksize) |
| Get the stack size in bytes that threads created with attr will use. | |
| int | pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, size_t stacksize) |
| Supply an external, caller-owned stack buffer for the thread. | |
| int | pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr, size_t *stacksize) |
| Get the previously-set external stack (stackaddr is NULL if none set). | |
| int | pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate) |
| Set PTHREAD_CREATE_JOINABLE or PTHREAD_CREATE_DETACHED. | |
| int | pthread_attr_getdetachstate (const pthread_attr_t *attr, int *detachstate) |
| Get the current detach-state setting. | |
| int | pthread_attr_setprivileged_np (pthread_attr_t *attr, int mode) |
| Non-portable: select the STK access mode of threads created with attr. | |
| int | pthread_attr_getprivileged_np (const pthread_attr_t *attr, int *mode) |
| Non-portable: get the access mode set in attr. | |
| int | pthread_create (pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) |
| Create and start a new thread. | |
| int | pthread_join (pthread_t thread, void **retval) |
| Block until the given joinable thread finishes, then reclaim its resources. | |
| int | pthread_detach (pthread_t thread) |
| Mark a thread as detached. | |
| void | pthread_exit (void *retval) |
| Terminate the calling thread. | |
| pthread_t | pthread_self (void) |
| Return the calling thread's own handle. | |
| int | pthread_equal (pthread_t t1, pthread_t t2) |
| Compare two thread handles for equality. | |
| int | pthread_yield (void) |
| Voluntarily give up the CPU to another ready task (cooperative yield), then resume once rescheduled. | |
| int | pthread_mutexattr_init (pthread_mutexattr_t *attr) |
| Initialize a mutex attributes object with default values (PTHREAD_MUTEX_DEFAULT). | |
| int | pthread_mutexattr_destroy (pthread_mutexattr_t *attr) |
| Destroy a mutex attributes object (no-op; no owned resources). | |
| int | pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type) |
| Set the mutex type. | |
| int | pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type) |
| Get the mutex type stored in attr. | |
| int | pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) |
| Initialize a mutex. | |
| int | pthread_mutex_destroy (pthread_mutex_t *mutex) |
| Destroy a mutex, releasing the underlying STK mutex object. | |
| int | pthread_mutex_lock (pthread_mutex_t *mutex) |
| Lock a mutex, blocking until it becomes available. | |
| int | pthread_mutex_trylock (pthread_mutex_t *mutex) |
| Try to lock a mutex without blocking. | |
| int | pthread_mutex_unlock (pthread_mutex_t *mutex) |
| Unlock a mutex held by the calling thread. | |
| int | pthread_mutex_timedlock (pthread_mutex_t *mutex, const struct timespec *abstime) |
| Lock with an absolute deadline. | |
| int | pthread_condattr_init (pthread_condattr_t *attr) |
| Initialize a condition variable attributes object (no settable properties). | |
| int | pthread_condattr_destroy (pthread_condattr_t *attr) |
| Destroy a condition variable attributes object (no-op). | |
| int | pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr) |
| Initialize a condition variable. | |
| int | pthread_cond_destroy (pthread_cond_t *cond) |
| Destroy a condition variable, releasing the underlying STK object. | |
| int | pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) |
| Atomically unlock mutex and wait for a signal; re-locks mutex before returning. | |
| int | pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) |
| As pthread_cond_wait(), with an absolute deadline. | |
| int | pthread_cond_signal (pthread_cond_t *cond) |
| Wake one thread waiting on cond (no effect if none is waiting). | |
| int | pthread_cond_broadcast (pthread_cond_t *cond) |
| Wake all threads waiting on cond (no effect if none is waiting). | |
| int | pthread_rwlockattr_init (pthread_rwlockattr_t *attr) |
| Initialize a read-write lock attributes object (no settable properties). | |
| int | pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) |
| Destroy a read-write lock attributes object (no-op). | |
| int | pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) |
| Initialize a read-write lock. | |
| int | pthread_rwlock_destroy (pthread_rwlock_t *rwlock) |
| Destroy a read-write lock, releasing the underlying STK object. | |
| int | pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) |
| Acquire the lock for shared reading. Blocks until available. | |
| int | pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) |
| Try to acquire the read lock without blocking. | |
| int | pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock, const struct timespec *abstime) |
| Acquire the read lock with an absolute deadline. | |
| int | pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) |
| Acquire the lock for exclusive writing. Blocks until available. | |
| int | pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) |
| Try to acquire the write lock without blocking. | |
| int | pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, const struct timespec *abstime) |
| Acquire the write lock with an absolute deadline. | |
| int | pthread_rwlock_unlock (pthread_rwlock_t *rwlock) |
| Release a read or write hold, whichever the calling thread holds. | |
| int | pthread_spin_init (pthread_spinlock_t *lock, int pshared) |
| Initialize a spinlock. | |
| int | pthread_spin_destroy (pthread_spinlock_t *lock) |
| Destroy a spinlock. | |
| int | pthread_spin_lock (pthread_spinlock_t *lock) |
| Acquire the spinlock, spinning until available. | |
| int | pthread_spin_trylock (pthread_spinlock_t *lock) |
| Try to acquire the spinlock without blocking. | |
| int | pthread_spin_unlock (pthread_spinlock_t *lock) |
| Release a spinlock held by the calling thread. | |
| int | pthread_barrierattr_init (pthread_barrierattr_t *attr) |
| Initialize a barrier attributes object (no settable properties). | |
| int | pthread_barrierattr_destroy (pthread_barrierattr_t *attr) |
| Destroy a barrier attributes object (no-op). | |
| int | pthread_barrier_init (pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) |
| Initialize a barrier for count participating threads. | |
| int | pthread_barrier_destroy (pthread_barrier_t *barrier) |
| Destroy a barrier, releasing the underlying STK barrier object. | |
| int | pthread_barrier_wait (pthread_barrier_t *barrier) |
| Block until count threads have called this function, then release them all together; the barrier resets for reuse. | |
| int | pthread_once (pthread_once_t *once_control, void(*init_routine)(void)) |
| Call init_routine exactly once for a given once_control, no matter how many threads call pthread_once() on it concurrently. | |
| int | pthread_key_create (pthread_key_t *key, void(*destructor)(void *)) |
| Allocate a new thread-specific data key. | |
| int | pthread_key_delete (pthread_key_t key) |
| Free a thread-specific data key. | |
| int | pthread_setspecific (pthread_key_t key, const void *value) |
| Set the calling thread's value for key. | |
| void * | pthread_getspecific (pthread_key_t key) |
| Get the calling thread's value for key. | |
A minimal, POSIX-named pthreads-style API for STK. The public interface needs only stk_c.h / stk_c_memory.h (no C++ headers), so it can be used from C. The implementation (stk_c_pthread.cpp) calls the STK C++ API directly for thread/task control, TLS, critical sections, sleep/yield/time and the synchronization primitives; the stk_*_mem_t blobs embedded in the pthread_* types are used as in-place storage for those C++ objects.
Covers thread lifecycle and attributes, mutexes, condition variables, read-write locks, spinlocks, barriers, pthread_once() and thread-specific data. This is deliberately a subset of full POSIX threads, scoped to what maps cleanly onto STK's task/synchronization model:
| POSIX area | Support |
|---|---|
| pthread_create/join/detach/exit/self/equal | Yes |
| pthread_yield (non-POSIX; POSIX uses sched_yield()) | Yes (GNU/BSD-style extension) |
| pthread_attr_t (stacksize, stack, detachstate) | Yes |
| pthread_attr_set/getprivileged_np | Yes (non-portable STK extension) |
| pthread_mutex_t (normal/default) | Yes (recursive in practice, see PTHREAD_MUTEX_NORMAL note) |
| pthread_mutex_t (recursive, errorcheck) | Yes |
| pthread_cond_t (wait/timedwait/signal/broadcast) | Yes |
| pthread_rwlock_t (rdlock/wrlock/tryrdlock/trywrlock/timed variants/unlock) | Yes |
| pthread_spin_* (init/destroy/lock/trylock/unlock) | Yes |
| pthread_barrier_t (init/destroy/wait) | Yes |
| pthread_once | Yes |
| pthread_key_t (create/delete/setspecific/getspecific, destructors) | Yes |
| stk_pthread_bind_kernel() | Yes (STK-specific bootstrap, not POSIX; required before pthread_create()) |
| Cancellation (pthread_cancel etc.) | No |
| Thread scheduling policy / priority get-set | No (pthread_t is opaque, so stk_task_set_priority() cannot be applied to it) |
STK_C_KERNEL_TYPE_CPU_X in stk_config.h, X being the core number passed to stk_kernel_create()) must include KERNEL_DYNAMIC (threads finish by returning from their entry function or calling pthread_exit(), which STK only supports for dynamic kernels) and KERNEL_SYNC (which enables the Mutex/Event/Semaphore primitives this shim is built on). The shim cannot verify this: a mismatch is a build configuration error and is not reported through an error code.STK_C_KERNEL_MAX_TASKS must be large enough to hold: the application's own pre-existing tasks + one internal reaper task (added to the kernel by stk_pthread_bind_kernel(), whether or not any thread is ever detached) + the maximum number of concurrently-alive pthreads (joined-but-not-yet-collected and detached-but-not-yet-reaped threads still count as "alive" until reclaimed).STK_C_PTHREAD_DEFAULT_STACK_WORDS) takes its stack from a static pool and uses no heap. Any other size set via pthread_attr_setstacksize() is allocated with malloc() and freed when the thread is reclaimed. A stack supplied through pthread_attr_setstack() is used as-is and is never freed by the shim. The internal reaper task uses a static stack of STK_C_PTHREAD_REAPER_STACK_WORDS words.STK_C_PTHREAD_MAX_THREADS (this file) bounds how many pthread_t's can exist concurrently; increase it via a -D define or in stk_config.h.stk_pthread_bind_kernel() once (before the first pthread_create() call) so the shim knows which kernel to add new threads to (the call also adds the internal reaper task to that kernel):pthread_self() is backed by STK's per-task TLS slot (stk_tls_get()), which this shim populates for every thread it creates via pthread_create(). A task the shim did not create - typically the application's bootstrap task added to the kernel before stk_kernel_start() - is adopted on first use: the first call to pthread_self() or pthread_setspecific() from such a task gives it a pthread_t and stores that handle in its TLS slot. Consequences:STK_C_PTHREAD_MAX_THREADS slot, so size that limit as (pthread_create()'d threads + adopted tasks);EINVAL for it);stk_tls_set() in a task that uses the pthread API (it would replace the handle);pthread_exit() from an adopted task runs its key destructors and then parks the task forever (the shim holds no kernel task object for it, so it cannot ask the kernel to remove it);pthread_getspecific() never adopts (it returns NULL for a task that has not yet stored any value), so merely reading does not consume a slot. pthread_self() returns NULL only if no slot is left to adopt into.CLOCK_REALTIME) concept - only a monotonic tick count since stk_kernel_init(). abstime is therefore a point on the timeline of stk::GetTimeNowMs() (C alias: stk_time_now_ms()): derive it by adding a duration to a value read from that function, never from a time-of-day clock:abstime is converted to a relative timeout in milliseconds (and then to kernel ticks). A deadline that is already in the past yields a zero timeout, so the call behaves like a non-blocking attempt, and very distant deadlines are clamped to INT32_MAX ms. The same interpretation applies to pthread_rwlock_timedrdlock() and pthread_rwlock_timedwrlock().
pthread_rwlock_unlock() call to release either a read or a write hold, but the underlying stk::sync::RWMutex exposes separate ReadUnlock() / Unlock() calls. This shim disambiguates by recording, inside the pthread_rwlock_t itself, whether the lock is currently held for writing; this is safe because a write hold is always exclusive (no reader can be active while it is set), so the flag unambiguously identifies which underlying call to make. As with real pthreads, calling pthread_rwlock_unlock() on a lock you do not hold is undefined behavior and is not detected here.PTHREAD_PROCESS_PRIVATE is supported for the pshared argument to pthread_spin_init(); PTHREAD_PROCESS_SHARED returns ENOTSUP (STK has no cross-process concept).stk::sync::Barrier::Wait(), pthread_barrier_wait() is ISR-unsafe - do not call it from interrupt context. It returns PTHREAD_BARRIER_SERIAL_THREAD to exactly one arbitrary calling thread per round (the one whose arrival trips the barrier) and 0 to the rest, matching POSIX.pthread_once_t lazily creates its own guard mutex (on first use; it is embedded in the pthread_once_t and never explicitly destroyed) and blocks concurrent callers on it while init_routine runs, so - unlike a naive flag check - a thread that calls pthread_once() while another thread's init_routine is still running correctly waits for it to finish rather than racing ahead. init_routine must not itself call pthread_once() on the same pthread_once_t (self-deadlock, as in real POSIX).pthread_setspecific() are stored in the thread's control block (reached through STK's per-task TLS slot). Foreign tasks are adopted on first pthread_setspecific() as described above (ENOMEM if no slot is left). Destructors (if any) run when a thread finishes (natural return or pthread_exit()), for at most PTHREAD_DESTRUCTOR_ITERATIONS passes - matching POSIX, a destructor that calls pthread_setspecific() to set a new non-NULL value for its own key causes another pass. They do not run for an adopted task that simply never exits. STK_C_PTHREAD_KEYS_MAX (this file) bounds how many keys can exist concurrently. Definition in file stk_c_pthread.h.
| #define _SYS__PTHREADTYPES_H_ |
Definition at line 15 of file stk_c_pthread.h.