From 6acf560ed06ba3858d8bdbe3aa9ffcaf2fda7c3f Mon Sep 17 00:00:00 2001 From: Wildan M Date: Thu, 4 Jun 2026 00:38:58 +0700 Subject: [PATCH] Fix pthread init and null for C++ --- src/header/bits_null/cbindgen.toml | 7 ++++ src/header/bits_null/mod.rs | 5 +-- src/header/bits_pthread/cbindgen.toml | 6 +-- src/header/threads/cbindgen.toml | 2 + tests/Makefile | 9 ++++- tests/Makefile.tests.mk | 2 + tests/expected/pthread/init.stdout | 1 + tests/expected/pthread/init_cpp.stdout | 1 + tests/pthread/init.c | 1 + tests/pthread/init.cpp | 52 ++++++++++++++++++++++++++ 10 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 tests/expected/pthread/init.stdout create mode 100644 tests/expected/pthread/init_cpp.stdout create mode 120000 tests/pthread/init.c create mode 100644 tests/pthread/init.cpp diff --git a/src/header/bits_null/cbindgen.toml b/src/header/bits_null/cbindgen.toml index 2dd16668fc..be6b69c17f 100644 --- a/src/header/bits_null/cbindgen.toml +++ b/src/header/bits_null/cbindgen.toml @@ -9,3 +9,10 @@ include_guard = "_RELIBC_BITS_NULL_T_H" language = "C" no_includes = true +after_includes = """ +#ifdef __cplusplus + #define NULL nullptr +#else + #define NULL ((void *)0) +#endif +""" diff --git a/src/header/bits_null/mod.rs b/src/header/bits_null/mod.rs index a345f3c829..aa36f0cf83 100644 --- a/src/header/bits_null/mod.rs +++ b/src/header/bits_null/mod.rs @@ -1,4 +1 @@ -use crate::platform::types::c_long; - -/// Null pointer constant. -pub const NULL: c_long = 0; +// NULL is defined in cbindgen diff --git a/src/header/bits_pthread/cbindgen.toml b/src/header/bits_pthread/cbindgen.toml index ea30c3892b..dd0584daa0 100644 --- a/src/header/bits_pthread/cbindgen.toml +++ b/src/header/bits_pthread/cbindgen.toml @@ -6,10 +6,10 @@ no_includes = true cpp_compat = true # TODO: Any better way to implement pthread_cleanup_push/pthread_cleanup_pop? after_includes = """ -#define PTHREAD_COND_INITIALIZER ((pthread_cond_t){0}) -#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t){0}) +#define PTHREAD_COND_INITIALIZER {0} +#define PTHREAD_MUTEX_INITIALIZER {0} +#define PTHREAD_RWLOCK_INITIALIZER {0} #define PTHREAD_ONCE_INIT ((pthread_once_t){0}) -#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t){0}) #define pthread_cleanup_push(ROUTINE, ARG) do { \\ struct { \\ diff --git a/src/header/threads/cbindgen.toml b/src/header/threads/cbindgen.toml index 996bd702c4..5eedcd9937 100644 --- a/src/header/threads/cbindgen.toml +++ b/src/header/threads/cbindgen.toml @@ -15,7 +15,9 @@ after_includes = """ #include // for timespec #include // for pthread-related types +#ifndef __cplusplus #define thread_local _Thread_local +#endif #define ONCE_FLAG_INIT PTHREAD_ONCE_INIT // once_flag == pthread_once_t """ diff --git a/tests/Makefile b/tests/Makefile index a47fd5534b..31f0d79715 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -69,7 +69,6 @@ $(BUILD)/%.c: %.c cp "$*.c" "$@" FLAGS=\ - -std=c11 \ -fno-builtin \ -fno-stack-protector \ -Wall \ @@ -145,6 +144,10 @@ else endif endif +$(BUILD)/bins_static/%_cpp: %.cpp $(DEPS) + mkdir -p "$$(dirname "$@")" + $(CC) -x c++ "$<" -x none -o "$@" $(FLAGS) $(STATIC_FLAGS) + $(BUILD)/bins_static/%: %.c $(DEPS) mkdir -p "$$(dirname "$@")" @$(CC) "$<" -o "$@" $(FLAGS) $(STATIC_FLAGS) @@ -171,6 +174,10 @@ $(BUILD)/bins_dynamic/dlopen_scopes: dlopen_scopes.c $(BUILD)/bins_dynamic/libfo mkdir -p "$$(dirname "$@")" @$(CC) "$<" -o "$@" $(FLAGS) $(DYNAMIC_FLAGS) +$(BUILD)/bins_dynamic/%_cpp: %.cpp $(DEPS) + mkdir -p "$$(dirname "$@")" + $(CC) -x c++ "$<" -x none -o "$@" $(FLAGS) $(DYNAMIC_FLAGS) + $(BUILD)/bins_dynamic/%: %.c $(DEPS) mkdir -p "$$(dirname "$@")" @$(CC) "$<" -o "$@" $(FLAGS) $(DYNAMIC_FLAGS) diff --git a/tests/Makefile.tests.mk b/tests/Makefile.tests.mk index 634884d7c2..d545a0f29f 100644 --- a/tests/Makefile.tests.mk +++ b/tests/Makefile.tests.mk @@ -338,6 +338,8 @@ STATIC_CHECK_EXPECT_NAMES=\ args \ constructor \ destructor \ + pthread/init \ + pthread/init_cpp \ stdlib/env \ unistd/brk \ tls diff --git a/tests/expected/pthread/init.stdout b/tests/expected/pthread/init.stdout new file mode 100644 index 0000000000..b2d1a7762f --- /dev/null +++ b/tests/expected/pthread/init.stdout @@ -0,0 +1 @@ +once diff --git a/tests/expected/pthread/init_cpp.stdout b/tests/expected/pthread/init_cpp.stdout new file mode 100644 index 0000000000..b2d1a7762f --- /dev/null +++ b/tests/expected/pthread/init_cpp.stdout @@ -0,0 +1 @@ +once diff --git a/tests/pthread/init.c b/tests/pthread/init.c new file mode 120000 index 0000000000..95f5d3ede0 --- /dev/null +++ b/tests/pthread/init.c @@ -0,0 +1 @@ +init.cpp \ No newline at end of file diff --git a/tests/pthread/init.cpp b/tests/pthread/init.cpp new file mode 100644 index 0000000000..c0a2072c94 --- /dev/null +++ b/tests/pthread/init.cpp @@ -0,0 +1,52 @@ +// this file is both C and CPP to check NULL and thread_local on C++ environment + +#include +#include +#include +#include +#include + +static pthread_cond_t global_cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_rwlock_t global_rwlock = PTHREAD_RWLOCK_INITIALIZER; +// TODO: POSIX mandates *_INITIALIZER as const initializer but not PTHREAD_ONCE_INIT +// But glibc and other platform support it. Ours cannot in C due to union type +#ifdef __cplusplus +static pthread_once_t global_once = PTHREAD_ONCE_INIT; +#else +static pthread_once_t global_once = {0}; +#endif + +static void once_callback(void) { + printf("once\n"); +} + +static thread_local int tls_counter = 100; + +void* thread_func(void* args) { + (void)args; + assert(tls_counter == 100); + tls_counter = 200; + assert(tls_counter == 200); + return NULL; +} + +int main(void) { + assert(pthread_mutex_lock(&global_mutex) == 0); + assert(pthread_mutex_unlock(&global_mutex) == 0); + assert(pthread_rwlock_wrlock(&global_rwlock) == 0); + assert(pthread_rwlock_unlock(&global_rwlock) == 0); + assert(pthread_once(&global_once, once_callback) == 0); + assert(pthread_cond_signal(&global_cond) == 0); + + pthread_t thread_id; + int create_res = pthread_create(&thread_id, NULL, thread_func, NULL); + assert(create_res == 0); + pthread_mutex_t dynamic_mutex; + int mutex_res = pthread_mutex_init(&dynamic_mutex, NULL); + assert(mutex_res == 0); + assert(pthread_join(thread_id, NULL) == 0); + assert(tls_counter == 100); + + return 0; +}