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:
parent
dd27dff492
commit
97668b8b09
@ -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__)
|
||||
|
||||
@ -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>)
|
||||
|
||||
@ -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.
|
||||
|
||||
20
lib/libc/common/include/machine/_threads.h
Normal file
20
lib/libc/common/include/machine/_threads.h
Normal 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_ */
|
||||
47
lib/libc/common/include/threads.h
Normal file
47
lib/libc/common/include/threads.h
Normal 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_ */
|
||||
85
lib/libc/common/source/thrd/thrd.c
Normal file
85
lib/libc/common/source/thrd/thrd.c
Normal 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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user