pthread_attr_destroy()
Synopsis
int pthread_attr_destroy(
pthread_attr_t *attr)
Function
Clear a thread attribute object after its last use. This implementation
zeroes the object and does not free any memory.
Result
0 on success; EINVAL if attr is NULL. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. The call does not block or
affect an existing worker, whose attributes were copied at creation.
A caller-supplied stack remains caller-owned and is not released.
Reinitialize the object before using it for another creation request;
a zeroed object is not equivalent to pthread_attr_init() defaults.
Exclude concurrent access while destroying it.
pthread_attr_getdetachstate()
Synopsis
int pthread_attr_getdetachstate(
const pthread_attr_t *attr, int *detachstate)
Function
Read the detach state stored in a thread attribute object.
Result
0 on success; EINVAL if attr is NULL.
Notes
Reads the stored field; it does not inspect any running thread. Errors
are returned directly.
pthread_attr_getschedparam()
Synopsis
int pthread_attr_getschedparam(
const pthread_attr_t *attr, struct sched_param *param)
Function
Read the scheduling parameters stored in a thread attribute object.
Result
0 on success; EINVAL if attr is NULL.
Notes
This is a copy of the attribute field, not a query of the task
scheduler. A NULL output pointer is accepted.
pthread_attr_getstack()
Synopsis
int pthread_attr_getstack(
const pthread_attr_t *attr, void **stackaddr, size_t *stacksize)
Function
Read the requested stack address and size from thread attributes.
Result
0 on success; EINVAL if attr is NULL.
Notes
The values describe an attribute object, not the current stack of a
live thread. No allocation or validation occurs.
pthread_attr_getstacksize()
Synopsis
int pthread_attr_getstacksize(
const pthread_attr_t *attr, size_t *stacksize)
Function
Read the stack size stored in thread attributes.
Result
The result of pthread_attr_getstack(attr, NULL, stacksize): 0 or
EINVAL.
Notes
This function does not query a running task or determine a minimum
usable stack size.
pthread_attr_init()
Synopsis
int pthread_attr_init(
pthread_attr_t *attr)
Function
Initialize a caller-provided thread attribute object. Clear its fields,
select a joinable worker with no supplied stack, copy the current task
priority, and set the stack size to the current task's stack extent.
Result
0 on success; EINVAL if attr is NULL. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. Call in task context. No stack
or thread is allocated. The default size comes from tc_SPUpper minus
tc_SPLower; it is not a fixed PTHREAD_STACK_MIN allocation. Set an
appropriate size explicitly when the new worker needs a different one.
pthread_create() copies the object, so it need not outlive creation.
Destroy it with pthread_attr_destroy() when no longer needed.
Do not modify an object concurrently with a reader.
pthread_attr_setdetachstate()
Synopsis
int pthread_attr_setdetachstate(
pthread_attr_t *attr, int detachstate)
Function
Choose whether new threads are joinable or detached.
Result
0 on success; EINVAL for a NULL attr or any other detach state.
Notes
The selection takes effect when pthread_create() copies these
attributes. Changing an attribute object does not detach an existing
thread.
pthread_attr_setschedparam()
Synopsis
int pthread_attr_setschedparam(
pthread_attr_t *attr, const struct sched_param *param)
Function
Store scheduling parameters for a subsequently created thread.
Result
0 on success; EINVAL if attr or param is NULL.
Notes
The entire struct sched_param is copied. The setter does not validate
its priority; thread creation uses the stored priority.
Bugs
The pthread_create() path does not implement scheduling inheritance or
contention-scope controls.
pthread_attr_setstack()
Synopsis
int pthread_attr_setstack(
pthread_attr_t *attr, void *stackaddr, size_t stacksize)
Function
Store a stack buffer address and requested size for future thread
creation.
Result
0 on success; EINVAL if attr is NULL or a non-NULL stackaddr is paired
with zero size.
Notes
The function stores the two values without allocating, checking
alignment, enforcing PTHREAD_STACK_MIN, or checking actual accessible
memory. Keep a supplied buffer valid throughout the worker lifetime.
Bugs
Not all invalid stack sizes and pointers are rejected by the setter. A
successful result does not establish that subsequent thread creation
can use the buffer.
pthread_attr_setstacksize()
Synopsis
int pthread_attr_setstacksize(
pthread_attr_t *attr,
size_t stacksize)
Function
Set the stack size for subsequent worker creation and clear any
previously supplied stack address. This delegates to
pthread_attr_setstack(attr, NULL, stacksize).
Result
0 on success; EINVAL if attr is NULL. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. No memory is allocated, resized
or freed. The change affects later pthread_create() calls only. Clearing
a supplied stack pointer does not transfer or release that storage.
Exclude concurrent access to attr.
Bugs
All size values are accepted without checking PTHREAD_STACK_MIN,
alignment or whether the size can support the worker. Successful
attribute assignment does not establish that creation will succeed
or that the resulting stack is sufficient.
pthread_barrier_destroy()
Synopsis
int pthread_barrier_destroy(
pthread_barrier_t *barrier)
Function
Destroy a barrier that has no arriving or departing participants.
Result
0 if destruction proceeds; EINVAL for NULL; EBUSY if the mutex cannot
be acquired, a generation is active, or the condition destroy fails.
Notes
Attempts a nonblocking lock and checks internal generation state
before destroying the embedded condition and mutex. Do not reuse the
storage without initialization.
Bugs
A successful probe does not exclude new arrivals; external quiescence
is required. The return value from the final mutex destruction is
ignored.
pthread_barrier_init()
Synopsis
int pthread_barrier_init(
pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
Function
Initialize a reusable barrier for a fixed number of participating
threads.
Result
0 on success; EINVAL if barrier is NULL or count is zero.
Notes
Stores count and initializes an embedded condition variable and mutex.
All participants must reach the barrier before they can proceed.
Caller owns the barrier storage.
Bugs
The return values of the embedded mutex and condition initializers are
not checked. No maximum participant count or overflow guard is
enforced.
pthread_barrier_wait()
Synopsis
int pthread_barrier_wait(
pthread_barrier_t *barrier)
Function
Wait for all members of a barrier generation and release them
together.
Result
PTHREAD_BARRIER_SERIAL_THREAD for the final arrival; 0 for other
arrivals after the generation completes; EINVAL for NULL.
Notes
Uses an embedded mutex and condition variable. The last arrival
broadcasts to waiting peers. A departing generation must finish before
the next generation is admitted.
Bugs
The implementation does not propagate embedded mutex/condition
failures. If a participant exits or never arrives, other participants
may wait indefinitely.
pthread_cancel()
Synopsis
int pthread_cancel(
pthread_t thread)
Function
Mark a live worker as having a pending cancellation request and signal
it with SIGBREAKF_CTRL_C. Cancellation takes effect when the worker
processes the request with cancellation enabled. Acceptance does not
wait for the worker to finish.
Result
0 if the request was recorded. ESRCH if no allocated record is found,
the record has no parent, or cancellation is already pending.
An enabled asynchronous request for the calling worker exits through
pthread_testcancel() and does not return. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. A new worker uses enabled,
deferred cancellation. Disabled cancellation remains pending. Use
pthread_join() on a joinable worker to observe completion and obtain
PTHREAD_CANCELED; do not free worker-owned resources on request success.
Cleanup handlers run when cancellation reaches pthread_exit().
Bugs
The default build does not enable USE_ASYNC_CANCEL. Selecting
PTHREAD_CANCEL_ASYNCHRONOUS does not make a signal forcibly terminate
another worker. Deferred cancellation requires a reached cancellation
check; pthread_join() does not repeat that check while blocked.
Record access is not serialized here, and finished joinable workers
are not rejected by a finished-state check. Passing such an identifier
can signal a stale task pointer. Repeated requests return ESRCH even
while the target still exists. Do not target the initial program task:
it has no worker exit jump point.
pthread_cleanup_pop()
Synopsis
void pthread_cleanup_pop(
int execute)
Function
Remove the most recently registered cancellation cleanup handler.
Result
No return value. A missing handler is treated as an empty pop.
Notes
Removes the tail record from the current pthread cleanup list,
optionally invokes its callback with the stored argument, then frees
the record.
Bugs
No dynamic balancing or thread-identity validation is performed. A
previous failed push can leave the pop operating on another registered
handler.
pthread_cleanup_push()
Synopsis
void pthread_cleanup_push(
void (*routine)(void *), void *arg)
Function
Register a callback to run when the current pthread unwinds its
cleanup stack.
Result
No return value. On allocation failure the handler is silently not
registered.
Notes
Allocates a cleanup record and appends it to the calling thread's
list. A matching pthread_cleanup_pop() normally removes the most
recently pushed record. These are implemented as callable functions,
not lexical pairing macros.
Bugs
Allocation failure is not reported. If registration fails, a later pop
may remove an older handler. Normal return from the thread start
routine does not run the cleanup list in this implementation.
pthread_cond_broadcast()
Synopsis
int pthread_cond_broadcast(
pthread_cond_t *cond)
Function
Signal every registered waiter on cond. If no task is waiting, the
call has no retained effect. It does not change the application's
predicate or transfer ownership of the associated mutex.
Result
0 after signalling, including when no waiter is present. EINVAL if cond
is NULL. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. Call from task context; acquiring
the internal condition semaphore can block. This is not an interrupt
or asynchronous signal-handler interface. Protect the predicate with
the same mutex used by waiters and recheck it in a loop after waking.
A woken task must reacquire that mutex before returning from its wait.
Explicit initialization before sharing avoids the lazy-init race.
Bugs
Signals are task bits, not queued notifications. Repeated broadcasts
may coalesce. A waiter remains listed until it has reacquired its
mutex, and no ordering or fairness guarantee is provided.
pthread_cond_destroy()
Synopsis
int pthread_cond_destroy(
pthread_cond_t *cond)
Function
Clear a condition variable after checking that its internal semaphore
is available and its waiter list is empty.
Result
0 on success, including an uninitialized static condition (left as is).
EINVAL if cond is NULL. EBUSY if its semaphore cannot be acquired
immediately or its waiter list is nonempty. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. The probe does not wait. No
caller storage is freed. Reinitialize before reuse. A waiter remains
on the internal list until it has reacquired its application mutex,
so a signalled waiter can still make this call report EBUSY.
Bugs
The implementation releases its semaphore before zeroing the object.
The empty-list probe cannot make concurrent destruction safe. Establish
that all potential users have finished outside this call.
pthread_cond_init()
Synopsis
int pthread_cond_init(
pthread_cond_t *cond,
const pthread_condattr_t *attr)
Function
Initialize a condition variable with an empty waiter list. Select the
absolute-deadline clock from attr, or CLOCK_REALTIME by default.
Result
0 on success. EINVAL if cond is NULL or attr specifies an unsupported
clock on AROS. Validation failure leaves cond unchanged.
Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. No waiter or timer is allocated.
The caller retains the storage until no task can wait or signal and
pthread_cond_destroy() has completed. Attributes are copied and need
not outlive the condition. Initialize before publishing to other tasks.
Use pthread_condattr_init(), not manual zeroing: clock identifier 0
denotes CLOCK_MONOTONIC on AROS, not the realtime default.
Bugs
Process-sharing attributes are ignored. Reinitialization of an active
condition is not detected. Static lazy initialization elsewhere in
this implementation is not serialized against simultaneous first use.
pthread_cond_signal()
Synopsis
int pthread_cond_signal(
pthread_cond_t *cond)
Function
Signal the first registered waiter on cond. If no task is waiting, the
call has no retained effect. It does not change the application's
predicate or transfer ownership of the associated mutex.
Result
0 after signalling, including when no waiter is present. EINVAL if cond
is NULL. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. Call from task context; acquiring
the internal condition semaphore can block. This is not an interrupt
or asynchronous signal-handler interface. Protect the predicate with
the same mutex used by waiters and recheck it in a loop after waking.
A woken task must reacquire that mutex before returning from its wait.
Explicit initialization before sharing avoids the lazy-init race.
Bugs
Signalling does not remove or reserve the selected waiter. Repeated
calls before that waiter removes itself can target it again, coalescing
signals and leaving other waiters asleep. Do not assume successive
calls wake distinct waiters.
pthread_cond_timedwait()
Synopsis
int pthread_cond_timedwait(
pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *abstime)
Function
Wait on cond as pthread_cond_wait() does, with an absolute deadline
measured against the clock selected at condition initialization.
Reacquire mutex before returning from the wait, including on timeout.
Test the protected predicate after every return; a zero result does
not certify that a condition signal or predicate change occurred.
Result
0 after a nontimeout wake; ETIMEDOUT if the timer signal was observed.
EINVAL for NULL cond/mutex, an invalid nanosecond field, failure to open
timer.device, or failure to read the selected clock. Setup errors occur
before releasing mutex. Errors are returned directly. Cancellation can
exit the worker after the mutex has been reacquired.
Notes
Include <pthread.h>; link with pthread. Call from the initial program
task or a registered worker. Keep both objects valid through all waits.
The wait creates a timer request and closes it before returning. Reacquiring
mutex may block past the deadline; this is not a bound on return time.
Install cancellation cleanup that releases mutex.
The deadline is converted once to a relative timer interval. Later
changes to the realtime clock do not adjust it. Nonpositive intervals
are changed to 1 ms. Positive fractions are truncated to microseconds,
with a minimum timer request of 1 microsecond.
Bugs
If timeout, condition and cancellation signals arrive together, timeout
takes precedence and cancellation is not tested on that return.
Mutex lock/unlock failures are ignored. Multiple recursive acquisitions
do not fully release mutex. Signal-allocation failure uses CTRL_D for
the timer and CTRL_E for the condition; those bits are not cleared by
the fallback setup and can collide with application signal use.
Explicit initialization before sharing avoids unsynchronized lazy init.
pthread_cond_timedwait_relative_np()
Synopsis
int pthread_cond_timedwait_relative_np(
pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *reltime)
Function
Wait on a condition variable using a relative time interval.
Result
Returns the status of _pthread_cond_timedwait(), including timeout and
argument errors established by that implementation.
Notes
Calls the existing condition-wait helper with relative mode enabled.
The caller must hold the mutex and recheck its shared predicate after
waking; cancellation can exit the worker.
pthread_cond_wait()
Synopsis
int pthread_cond_wait(
pthread_cond_t *cond,
pthread_mutex_t *mutex)
Function
Register the caller as a waiter, release one acquisition of mutex,
wait for a condition or CTRL_C signal, and reacquire mutex before
removing the waiter. A return does not establish that the application's
predicate is true; always test it again while holding mutex.
Result
0 after waking and reacquiring a valid mutex. EINVAL if cond or mutex
is NULL. Errors are returned directly. Pending enabled cancellation
observed after a CTRL_C wake exits the worker instead of returning.
Example
// mutex is locked; ready is protected by mutex.
int error = 0;
while (!ready) {
error = pthread_cond_wait(&cond, &mutex);
if (error != 0)
break;
}
// Examine ready or handle the error before using protected data.
Notes
Include <pthread.h>; link with pthread. Call from the initial program
task or a registered worker. There is no timeout. The mutex is reacquired
before cancellation cleanup; arrange for a cleanup handler to release it.
Other CTRL_C wakes can produce a zero result without a condition signal.
This implementation does not return EINTR for those wakes.
Initialize the objects before concurrent use.
Bugs
Mutex ownership and matching are not validated, and lock/unlock errors
are ignored. Waiting while holding multiple recursive acquisitions
does not fully release the mutex and can deadlock other participants.
Signal allocation failure uses the task's CTRL_E bit; the fallback
does not clear an already pending bit and can consume unrelated use
of that signal. Unregistered tasks cannot safely process cancellation.
pthread_condattr_destroy()
Synopsis
int pthread_condattr_destroy(
pthread_condattr_t *attr)
Function
Clear a condition-variable attribute object after use.
Result
0 on success; EINVAL if attr is NULL.
Notes
Zeros the attribute storage. It does not deallocate the caller-owned
object or affect condition variables already initialized from it.
pthread_condattr_getclock()
Synopsis
int pthread_condattr_getclock(
const pthread_condattr_t *attr, clockid_t *clock_id)
Function
Read the deadline clock selected in condition attributes.
Result
0 on success; EINVAL if either pointer is NULL.
Notes
Reports the stored field. It does not query timer.device or the clock
currently used by a running wait.
pthread_condattr_init()
Synopsis
int pthread_condattr_init(
pthread_condattr_t *attr)
Function
Initialize condition-variable attributes with the default realtime
clock.
Result
0 on success; EINVAL if attr is NULL.
Notes
Clears the object and sets cond_clock to CLOCK_REALTIME when the
symbol is available. Initialize attributes before passing them to
pthread_cond_init().
pthread_condattr_setclock()
Synopsis
int pthread_condattr_setclock(
pthread_condattr_t *attr, clockid_t clock_id)
Function
Select the clock used to interpret an absolute condition-wait
deadline.
Result
0 on success; EINVAL if attr is NULL or clock_id is unsupported.
Notes
Stores the chosen clock. pthread_cond_init() copies it into the
condition variable; changing attributes later does not change existing
conditions.
pthread_create()
Synopsis
int pthread_create(
pthread_t *thread,
const pthread_attr_t *attr,
void *(*start)(void *),
void *arg)
Function
Start a worker running start(arg). The worker may execute before this
call returns. A normal return from start stores its pointer result for
pthread_join(); pthread_exit() also runs registered cleanup handlers.
The attributes are copied. With NULL attributes, the worker is joinable,
uses the creator's priority and stack extent, and starts with deferred
cancellation enabled. A joinable worker retains its slot until joined;
a detached worker releases its slot when it finishes.
Result
0 on success; *thread receives the identifier. EINVAL if thread or start
is NULL. EAGAIN if no slot is available, a thread record cannot be
allocated, or the process-creation result is observed as NULL.
On error, *thread is unchanged. Errors are returned directly.
Notes
Include <pthread.h> and link with the pthread link library. Call from
task context with its runtime initialized. Creation can wait for the
internal thread semaphore and system allocation; it has no timeout.
The worker runs in a DOS process and applies attr's scheduling priority.
Scheduling inheritance and contention-scope fields are not implemented
by this creation path. The start routine must return a pointer whose
lifetime permits its eventual use by the joiner, not worker-stack data.
Worker exit runs non-NULL thread-specific destructors before releasing
its C runtime. Destructors are skipped during program-wide teardown.
Join or detach every successfully created joinable worker. Identifiers
are reused; they are not permanent handles.
Bugs
An immediately finishing detached worker can clear its record before
the creator tests inf->task after releasing the thread semaphore. Thus
an EAGAIN result does not establish that the entry point never ran.
Returning from start bypasses the cleanup-handler list in this
implementation. Use balanced cleanup operations or pthread_exit()
when those handlers must run.
pthread_detach()
Synopsis
int pthread_detach(
pthread_t thread)
Function
Detach a thread so that its identifier slot can be released without
joining.
Result
0 on success; ESRCH if the slot or its task is unavailable; EINVAL if
the thread is already detached.
Notes
A running detached worker releases its slot on exit. An
already-finished joinable worker has its slot cleared immediately. No
implicit pthread_join() is performed.
Bugs
Identifier records may be reused, and the initial program task is not
excluded by an explicit worker-only check. Synchronize lifecycle
operations and avoid stale identifiers.
pthread_equal()
Synopsis
int pthread_equal(
pthread_t t1,
pthread_t t2)
Function
Compare two thread identifier values. This implementation compares the
numeric identifiers without looking up either thread.
Result
Nonzero (1) if the values are equal; 0 otherwise. No errors are reported.
Notes
Include <pthread.h>; link with pthread. This call neither blocks nor
changes thread state. Equality does not prove that a thread exists or
is still running. An identifier may be reused after its slot is released,
so equal values obtained at different times need not name the same
worker lifetime.
pthread_exit()
Synopsis
void pthread_exit(
void *value_ptr)
Function
Finish the calling worker with value_ptr as its result. Run registered
cleanup handlers in reverse registration order, then return control to
the worker starter without returning to this caller. The starter runs
thread-specific destructors and C runtime leave hooks before marking
the worker finished or releasing its detached record.
Result
Does not return for a worker created by pthread_create().
Notes
Include <pthread.h>; link with pthread. Call only from a registered
worker after its entry point has started. Cleanup handlers run in that
worker's context and must return normally. Their execution can block.
Held mutexes and other application resources are not released
automatically; arrange explicit cleanup before exiting.
Non-NULL thread-specific values with destructors are cleared before
invocation. Reinstalled values can cause further passes, up to
PTHREAD_DESTRUCTOR_ITERATIONS. Program-wide teardown skips these
destructors. A joinable completion record remains until joined.
Bugs
The initial program task has no initialized exit jump point. Calling
pthread_exit() there, or from an unregistered task, is unsupported.
TLS destructors run while the runtime holds its shared TLS semaphore;
creating or deleting keys from a destructor can contend for an
exclusive acquisition and must not be relied on.
pthread_getattr_np()
Synopsis
int pthread_getattr_np(
pthread_t thread, pthread_attr_t *attr)
Function
Snapshot the attributes of a registered pthread and its current stack
extent.
Result
0 on success; EINVAL if attr is NULL; ESRCH if thread lookup fails.
Notes
Copies the attributes captured at creation, then replaces stackaddr
with tc_SPLower and stacksize with tc_SPUpper - tc_SPLower from the
current Exec task. The result is a snapshot, not a live object.
Bugs
No live-task guard or synchronization protects the task stack fields.
A stale identifier can dereference an invalid task. No atomic snapshot
against an in-progress stack swap is guaranteed.
pthread_getname_np()
Synopsis
int pthread_getname_np(
pthread_t thread, char *name, size_t len)
Function
Copy the current Exec task name for a pthread into a caller-owned
buffer.
Result
0 on success; ERANGE if name is NULL, len is zero, the identifier
cannot be located, or the destination is too small.
Notes
Copies the NUL-terminated task name after comparing strlen(name)+1
against len. No destination bytes are written when that size check
fails.
Bugs
The task pointer and source string are not protected against
concurrent task completion or renaming.
pthread_getschedparam()
Synopsis
int pthread_getschedparam(
pthread_t thread, int *policy, struct sched_param *param)
Function
Report the current Exec priority for a pthread and a fixed scheduling
policy.
Result
0 on success; EINVAL if either output is NULL; ESRCH if thread lookup
fails.
Notes
Reads tc_Node.ln_Pri directly from the associated task. Other fields
of *param are not initialized by this function.
Bugs
The task pointer is not checked for NULL before dereference. A
finished or invalidated slot can therefore cause invalid memory
access.
pthread_getspecific()
Synopsis
void *pthread_getspecific(
pthread_key_t key)
Function
Read the calling thread's pointer slot for key. The pointer is returned
unchanged; the call neither copies nor frees the pointed-to data.
Result
The stored pointer, or NULL if the slot is NULL or key is outside
0..PTHREAD_KEYS_MAX-1. There is no separate error result.
Notes
Include <pthread.h>; link with pthread. This is a nonblocking slot
read. A new worker's slots start as NULL. A task that is not a pthread
(another program calling into a shared library, a raw subtask) has
slots of its own, and its destructors never run. Values belong to the
application and remain valid only for the lifetime established by
that application.
Bugs
The call does not check whether an in-range key is allocated. Deleting
or recreating a key does not clear old slot contents, so it can return
a stale pointer.
pthread_join()
Synopsis
int pthread_join(
pthread_t thread,
void **value_ptr)
Function
Wait for a joinable worker to finish, optionally copy its result pointer,
and release its thread record for reuse. A worker that has already
finished is collected without waiting for another completion signal.
Result
0 after collection. ESRCH if the record is absent or no longer active.
EINVAL if it is detached, or changes identity/state before collection.
On failure, value_ptr is not written. Errors are returned directly.
Pending enabled cancellation at the entry check exits the caller.
Notes
Include <pthread.h>; link with pthread. Call from the initial program
task or a registered worker, in task context. The wait has no timeout.
The result is copied, not freed; arranging its lifetime and disposal
remains the application's responsibility. Successful collection ends
the identifier's lifetime. Worker destructors and runtime leave hooks
precede the completion indication.
Bugs
Self-join is not detected and can block indefinitely. Multiple joiners
overwrite the single waiter field and can strand earlier callers.
Cancellation is checked only before entering the wait loop. The loop
waits for SIGBREAKF_CTRL_F, not the CTRL_C cancellation signal, and does
not recheck cancellation after waking. This call cannot be relied on
as an interruptible wait. It also consumes that task signal.
pthread_key_create()
Synopsis
int pthread_key_create(
pthread_key_t *key,
void (*destructor)(void *))
Function
Reserve the lowest free thread-specific key and associate an optional
destructor with it. Each registered thread has a separate pointer slot
for the key. Allocation is limited to PTHREAD_KEYS_MAX (64) keys shared
by this pthread runtime.
Result
0 on success, with *key set. EINVAL if key is NULL; EAGAIN if every key
is in use. The output is unchanged on failure. Errors are returned
directly.
Notes
Include <pthread.h>; link with pthread. Allocation can wait for the TLS
semaphore. Creating a key does not allocate or take ownership of values.
Set each thread's value with pthread_setspecific(). The application
must eventually delete the key after its users have finished.
At normal worker exit, a non-NULL value is cleared before its destructor
is called in the exiting worker. A destructor may install another value;
at most PTHREAD_DESTRUCTOR_ITERATIONS passes are made. Values without a
destructor are not freed. Program-wide teardown skips destructors.
Bugs
Reusing a deleted key does not clear old per-thread values. A thread
can read a stale pointer, and the new destructor can receive it. Avoid
reuse while any surviving thread may retain a value for that slot.
Destructors execute under the shared TLS semaphore. Key creation and
deletion require exclusive acquisition; do not rely on those operations
from a destructor. Initial-task exit does not use the worker destructor
path.
pthread_key_delete()
Synopsis
int pthread_key_delete(
pthread_key_t key)
Function
Release a thread-specific storage key for future reuse.
Result
0 if a used key is marked free; EINVAL if the key is out of range or
already unused.
Notes
The key table is protected by its internal semaphore. Deletion clears
the registered destructor but does not invoke it or free values stored
by individual threads.
pthread_kill()
Synopsis
int pthread_kill(
pthread_t thread, int sig)
Function
Provide the pthread_kill entry point without signal delivery support.
Result
Always returns EINVAL. No signal is delivered.
Notes
The present implementation contains only a diagnostic trace and the
EINVAL return. Do not use it to probe thread existence or deliver
POSIX signals.
Bugs
Signal delivery is not implemented for this entry point.
pthread_mutex_destroy()
Synopsis
int pthread_mutex_destroy(
pthread_mutex_t *mutex)
Function
Clear an unused mutex after checking that its semaphore can be acquired
and no condition wait is recorded. No caller-owned storage is freed.
Result
0 on success, including an uninitialized static semaphore (left as is).
EINVAL if mutex is NULL. EBUSY if AttemptSemaphore() fails or the
condition-wait count is nonzero. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. The ownership probe does not
wait. An initialized mutex is zeroed after the probe is released.
Reinitialize before reuse. EBUSY is a diagnostic, not a substitute for
establishing that all potential users have finished.
Bugs
Exec permits recursive acquisition by the owner, so the probe does not
reject a mutex still held by the caller. It can report success and clear
that live lock. Concurrent acquisition after the probe is also not
excluded by the implementation. Destroy only after external quiescence.
pthread_mutex_init()
Synopsis
int pthread_mutex_init(
pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr)
Function
Initialize a mutex's embedded Exec semaphore, copy its kind from attr
(or use PTHREAD_MUTEX_DEFAULT), and clear its condition-wait count.
Result
0 on success; EINVAL if mutex is NULL. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. The caller owns the storage and
must retain it until the unlocked, unused mutex has been destroyed.
No heap storage is allocated. Initialize before publishing the mutex
to other tasks. Attributes are copied and may then be destroyed.
Reinitializing a live mutex is invalid; no busy check is performed.
Bugs
The supplied kind is not validated here. Process-sharing attributes are
ignored. Lazy initialization of static mutexes is not serialized, so
explicit initialization before concurrent use avoids that race.
pthread_mutex_lock()
Synopsis
int pthread_mutex_lock(
pthread_mutex_t *mutex)
Function
Acquire a mutex, waiting for its current owner to release it if needed.
A recursive mutex increments its nesting count when acquired by its
owner. Initialize a static mutex lazily if its semaphore is uninitialized.
Result
0 with the mutex acquired. EINVAL if mutex is NULL. EDEADLK if the
calling task already owns an ERRORCHECK mutex. Errors are returned
directly; errno is not the result channel.
Notes
Include <pthread.h>; link with pthread. Call from task context where
waiting is permitted. There is no timeout or cancellation check.
Pair every successful acquisition with pthread_mutex_unlock().
Explicitly initialize before concurrent use; the lazy path is not
protected against simultaneous first use.
Bugs
NORMAL uses the recursive Exec semaphore path without rejecting an
owner reacquisition. It therefore permits recursion here, although
pthread_mutex_trylock() rejects the same case with EBUSY. Use the
RECURSIVE kind when nested ownership is required.
pthread_mutex_timedlock()
Synopsis
int pthread_mutex_timedlock(
pthread_mutex_t *mutex, const struct timespec *abstime)
Function
Try to acquire an exclusive mutex until an absolute deadline.
Result
0 when the timed helper reports success; EINVAL for NULL mutex,
invalid nanoseconds, or timer-device failure; EDEADLK for detected
nonrecursive self-lock; ETIMEDOUT if the deadline has passed. Other
try-lock errors propagate.
Notes
First attempts immediate acquisition. If busy, opens timer.device,
converts the absolute timestamp against gettimeofday(), and waits for
a semaphore acquisition or timer reply. Errors are returned directly.
Bugs
A NULL deadline is treated as an unbounded lock rather than rejected.
An immediately successful pthread_mutex_trylock() is followed by
another timed semaphore acquisition instead of an immediate return.
This can increase the Exec semaphore nest count twice, so one
pthread_mutex_unlock() may not fully release the mutex. No
independently selected clock is supported.
pthread_mutex_trylock()
Synopsis
int pthread_mutex_trylock(
pthread_mutex_t *mutex)
Function
Attempt to acquire a mutex without waiting for another owner. A
recursive mutex may be reacquired by its owner. Initialize a static
mutex lazily if its semaphore is uninitialized.
Result
0 with one acquisition held. EBUSY if the semaphore cannot be acquired,
or if the caller owns a nonrecursive mutex. EINVAL if mutex is NULL.
Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. Call from task context. This
function does not enqueue a wait or check cancellation. A successful
call must be paired with pthread_mutex_unlock(); failure grants no
ownership. Explicit initialization before sharing avoids the
unsynchronized lazy-initialization path.
Bugs
Owner reacquisition of an ERRORCHECK mutex returns EBUSY here, whereas
pthread_mutex_lock() returns EDEADLK. Owner reacquisition of NORMAL is
rejected here but allowed by the blocking lock implementation.
pthread_mutex_unlock()
Synopsis
int pthread_mutex_unlock(
pthread_mutex_t *mutex)
Function
Release one acquisition of a mutex owned by the calling task. A recursive
mutex remains owned until every nested acquisition has been released.
Result
0 after ReleaseSemaphore(). EINVAL if mutex is NULL. EPERM if a
non-NORMAL mutex is not owned by the caller. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. Use from task context. The call
does not wait for ownership or check cancellation. Releasing the last
acquisition allows another waiting task to proceed. It does not free
the mutex storage.
Bugs
NORMAL performs no ownership check before ReleaseSemaphore(). Passing
an unowned or already unlocked mutex is invalid and may corrupt its
state. A successful return is not independent proof of prior ownership.
An uninitialized semaphore also takes a lazy-initialization path; that
path does not make unlocking without an acquisition valid.
pthread_mutexattr_destroy()
Synopsis
int pthread_mutexattr_destroy(
pthread_mutexattr_t *attr)
Function
Clear a mutex attribute object after its last use.
Result
0 on success; EINVAL if attr is NULL. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. The call zeroes the object; it
allocates and releases no resources and does not block. Existing
mutexes retain their copied kind. Exclude concurrent access and call
pthread_mutexattr_init() before using the object again.
pthread_mutexattr_gettype()
Synopsis
int pthread_mutexattr_gettype(
pthread_mutexattr_t *attr, int *kind)
Function
Read the mutex type stored in a mutex attribute object.
Result
0 on success; EINVAL if attr is NULL.
Notes
A NULL kind pointer is accepted. The function does not validate the
current stored value.
pthread_mutexattr_init()
Synopsis
int pthread_mutexattr_init(
pthread_mutexattr_t *attr)
Function
Set a mutex attribute object's kind to PTHREAD_MUTEX_DEFAULT, which is
PTHREAD_MUTEX_NORMAL in this implementation.
Result
0 on success; EINVAL if attr is NULL. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. No mutex or other resource is
allocated, and the call does not block. pthread_mutex_init() copies the
kind; the attribute object need not outlive the initialized mutex.
Exclude concurrent access to attr.
Bugs
Only kind is initialized. The process-sharing field is left untouched,
and pthread_mutex_init() ignores that field. This call does not provide
process-shared synchronization.
pthread_mutexattr_settype()
Synopsis
int pthread_mutexattr_settype(
pthread_mutexattr_t *attr,
int kind)
Function
Set the kind to be copied by subsequent pthread_mutex_init() calls.
Result
0 on success. EINVAL if attr is NULL or kind is outside the supported
range; the object is unchanged on failure. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. This changes no existing mutex,
allocates no resources and does not block. Exclude concurrent access
to the attribute object. Recursive locks require a matching unlock for
each acquisition. ERRORCHECK diagnoses a blocking lock by the owner
with EDEADLK and an unlock by a non-owner with EPERM.
Bugs
NORMAL does not implement a strict nonrecursive lock: pthread_mutex_lock()
permits repeated acquisition by its owner, while pthread_mutex_trylock()
returns EBUSY for that case. Do not depend on owner recursion for NORMAL.
pthread_once()
Synopsis
int pthread_once(
pthread_once_t *once_control, void (*init_routine)(void))
Function
Execute an initialization routine at most once per correctly
initialized control object.
Result
0 on the implemented paths; EINVAL if either pointer is NULL.
Notes
Competing callers synchronize through the control object spinlock. The
initializer must be valid for the lifetime of concurrent callers.
Bugs
A zero-initialized control object is not equivalent to
PTHREAD_ONCE_INIT: the initial compare-and-swap path can skip
initialization. Cancellation during the callback also has nontrivial
state and cleanup implications; do not assume a POSIX retry guarantee
without testing. On __mc68000__, its spin-lock helper also uses the
problematic test-and-set replacement.
pthread_rwlock_destroy()
Synopsis
int pthread_rwlock_destroy(
pthread_rwlock_t *lock)
Function
Clear an unused reader-writer lock after a nonblocking semaphore
probe.
Result
0 if the semaphore is uninitialized or the probe succeeds; EINVAL if
lock is NULL; EBUSY if the exclusive probe fails.
Notes
If the semaphore is initialized, attempts exclusive acquisition,
releases it, and zeros the lock storage.
Bugs
The probe is not a synchronization barrier against subsequent
acquisitions. A lock held by the calling owner may pass Exec recursive
acquisition checks. External quiescence is required.
pthread_rwlock_init()
Synopsis
int pthread_rwlock_init(
pthread_rwlock_t *lock, const pthread_rwlockattr_t *attr)
Function
Initialize the Exec shared/exclusive semaphore used by a reader-writer
lock.
Result
0 on success; EINVAL if lock is NULL.
Notes
Initializes the embedded Exec SignalSemaphore. The caller owns the
lock storage; destroy only when no holders or waiters remain.
Bugs
No process-sharing attributes, fairness policy, or other optional lock
attributes are consumed.
pthread_rwlock_rdlock()
Synopsis
int pthread_rwlock_rdlock(
pthread_rwlock_t *lock)
Function
Acquire a shared reader lock, waiting if exclusive ownership prevents
it.
Result
0 after acquisition; EINVAL if lock is NULL. Cancellation at the
initial check may terminate the calling thread.
Notes
Calls pthread_testcancel(), lazily initializes static locks, then
blocks in ObtainSemaphoreShared(). Release with
pthread_rwlock_unlock().
Bugs
No explicit deadlock test is active for a caller already holding a
write lock; the source contains a disabled ownership check. Concurrent
lazy initialization is unguarded.
pthread_rwlock_timedrdlock()
Synopsis
int pthread_rwlock_timedrdlock(
pthread_rwlock_t *lock, const struct timespec *abstime)
Function
Acquire a shared reader lock subject to an absolute deadline.
Result
0 on success; EINVAL for NULL lock, malformed nanoseconds, or
timer-device failure; ETIMEDOUT after the deadline; other try-lock
errors propagate.
Notes
Checks cancellation, tries immediate shared acquisition, then waits
using _obtain_sema_timed() and the Exec shared-semaphore mode.
Bugs
NULL abstime is accepted as an unbounded operation. The timed helper
uses gettimeofday(), not a condition-variable clock attribute.
Concurrent lazy initialization is unguarded.
pthread_rwlock_timedwrlock()
Synopsis
int pthread_rwlock_timedwrlock(
pthread_rwlock_t *lock, const struct timespec *abstime)
Function
Attempt exclusive writer acquisition until an absolute deadline.
Result
0 on success; EINVAL for NULL lock, invalid nanoseconds, or timer
setup failure; ETIMEDOUT on expiry; immediate try-lock errors
propagate.
Notes
Checks cancellation, first attempts a nonblocking exclusive lock, and
waits through the timer/semaphore helper only on EBUSY.
Bugs
A NULL deadline is not rejected. Unlike pthread_rwlock_wrlock(), this
path does not explicitly detect a self-owned write lock before
entering timed acquisition.
pthread_rwlock_tryrdlock()
Synopsis
int pthread_rwlock_tryrdlock(
pthread_rwlock_t *lock)
Function
Attempt a shared reader lock without waiting.
Result
0 on acquisition; EINVAL if lock is NULL; EBUSY if the shared attempt
fails.
Notes
Lazily initializes a statically initialized lock and calls
AttemptSemaphoreShared(). Unlock once for each successful acquisition.
Bugs
Lazy initialization is not serialized; initialize explicitly before
concurrent first use. Deadlock checks for a caller already holding the
write lock are absent.
pthread_rwlock_trywrlock()
Synopsis
int pthread_rwlock_trywrlock(
pthread_rwlock_t *lock)
Function
Attempt exclusive writer acquisition without blocking.
Result
0 on acquisition; EINVAL for NULL; EBUSY if exclusive acquisition
fails.
Notes
Initializes a static semaphore lazily, then uses Exec
AttemptSemaphore().
Bugs
Exec semaphore ownership can make recursive acquisition succeed; this
wrapper does not explicitly reject a writer already owning the lock.
Concurrent lazy initialization is also unguarded.
pthread_rwlock_unlock()
Synopsis
int pthread_rwlock_unlock(
pthread_rwlock_t *lock)
Function
Release a reader or writer acquisition of a reader-writer lock.
Result
0 if ReleaseSemaphore() is called; EINVAL for NULL; EPERM if the
semaphore nest count is below one.
Notes
Lazily initializes an invalid static semaphore and uses Exec
ReleaseSemaphore() to release one acquisition.
Bugs
The check examines only ss_NestCount, not a reader ownership list. It
cannot reliably reject a thread that does not own a shared
acquisition; unlocking from the wrong thread has undefined effects.
pthread_rwlock_wrlock()
Synopsis
int pthread_rwlock_wrlock(
pthread_rwlock_t *lock)
Function
Acquire an exclusive writer lock on a reader-writer semaphore.
Result
0 after exclusive acquisition; EINVAL if lock is NULL; EDEADLK if the
calling task already owns the semaphore.
Notes
Checks cancellation, initializes static locks lazily, and waits in
ObtainSemaphore(). Release with pthread_rwlock_unlock().
Bugs
No fairness, writer-preference, or lock-upgrade guarantee is
established. Concurrent lazy initialization is unguarded.
pthread_rwlockattr_destroy()
Synopsis
int pthread_rwlockattr_destroy(
pthread_rwlockattr_t *attr)
Function
Clear an unused reader-writer lock attribute object.
Result
0 on success; EINVAL if attr is NULL.
Notes
Zeros the caller-owned structure; existing locks are unaffected.
pthread_rwlockattr_init()
Synopsis
int pthread_rwlockattr_init(
pthread_rwlockattr_t *attr)
Function
Initialize attributes for a reader-writer lock.
Result
0 on success; EINVAL if attr is NULL.
Notes
Clears the attribute structure. No process-sharing policy is applied
by pthread_rwlock_init().
pthread_self()
Synopsis
pthread_t pthread_self(
void)
Function
Return the identifier associated with the calling task in this pthread
runtime's thread table.
Result
The registered worker identifier, or 0 for the initial program task.
This implementation also returns 0 for an unregistered task; there is
no separate failure result.
Notes
Include <pthread.h>; link with pthread. The call does not wait for a
worker to finish and transfers no ownership. Compare identifiers with
pthread_equal(). A worker identifier is valid only for that worker's
lifetime, including any joinable completion record.
Bugs
Tasks created outside this pthread runtime are not registered by this
call. Their fallback value aliases the initial task, so it must not be
used to access cancellation state or thread-specific storage from an
arbitrary Exec task.
pthread_setcancelstate()
Synopsis
int pthread_setcancelstate(
int state,
int *oldstate)
Function
Set the calling thread's cancellation state, optionally saving the
previous value. A newly created worker starts with PTHREAD_CANCEL_ENABLE.
Result
0 on success. EINVAL for any other state; neither the setting nor the
optional output is changed on that error. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. The call updates only the current
thread record and does not wait. It neither clears a pending request
nor tests it. Arrange cleanup before enabling cancellation and use
pthread_testcancel() when an immediate deferred check is required.
Bugs
Re-enabling cancellation does not itself act on a pending request.
Only registered workers have the exit context needed to process it;
an unregistered task aliases the initial task's state.
pthread_setcanceltype()
Synopsis
int pthread_setcanceltype(
int type,
int *oldtype)
Function
Set the calling thread's cancellation type, optionally saving the
previous value. A newly created worker starts with PTHREAD_CANCEL_DEFERRED.
Result
0 on success. EINVAL for any other type; neither the setting nor the
optional output is changed on that error. Errors are returned directly.
Notes
Include <pthread.h>; link with pthread. The call updates only the current
thread record and does not wait. It neither clears a pending request
nor tests it. Arrange cleanup before enabling cancellation and use
pthread_testcancel() when an immediate deferred check is required.
Bugs
The default build does not enable the exception handler needed for
remote asynchronous cancellation. Accepting the asynchronous constant
does not establish that capability. Switching types does not process
an already pending request. Use only from a registered worker; an
unregistered task aliases the initial task's state.
pthread_setname_np()
Synopsis
int pthread_setname_np(
pthread_t thread, const char *name)
Function
Replace the Exec task name associated with a pthread identifier.
Result
0 on success; ERANGE if name is NULL, the identifier cannot be
located, or the replacement exceeds the available name space.
Notes
For a worker, the name must fit NAMELEN including its terminator. For
the initial task, the destination capacity is taken from the length of
its existing name plus one.
Bugs
Writes into the existing Exec task name storage rather than allocating
a new buffer. No thread-lifetime or concurrent name-access
synchronization is provided.
pthread_setschedparam()
Synopsis
int pthread_setschedparam(
pthread_t thread, int policy, const struct sched_param *param)
Function
Apply a scheduling priority to the Exec task named by a pthread
identifier.
Result
0 after calling SetTaskPri(); EINVAL if param is NULL; ESRCH if thread
lookup fails.
Notes
Only param->sched_priority is passed to Exec. The function does not
validate policy or the requested priority.
Bugs
A record may exist without a live task. No NULL task check protects
the SetTaskPri() call.
pthread_setschedprio()
Synopsis
int pthread_setschedprio(
pthread_t thread, int prio)
Function
Set the Exec task priority associated with a pthread identifier.
Result
0 when SetTaskPri() is called; EINVAL if the range comparison rejects
prio; ESRCH if the identifier is outside the allocated record range.
Notes
The implementation evaluates the value against
sched_get_priority_max/min(SCHED_NORMAL), then calls SetTaskPri(). It
does not negotiate a distinct POSIX scheduling class.
Bugs
The comparison uses prio < max or prio > min, so actual accepted
values depend on the ordering returned by those helpers. A record
within range is not checked for a live task pointer.
pthread_setspecific()
Synopsis
int pthread_setspecific(
pthread_key_t key,
const void *value)
Function
Store value in the calling thread's slot for an allocated key. Replacing
a value does not call its destructor or free the previous value.
Result
0 after storing the pointer. EINVAL if key is out of range or not
allocated when checked, ENOMEM if a task that is not a pthread could
not get slots; the slot is unchanged on failure. Errors are returned
directly.
Notes
Include <pthread.h>; link with pthread. The allocation check can wait
for the shared TLS semaphore. A task that is not a pthread (another
program calling into a shared library, a raw subtask) gets slots of
its own on its first store, and its destructors never run. No data
storage is allocated or copied. At worker
exit, a non-NULL value with an associated destructor is cleared and
passed to that destructor, subject to the rules of pthread_key_create().
Clear or dispose of a replaced value explicitly when necessary.
Bugs
The TLS semaphore is released before the slot is written; concurrent
key deletion/reuse is not excluded. Recreated keys retain stale values
in surviving threads. Program-wide teardown does not guarantee
execution of worker TLS destructors.
pthread_sigmask()
Synopsis
int pthread_sigmask(
int how,
const sigset_t *set,
sigset_t *oldset)
Function
Reject a request to inspect or modify the calling thread's signal
mask because this operation is not implemented.
Result
Always returns -1 and sets errno to ENOSYS.
Notes
The thread's signal mask remains unchanged.
pthread_spin_destroy()
Synopsis
int pthread_spin_destroy(
pthread_spinlock_t *lock)
Function
Finish using a spinlock after all users have stopped accessing it.
Result
Always returns 0, including for a NULL pointer.
Notes
The implementation does not read or modify the lock word and allocates
no memory to release.
Bugs
No busy, validity, or NULL-pointer check is performed. A successful
result does not prove the lock was idle.
pthread_spin_init()
Synopsis
int pthread_spin_init(
pthread_spinlock_t *lock, int pshared)
Function
Initialize a spinlock in its unlocked state.
Result
0 on success; EINVAL if lock is NULL.
Notes
Stores zero in the lock word. Storage is caller-owned and must remain
valid while any thread uses it.
Bugs
No interprocess sharing policy is enforced; reinitializing a held or
contended lock is not detected.
pthread_spin_lock()
Synopsis
int pthread_spin_lock(
pthread_spinlock_t *lock)
Function
Acquire a spinlock using an atomic test-and-set loop.
Result
0 once the lock is acquired; EINVAL if lock is NULL.
Notes
Uses __sync_lock_test_and_set(). On AROS the contended loop yields the
processor with sched_yield(); the call can wait indefinitely.
Bugs
Non-recursive ownership is not tracked. Acquiring a lock already held
by the same task can deadlock. The source contains an explicit TODO
concerning yield frequency. The __mc68000__ replacement for
test-and-set returns the newly written value, so this loop cannot
observe an unlocked value through that replacement.
pthread_spin_trylock()
Synopsis
int pthread_spin_trylock(
pthread_spinlock_t *lock)
Function
Attempt an atomic spinlock acquisition without waiting.
Result
0 on acquisition; EINVAL for NULL; EBUSY if test-and-set finds the
lock already held.
Notes
Does not yield, sleep, or queue a waiter. Each successful acquisition
requires a matching unlock.
Bugs
The __mc68000__ replacement for test-and-set returns the written value
instead of the old value; with a nonzero lock request this path
reports EBUSY even on an initially clear lock.
pthread_spin_unlock()
Synopsis
int pthread_spin_unlock(
pthread_spinlock_t *lock)
Function
Clear an acquired spinlock using an atomic release operation.
Result
0 after the atomic release; EINVAL if lock is NULL.
Notes
Uses __sync_lock_release(). The caller must establish ownership and
the lifetime of the lock word.
Bugs
No ownership or held-state check is performed. Unlocking an unowned or
unlocked spinlock may break mutual exclusion.
pthread_testcancel()
Synopsis
void pthread_testcancel(
void)
Function
Act on a pending cancellation request at an explicit cancellation
point.
Result
Returns no value if cancellation is absent or disabled. If pending and
enabled, calls pthread_exit(PTHREAD_CANCELED) and does not return.
Notes
A disabled request remains pending; its cancellation wake-up signal is
cleared. Use from a task registered with the pthread runtime.
Bugs
This path dereferences the result of thread lookup without checking
for an unregistered caller. It cannot safely provide cancellation for
arbitrary Exec tasks.
sched_get_priority_max()
Synopsis
int sched_get_priority_max(
int policy)
Function
Return the upper bound of the library's fixed scheduling-priority
range.
Result
2 for every policy value.
Notes
The result is a library constant, not a query of the current
Exec scheduler.
sched_get_priority_min()
Synopsis
int sched_get_priority_min(
int policy)
Function
Return the lower bound of the library's fixed scheduling-priority
range.
Result
-2 for every policy value.
Notes
The result is a library constant, not a query of the current
Exec scheduler.
sem_close()
Synopsis
int sem_close(
sem_t *sem)
Function
Return from a named-semaphore close request without changing registry
state.
Result
Always returns 0, including for NULL and invalid pointers.
Notes
This is a no-op. It neither frees the object, releases a reference,
nor unlinks its name.
Bugs
The POSIX reference-counting and close lifecycle are not implemented.
A success result is not evidence that resources were released.
sem_destroy()
Synopsis
int sem_destroy(
sem_t *sem)
Function
Attempt to destroy an unused unnamed semaphore's internal mutex and
condition variable, then clear its count and waiter count.
Result
0 after the internal destruction calls. -1 with errno EINVAL if sem is
NULL, or EBUSY if its internal mutex cannot be acquired immediately.
Notes
Include <semaphore.h>; link with pthread. The ownership probe does not
wait. The caller's storage is not freed. Reinitialize before reuse.
Do not use this function to cancel or wake waiting tasks.
Bugs
Return values from pthread_mutex_destroy() and pthread_cond_destroy()
are ignored. A sleeping waiter can leave the mutex available for the
probe, so destruction can return 0 despite busy internal objects.
Success does not establish that waiting tasks are gone. Quiescence
must be established by the application before this call.
sem_getvalue()
Synopsis
int sem_getvalue(
sem_t *sem, int *sval)
Function
Read an instantaneous semaphore count or an approximation of blocked
waiters.
Result
0 if an output value is written; -1 with errno=EINVAL if sem or sval
is NULL.
Notes
When the internal mutex is available, returns value unless a condition
wait is recorded, in which case it returns -waiters_count. If the
mutex is busy, returns -waiters_count without acquiring it.
Bugs
The busy-mutex path reads waiters_count without synchronization and
can report zero or a negative count even when permits exist. This is
not an atomic count/waiter snapshot.
sem_init()
Synopsis
int sem_init(
sem_t *sem,
int pshared,
unsigned int value)
Function
Initialize an unnamed counting semaphore in caller-provided storage.
Set its available count to value and initialize the internal mutex and
condition variable used to wait for a positive count.
Result
0 on success. -1 with errno set to EINVAL if sem is NULL or value exceeds
SEM_VALUE_MAX. Validation failure leaves the object unchanged.
Notes
Include <semaphore.h>; link with pthread. No separate semaphore storage
is allocated. Initialize before publishing to other tasks, retain the
object while any operation can use it, and destroy it only after all
users have finished. Reinitializing an active semaphore is invalid.
The semaphore must not be copied while in use.
Bugs
Process-shared operation is not implemented or rejected. Successful
initialization with nonzero pshared does not establish that capability.
sem_open()
Synopsis
sem_t *sem_open(
const char *name, int oflag, mode_t mode, unsigned int value)
Function
Look up or create a named semaphore in the pthread library's local
registry.
Result
Pointer to the named sem_t on success; SEM_FAILED with errno=EINVAL,
EEXIST, ENOENT, ENOMEM, or an error from sem_init() on failure.
Notes
Initializes a process-local linked list once, searches by FindName(),
and allocates a named object only when absent and O_CREAT is set.
Existing objects retain their initial count. The returned address is
borrowed from the registry, not a separately owned handle.
Bugs
No cross-process namespace, permissions enforcement, reference
counting, or POSIX open-instance ownership is implemented. sem_close()
is a no-op; sem_unlink() can immediately invalidate previously
returned pointers.
sem_post()
Synopsis
int sem_post(
sem_t *sem)
Function
Increment the semaphore count and signal one condition waiter when the
recorded waiter count is nonzero. No waiting task owns a particular
posted unit until it successfully decrements the count.
Result
0 after incrementing. -1 with errno EINVAL if sem is NULL, or EOVERFLOW
if the count is already SEM_VALUE_MAX. No unit is added on overflow.
Builds without EOVERFLOW define it as EINVAL in this implementation.
Notes
Include <semaphore.h>; link with pthread. The call acquires the internal
mutex and can block. It is not safe in interrupt context or an
asynchronous signal handler. The semaphore is counting, not owned;
a posting task need not have performed a corresponding wait.
Bugs
pthread_cond_signal() can repeatedly target the same listed waiter
before it removes itself. Multiple posts can therefore leave other
waiters asleep despite a positive count. No fairness or distinct-waiter
wakeup guarantee is provided.
sem_timedwait()
Synopsis
int sem_timedwait(
sem_t *sem, const struct timespec *abstime)
Function
Wait for and consume one semaphore permit, subject to an absolute
deadline.
Result
0 after decrement; -1 on error, with errno=EINVAL for NULL or the
status returned by the condition wait, including ETIMEDOUT.
Notes
Acquires the embedded mutex, increments waiters_count, loops until a
permit arrives or the condition wait fails, and then decrements the
waiter count. The default condition clock is CLOCK_REALTIME.
Bugs
No upfront abstime validation is performed. The implementation enters
the timed condition wait only while value is zero; cancellation during
that wait needs particular care because waiter accounting and mutex
cleanup are not protected by a cleanup handler.
sem_trywait()
Synopsis
int sem_trywait(
sem_t *sem)
Function
Attempt to decrement a semaphore when a positive count is available.
Result
0 after decrement; -1 with errno=EINVAL for NULL or errno=EAGAIN if
the count is zero.
Notes
Protects the count with the semaphore's embedded pthread mutex. A
successful call consumes one permit without notifying other waiters.
Bugs
Although the count test is nonblocking, pthread_mutex_lock() can wait
for the embedded mutex. The function is therefore not guaranteed to
return immediately under contention.
sem_unlink()
Synopsis
int sem_unlink(
const char *name)
Function
Remove a semaphore name and free its registry object immediately.
Result
0 if the object is destroyed and removed; -1 with errno=EINVAL for
NULL, ENOENT for an unknown name, or an error propagated by
sem_destroy().
Notes
Looks up the object in the library-local list, calls sem_destroy(),
removes its list node, and frees its allocation. All pointers returned
by sem_open() for that name then become invalid.
Bugs
Unlike POSIX deferred unlink semantics, this implementation does not
retain an object while it has open users. Synchronize all consumers
before unlinking; concurrent semaphore operations can use freed
memory.
sem_wait()
Synopsis
int sem_wait(
sem_t *sem)
Function
Wait until the semaphore count is positive, then decrement it by one.
A positive count is consumed without a condition wait. The internal
mutex can still delay acquisition even when a unit is available.
Result
0 after consuming one unit. -1 with errno EINVAL if sem is NULL.
An internal condition-wait failure is returned as -1 with its error
number in errno. Cancellation during a condition wait exits the worker
instead of returning.
Notes
Include <semaphore.h>; link with pthread. Call from the initial program
task or a registered worker. There is no timeout. Posting is not tied to
ownership; another task can supply the unit with sem_post(). CTRL_C without
active cancellation does not produce EINTR: the count is checked again.
Do not destroy the semaphore to terminate this wait.
Bugs
Cancellation inside the condition wait occurs with the internal mutex
reacquired. No cleanup handler releases it or decrements waiters_count,
so cancellation can leave the semaphore locked and unusable. Avoid
cancellation of a worker blocked here; arrange explicit wakeup and
orderly termination instead.
A pending request is not checked when a unit is available immediately.
Repeated posts can also coalesce on one condition waiter; see sem_post().