libc: common: add support for iso c11 threads

This change capitalizes on newly added support for dynamic
thread stacks and the existing pthread support to provide
an implementation of the ISO C11 `<threads.h>` API.

Signed-off-by: Christopher Friedt <cfriedt@meta.com>
This commit is contained in:
Christopher Friedt 2023-07-24 20:51:00 -04:00 committed by Stephanos Ioannidis
parent dd27dff492
commit 97668b8b09
6 changed files with 166 additions and 1 deletions

View File

@ -114,7 +114,7 @@ struct stat {
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
#if defined(__linux) && defined(__x86_64__)
__uint64_t __glibc_reserved[3];
uint64_t __glibc_reserved[3];
#endif
#else
#if defined(__rtems__)

View File

@ -1,11 +1,14 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_system_include_directories(include)
zephyr_library()
zephyr_library_property(ALLOW_EMPTY TRUE)
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_ABORT source/stdlib/abort.c)
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_TIME source/time/time.c)
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_MALLOC source/stdlib/malloc.c)
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_STRNLEN source/string/strnlen.c)
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_THRD source/thrd/thrd.c)
# Prevent compiler from optimizing calloc into an infinite recursive call
zephyr_library_compile_options($<TARGET_PROPERTY:compiler,no_builtin_malloc>)

View File

@ -67,3 +67,13 @@ config COMMON_LIBC_STRNLEN
bool
help
common implementation of strnlen().
config COMMON_LIBC_THRD
bool "C11 <threads.h> API support"
depends on DYNAMIC_THREAD
# Note: the POSIX_API dependency is only necessary until common elements
# of C11 threads and POSIX API can be abstracted out to a common library.
depends on POSIX_API
default y
help
Common implementation of C11 <threads.h> API.

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2023, Meta
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_LIB_LIBC_COMMON_INCLUDE_MACHINE__THREADS_H_
#define ZEPHYR_LIB_LIBC_COMMON_INCLUDE_MACHINE__THREADS_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef int thrd_t;
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_LIB_LIBC_COMMON_INCLUDE_MACHINE__THREADS_H_ */

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2023, Meta
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_LIB_LIBC_COMMON_INCLUDE_THREADS_H_
#define ZEPHYR_LIB_LIBC_COMMON_INCLUDE_THREADS_H_
#include <time.h>
#include <machine/_threads.h>
#include <zephyr/toolchain.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef int (*thrd_start_t)(void *arg);
enum {
thrd_success,
#define thrd_success thrd_success
thrd_nomem,
#define thrd_nomem thrd_nomem
thrd_timedout,
#define thrd_timedout thrd_timedout
thrd_busy,
#define thrd_busy thrd_busy
thrd_error,
#define thrd_error thrd_error
};
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
int thrd_equal(thrd_t lhs, thrd_t rhs);
thrd_t thrd_current(void);
int thrd_sleep(const struct timespec *duration, struct timespec *remaining);
void thrd_yield(void);
_Noreturn void thrd_exit(int res);
int thrd_detach(thrd_t thr);
int thrd_join(thrd_t thr, int *res);
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_LIB_LIBC_COMMON_INCLUDE_THREADS_H_ */

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2023, Meta
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <threads.h>
#include <zephyr/kernel.h>
#include <zephyr/posix/pthread.h>
#include <zephyr/posix/sched.h>
struct thrd_trampoline_arg {
thrd_start_t func;
void *arg;
};
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
{
typedef void *(*pthread_func_t)(void *arg);
pthread_func_t pfunc = (pthread_func_t)func;
switch (pthread_create(thr, NULL, pfunc, arg)) {
case 0:
return thrd_success;
case EAGAIN:
return thrd_nomem;
default:
return thrd_error;
}
}
int thrd_equal(thrd_t lhs, thrd_t rhs)
{
return pthread_equal(lhs, rhs);
}
thrd_t thrd_current(void)
{
return pthread_self();
}
int thrd_sleep(const struct timespec *duration, struct timespec *remaining)
{
return nanosleep(duration, remaining);
}
void thrd_yield(void)
{
(void)sched_yield();
}
FUNC_NORETURN void thrd_exit(int res)
{
pthread_exit(INT_TO_POINTER(res));
CODE_UNREACHABLE;
}
int thrd_detach(thrd_t thr)
{
switch (pthread_detach(thr)) {
case 0:
return thrd_success;
default:
return thrd_error;
}
}
int thrd_join(thrd_t thr, int *res)
{
void *ret;
switch (pthread_join(thr, &ret)) {
case 0:
if (res != NULL) {
*res = POINTER_TO_INT(ret);
}
return thrd_success;
default:
return thrd_error;
}
}