![]() |
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 implemented on top of the STK C bindings (stk_c.h / stk_c_memory.h) only - no other STK headers are required. 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 | 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_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 limitation" 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 currently requested stack size in bytes (0 = default). | |
| 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 (NULL/0 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_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) |
| int | pthread_mutexattr_destroy (pthread_mutexattr_t *attr) |
| 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) |
| int | pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) |
| Initialize a mutex. | |
| int | pthread_mutex_destroy (pthread_mutex_t *mutex) |
| int | pthread_mutex_lock (pthread_mutex_t *mutex) |
| int | pthread_mutex_trylock (pthread_mutex_t *mutex) |
| int | pthread_mutex_unlock (pthread_mutex_t *mutex) |
| 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) |
| int | pthread_condattr_destroy (pthread_condattr_t *attr) |
| int | pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr) |
| int | pthread_cond_destroy (pthread_cond_t *cond) |
| 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) |
| int | pthread_cond_broadcast (pthread_cond_t *cond) |
| int | pthread_rwlockattr_init (pthread_rwlockattr_t *attr) |
| int | pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) |
| 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) |
| 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) |
| 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) |
| int | pthread_barrierattr_init (pthread_barrierattr_t *attr) |
| int | pthread_barrierattr_destroy (pthread_barrierattr_t *attr) |
| 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) |
| 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 implemented on top of the STK C bindings (stk_c.h / stk_c_memory.h) only - no other STK headers are required.
Covers thread lifecycle (create/join/detach/exit/self/equal), mutexes and condition variables. 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/yield | Yes |
| pthread_attr_t (stacksize, stack, detachstate) | Yes |
| pthread_mutex_t (normal, non-recursive) | Yes |
| pthread_mutex_t (recursive, errorcheck) | No (returns ENOTSUP) |
| 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 |
| Cancellation (pthread_cancel etc.) | No |
| Thread scheduling policy / priority get-set | No (use stk_task_set_priority() directly via stk_task_get_instance-less path if needed) |
KERNEL_DYNAMIC (threads finish by returning from their entry function or calling pthread_exit(), which STK only supports for dynamic kernels).STK_C_KERNEL_MAX_TASKS must be large enough to hold: the application's own pre-existing tasks + one internal reaper task (created lazily on first use) + 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_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:pthread_self() is backed by STK's per-task TLS slot (stk_tls_get()), which this shim populates only for threads it created via pthread_create(). Calling pthread_self() from the application's original bootstrap task (the one added to the kernel before stk_kernel_start()) returns NULL, since that task was never handed a pthread_t. If the bootstrap task needs a pthread_t identity, create it via pthread_create() instead of stk_task_create_user() + manual stk_kernel_add_task().CLOCK_REALTIME) concept - only a monotonic tick count since stk_kernel_init(). abstime is therefore interpreted as a point on the same timeline as stk_time_now_ms() (i.e. derive it by adding a duration to a value you obtained from stk_time_now_ms(), not from a real-time-of-day clock). 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_rwmutex_t exposes separate stk_rwmutex_read_unlock() / stk_rwmutex_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.stk_spinlock_t is recursive (the owning thread/ISR may re-acquire it without deadlocking). Real POSIX spinlocks are non-recursive, and a thread that relocks one it already holds has undefined behavior; this shim's spinlocks are therefore a strict superset - portable code written against real pthread_spin_* semantics will still work correctly here. Only 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_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) 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_self(), per-thread values set via pthread_setspecific() are stored in STK's per-task TLS slot and are therefore only available to threads created via pthread_create(); calling pthread_setspecific() from the application's original bootstrap task returns EINVAL, and pthread_getspecific() returns NULL for it. Destructors (if any) run once, for at most PTHREAD_DESTRUCTOR_ITERATIONS passes, when a pthread_create()'d thread finishes (natural return or pthread_exit()) - matching POSIX, a destructor that calls pthread_setspecific() to set a new non-NULL value for its own key causes another pass. STK_C_PTHREAD_KEYS_MAX (this file) bounds how many keys can exist concurrently. Definition in file stk_c_pthread.h.