Implement pthread_getguardsize() and pthread_setguardsize().
pthread_getguardsize() and pthread_setguardsize() are required
by the POSIX_THREADS_EXT Option Group as detailed in Section
E.1 of IEEE-1003.1-2017. However, they were formerly part of
XSI_THREADS_EXT.
The XSI_THREADS_EXT Option Group was required for PSE51, PSE52,
PSE53, and PSE54 conformance.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
This change reduces the space occupied by struct pthread_attr
which is the internal type used for pthread_attr_t.
We cap the stack size at 16 bits (so up to 65536 bytes) and
since a stack size of 0 is invalid, we can encode the stack
size by simply subtracting 1 or adding 1 when setting or
getting.
The schedpolicy is capped at 2 bits and initialized,
cancellable, and detached are given 1 bit.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
Since pthread_once() is both the initializer and executor of
pthread_once_t, it can have maximally two states. Since the
implementation in Zephyr previously aimed to maximize libc
compatibility, we opted to use the definition of pthread_once_t
from newlib, which is a structure with two ints.
It does not make sense to use 64 bits to manage 2 possible
states. The control for that should effectively be a bool.
We maintain compatibility with newlib by asserting (at build
time), that newlib's pthread_once_t is larger than Zephyr's
new struct pthread_once (which just contains a bool).
This allows us to delete the non-standard pthread_key.h
header file (finally).
Reuse the pthread_pool_lock in order to synchronize the related
init function (so that it is only called maximally once from any
thread). The spinlock is only used to test the state and the
init function is not called with the spinlock held.
The alternative was to use an atomic inside of
struct pthread_once. But again, that could be up to 64-bits with
Zephyr's atomics implementation.
Ideally we would use C11 generics or something to support atomics
on 8, 16, 32, and 64-bit primitives.
Lastly, also update declarations for C11 threads as they mostly
mirror our pthread implementation.
This needed to be done as a single commit in order to ensure
continuity of build.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
pthread_sigmask() is required by the POSIX_THREADS_BASE
Option Group as detailed in Section E.1 of IEEE-1003.1-2017.
The POSIX_THREADS_BASE Option Group is required for PSE51,
PSE52, PSE53, and PSE54 conformance, and is otherwise mandatory
for any POSIX conforming system as per Section A.2.1.3 of
IEEE-1003-1.2017.
Currently, setting a pthread signal mask has no effect.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
pthread_cleanup_push() and pthread_cleanup_pop() are required
by the POSIX_THREADS_BASE Option Group as detailed in Section
E.1 of IEEE-1003.1-2017.
The POSIX_THREADS_BASE Option Group is required for PSE51,
PSE52, PSE53, and PSE54 conformance, and is otherwise mandatory
for any POSIX conforming system as per Section A.2.1.3 of
IEEE-1003-1.2017.
In this change, we require the addition of a dedicated
pthread_key_t that will not be available for applilcation usage.
Rather than including that as part of
CONFIG_MAX_PTHREAD_KEY_COUNT, we increase the storage by 1 in
order to be least invasive from the application perspective.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
Initialize the variable to zero. I don't think there is any way
out of this function without it being initialized, so IMHO it's
a false positive.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
Zephyr must support all functionality of the XSI_THREADS_EXT
subprofiling option group in order to claim it supports that
subprofiling option group.
The XSI_THREADS_EXT option group is critical to be able to
run POSIX threads with statically allocated thread stacks, which
has been a feature of the implementation since it was initially
added.
The pthread_getconcurrency() and pthread_setconcurrency()
functions are the only remaining, unimplemented functions of
the XSI_THREADS_EXT option group.
Implement pthread_getconcurrency() and pthread_setconcurrency()
via the more "posixly correct" interpretation of the
specification.
I.e. as the pthread_t:k_thread relationship is 1:1 and not M:N,
Zephyr does not support multiplexing of user threads on top of
schedulable kernel entities (i.e. "user threads" are directly
mapped to native threads, just like linuxthreads or NPTL are in
Linux).
For that reason, to be "posixly correct", we should save the
provided value via pthread_setconcurrency(), in the absense of
errors, and also return that same value back via
pthread_getconcurrency(), even though that serves zero purpose
in Zephyr for the foreseeable future.
Note: the specification also states
"an implementation can always ignore any calls to
pthread_setconcurrency() and return a constant for
pthread_getconcurrency()."
For that reason, the implementation may be revisited at a later
time when when considering optimizations and when there is a
better system in place for documenting deviations.
Any such optimization should be explicitly controlled via
Kconfig.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
pthread_setcanceltype() is required by the POSIX_THREADS_BASE
Option Group as detailed in Section E.1 of IEEE-1003.1-2017.
The POSIX_THREADS_BASE Option Group is required for PSE51,
PSE52, PSE53, and PSE54 conformance, and is otherwise mandatory
for any POSIX conforming system as per Section A.2.1.3 of
IEEE-1003-1.2017.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
_PTHREAD_CANCEL_POS is an implementation detail and should not
be defined in the global scope. Furthermore, _PTHREAD_CANCEL_POS
uses a reserved identifier (underscore followed by capital
letter).
Adjust definitions so that the implementation detail is only
used in the implementation and not in the interface.
Additionally, modify naming so that the non-standard macro does
not use a reserved identifier.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
* "identity" functions grouped more closely
* posix_thread_pool_init() should be adjacent to the SYS_INIT()
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
pthread_atfork() is required by the POSIX_THREADS_BASE
Option Group as detailed in Section E.1 of IEEE-1003.1-2017.
The POSIX_THREADS_BASE Option Group is required for PSE51,
PSE52, PSE53, and PSE54 conformance, and is otherwise
mandatory for any POSIX conforming system as per Section
A.2.1.3 of IEEE-1003-1.2017.
Since Zephyr does not yet support processes and (by extension)
fork(), this implementation includes a deviation and should be
categorized as producing undefined behaviour.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
Compiler can't tell that k_thread_abort() won't return and issues a
warning unless we tell it that control never gets this far.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Log modules should be registered with LOG_MODULE_REGISTER
rather than LOG_MODULE_DECLARE. It seems the latter works
on most platforms (at least with in minimal mode as configured
with ZTest).
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
If `pthread_exit()` is called from a `k_thread`, then we would
previously trigger an assertion. The problem with that, is that
is POSIX is acting as a compatibility layer.
Given that it is a reasonable expectation to have the calling
thread exit or abort when calling `pthread_exit()`, lets do just
that.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
Ensure that the thread return value is set by `pthread_join()`
when `status` is non-NULL.
Additionally, we have an opportunity to synchronously clean
up thread stacks in `pthread_join()`, which is preferable.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
Discovered this while implementing c11 threads, but there
was a regression recently that made it so that `pthread_join()`
would report success when attempting to join a thread that had
been detached with `pthread_detach()`.
Technically now that is undefined behaviour, but historically,
we have reported `EINVAL`, which was the older specified
return value.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
This change allows users to call pthread_create() with
the pthread_attr_t argument equal to NULL.
If Zephyr is configured with `CONFIG_DYNAMIC_THREAD`, then a
suitable thread stack will be allocated via
k_thread_stack_alloc(). The allocated thread stack is
automatically freed via k_thread_stack_free().
This makes the Zephyr implementation of pthread_create()
compliant with the normative spec.
Signed-off-by: Christopher Friedt <chrisfriedt@gmail.com>
The `pthread_once_lock` `k_mutex` is statically initialized and
only visible within file scope. Coverity identified it as unsafe
because the return values of `pthread_mutex_lock()` and
`pthread_mutex_unlock()` were unchecked. However, if those
functions were to fail here, it would be indicative that
something far worse has happened.
In any case, we add assertions that these functions
succeed rather than silently ignoring with `(void)`, which
ensures that we have coverage when assertions are enabled,
in test, while removing unneeded code with assertions disable,
in production.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
A significant enough portion of these files has been
changed to justify adding Meta copyright as well as
that of the original author.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
Previously, the `posix_internal.h` header needed to be exposed
to the application because we had non-trivial details for
most posix types (pthread, mutex, cond, ...). Since most of
those have been simplified to a typedef'ed integer, we
no longer need to expose that header to the applicaiton.
Additionally, it means that we can adopt normalized
header order in posix.
Additionally, keep more implementation details hidden
and prefer the static keyword on internal symbols where
possible.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
To enable testing, introduce `CONFIG_PTHREAD_CREATE_BARRIER`.
Some observations were made that running several Qemu SMP targets
concurrently could lead to synchronization problems. On such
targets, it was found that the synchronization issues were
mitigated by introducing a `pthread_barrier_t` shared between
`pthread_create()` and the spawned thread.
It is suggested to enable the option when running many
SMP tests concurrently in several parallel Qemu processes,
e.g. with `twister`.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
Previously, pthreads suffered from some race conditions.
This was almost inevitable given that it was maintained in
parallel to Zephyr's threading and synchronization API.
The unfortunate side-effect of with that is that it did not
receive the reliability and other improvements that
`k_thread`s did.
Here, we perform a significant update of pthread code so
that it depends directly on public Zephyr API. With that,
we reuse as many concepts as possible and pthreads benefits for
free from any improvement made to Zephyr's threading and
synchronization APIs.
Included with this change, we
* implement state with `ready_q`, `run_q`, and `done_q`
* use `pthread_barrier_wait()` to sync `pthread_create()`
* synchronize internal state with a spinlock
These pthreads are considerably more reliable than
before.
Signed-off-by: Christopher Friedt <cfriedt@meta.com>
The `SCHED_OTHER` scheduling priority is mandatory as part of
POSIX. It must be numerically distinct from `SCHED_FIFO`,
`SCHED_RR`, and `SCHED_SPORADIC`, but is implementation-
defined and may behave identically to `SCHED_FIFO` or
`SCHED_RR`.
Signed-off-by: Chris Friedt <cfriedt@meta.com>
The init infrastructure, found in `init.h`, is currently used by:
- `SYS_INIT`: to call functions before `main`
- `DEVICE_*`: to initialize devices
They are all sorted according to an initialization level + a priority.
`SYS_INIT` calls are really orthogonal to devices, however, the required
function signature requires a `const struct device *dev` as a first
argument. The only reason for that is because the same init machinery is
used by devices, so we have something like:
```c
struct init_entry {
int (*init)(const struct device *dev);
/* only set by DEVICE_*, otherwise NULL */
const struct device *dev;
}
```
As a result, we end up with such weird/ugly pattern:
```c
static int my_init(const struct device *dev)
{
/* always NULL! add ARG_UNUSED to avoid compiler warning */
ARG_UNUSED(dev);
...
}
```
This is really a result of poor internals isolation. This patch proposes
a to make init entries more flexible so that they can accept sytem
initialization calls like this:
```c
static int my_init(void)
{
...
}
```
This is achieved using a union:
```c
union init_function {
/* for SYS_INIT, used when init_entry.dev == NULL */
int (*sys)(void);
/* for DEVICE*, used when init_entry.dev != NULL */
int (*dev)(const struct device *dev);
};
struct init_entry {
/* stores init function (either for SYS_INIT or DEVICE*)
union init_function init_fn;
/* stores device pointer for DEVICE*, NULL for SYS_INIT. Allows
* to know which union entry to call.
*/
const struct device *dev;
}
```
This solution **does not increase ROM usage**, and allows to offer clean
public APIs for both SYS_INIT and DEVICE*. Note that however, init
machinery keeps a coupling with devices.
**NOTE**: This is a breaking change! All `SYS_INIT` functions will need
to be converted to the new signature. See the script offered in the
following commit.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
init: convert SYS_INIT functions to the new signature
Conversion scripted using scripts/utils/migrate_sys_init.py.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
manifest: update projects for SYS_INIT changes
Update modules with updated SYS_INIT calls:
- hal_ti
- lvgl
- sof
- TraceRecorderSource
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
tests: devicetree: devices: adjust test
Adjust test according to the recently introduced SYS_INIT
infrastructure.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
tests: kernel: threads: adjust SYS_INIT call
Adjust to the new signature: int (*init_fn)(void);
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
The remaining types that needed to be harmonized between
Newlib and Zephyr's POSIX definitions are:
* `struct sched_param`
- don't re-define if using minimal libc
* `pthread_attr_t`
- convert to `struct pthread_attr`
- define type if using minimal libc
- assert acceptible object size
* `pthread_mutexattr_t`
- convert to `struct pthread_mutexattr`
- define type if using minimal libc
- assert acceptible object size
* `pthred_condattr_t`
- convert to `struct pthread_condattr`
- define type if using minimal libc
- assert acceptible object size
* `pthread_once_t`
- adopt newlib definition
- define type if using minimal libc
Signed-off-by: Chris Friedt <cfriedt@meta.com>
Define `PTHREAD_CREATE_DETACHED` and
`PTHREAD_CREATE_JOINABLE` to be compatible with the Newlib
definitions.
This is a temporary workaround for #51211 until Newlib
headers are pulled in.
Signed-off-by: Chris Friedt <cfriedt@meta.com>
Previously, `pthread_cond_init()` could not actually fail, and
destroying condition variables was a no-op, and it was missing
in `pthread_exit()`.
However, with the change of `pthread_cond_t` to `uint32_t`, and
since those are embedded inside of `struct posix_thread` for the
time being, the pthread code needs to keep track that it is
relinquishes used condition variables when a thread completes.
Signed-off-by: Chris Friedt <cfriedt@meta.com>
Previously, `pthread_mutex_init()` could not actually fail, and
destroying mutexes was a no-op, so it was missing in a couple of
places.
However, with the change of `pthread_mutex_t` to `uint32_t`, and
since those are embedded inside of `struct posix_thread` for the
time being, the pthread code needs to keep track that it is
relinquishes used mutex resources when a thread completes.
Signed-off-by: Chris Friedt <cfriedt@meta.com>
The `pthread_create()` function is not a cancellation point and
iterating over / mutating `posix_thread_pool` is not a blocking
operation, so use a spinlock for the internal `pthread_pool_lock`.
Signed-off-by: Chris Friedt <cfriedt@meta.com>
In the interest of reducing any layering concerns,
avoid using POSIX locking primitives where necessary.
Note: it is not safe to use a spinlock here, as the
callback function to `pthread_once()` may itself be
a cancellation point.
Signed-off-by: Chris Friedt <cfriedt@meta.com>
Several other widely-used pthread implementations
abstract `pthread_t` as `uint32_t`. The benefit
there is that we avoid passing around a pointer to
an internal structure (implementation detail).
Additionally, this removes the alias from `k_tid_t`
to `pthread_t` inside of `struct pthread_mutex`.
Signed-off-by: Chris Friedt <cfriedt@meta.com>
If a thread is joined using `pthread_join()`, then the
internal state would be set to `PTHREAD_EXITED`.
Previously, `pthread_create()` would only consider pthreads
with internal state `PTHREAD_TERMINATED` as candidates for new
threads. However, that causes a descriptor leak.
We should be able to reuse a single thread an infinite number
of times.
Here, we also consider threads with internal state
`PTHREAD_EXITED` as candiates in `pthread_create()`.
Fixes#47609
Signed-off-by: Christopher Friedt <cfriedt@fb.com>
In order to bring consistency in-tree, migrate all lib code to the new
prefix <zephyr/...>. Note that the conversion has been scripted, refer
to zephyrproject-rtos#45388 for more details.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
As described in
https://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_once.html.
The behavior of pthread_once() is undefined if once_control has
automatic storage duration or is not initialized by PTHREAD_ONCE_INIT
However, in Zephyr, the implementation is incorrect. If the init value
is PTHREAD_ONCE_INIT, the program will never run the init_func.
Signed-off-by: Jaxson Han <jaxson.han@arm.com>
In a primitive SYS_SLIST_FOR_EACH_NODE check for null was
after dereferencing. Place check for null of the "thread_spec_data"
before its dereferencing.
Found as a coding guideline violation (MISRA R4.1) by static
coding scanning tool.
Signed-off-by: Maksim Masalski <maksim.masalski@intel.com>
Mostly trivial search-and-replace, except for pthread_rwlock.c, where
we need spread timeout over 2 semaphore operations.
Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>