diff --git a/include/zephyr/posix/sys/stat.h b/include/zephyr/posix/sys/stat.h index 01251c65ace..2d19df29700 100644 --- a/include/zephyr/posix/sys/stat.h +++ b/include/zephyr/posix/sys/stat.h @@ -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__) diff --git a/lib/libc/common/CMakeLists.txt b/lib/libc/common/CMakeLists.txt index 04897751186..c65b6a1aa12 100644 --- a/lib/libc/common/CMakeLists.txt +++ b/lib/libc/common/CMakeLists.txt @@ -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($) diff --git a/lib/libc/common/Kconfig b/lib/libc/common/Kconfig index 56ac8f7b22b..dc22d0c2108 100644 --- a/lib/libc/common/Kconfig +++ b/lib/libc/common/Kconfig @@ -67,3 +67,13 @@ config COMMON_LIBC_STRNLEN bool help common implementation of strnlen(). + +config COMMON_LIBC_THRD + bool "C11 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 API. diff --git a/lib/libc/common/include/machine/_threads.h b/lib/libc/common/include/machine/_threads.h new file mode 100644 index 00000000000..2c61ac0d81a --- /dev/null +++ b/lib/libc/common/include/machine/_threads.h @@ -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_ */ diff --git a/lib/libc/common/include/threads.h b/lib/libc/common/include/threads.h new file mode 100644 index 00000000000..f045a23830c --- /dev/null +++ b/lib/libc/common/include/threads.h @@ -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 + +#include +#include + +#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_ */ diff --git a/lib/libc/common/source/thrd/thrd.c b/lib/libc/common/source/thrd/thrd.c new file mode 100644 index 00000000000..d811fe31ce6 --- /dev/null +++ b/lib/libc/common/source/thrd/thrd.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include + +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; + } +}