From b731c65d8ad8954ba646eedbd4cd68ab2f485c93 Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sat, 24 Jan 2026 22:29:12 +0100 Subject: [PATCH 01/10] initial new pthread wrapper --- src/pthreads.cpp | 69 +++++++++++++++++++++++++++--------------------- src/pthreads.h | 47 ++++++++++++++++++++++++--------- 2 files changed, 73 insertions(+), 43 deletions(-) diff --git a/src/pthreads.cpp b/src/pthreads.cpp index eeb47fc..288658b 100644 --- a/src/pthreads.cpp +++ b/src/pthreads.cpp @@ -22,36 +22,33 @@ bionic::pthread_cleanup_holder::~pthread_cleanup_holder() { } } -void bionic::mutex_static_initializer(shim::pthread_mutex_t *mutex, shim::pthread_mutex_t &old) { - if (is_mutex_initialized(&old)) - return; +::pthread_mutex_t *shim::bionic::mutex_static_initializer(int32_t init_value, shim::bionic::atomic_uintptr_t *p, uintptr_t payload) { + // assert((uintptr_t)p % 8 == 0); -#ifdef __LP64__ - auto init_value = old.init_value; -#else - auto init_value = (size_t) old.wrapped; -#endif - shim::pthread_mutex_t n = old; - - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - if (init_value == recursive_mutex_init_value) - pthread_mutexattr_settype(&attr, (int) mutex_type::RECURSIVE); - else if (init_value == errorcheck_mutex_init_value) - pthread_mutexattr_settype(&attr, (int) mutex_type::ERRORCHECK); - if (pthread_mutex_init(&n, &attr) != 0) + ::pthread_mutex_t *mutex_ptr = (::pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + + ::pthread_mutexattr_t attr; + ::pthread_mutexattr_init(&attr); + if (init_value == bionic::recursive_mutex_init_value) + ::pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + else if (init_value == bionic::errorcheck_mutex_init_value) + ::pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); + + if (::pthread_mutex_init(mutex_ptr, &attr) != 0) handle_runtime_error("Failed to init mutex"); + pthread_mutexattr_destroy(&attr); - if(!detail::update_wrapper(mutex, old, n)) { - // Concurrent creation, we need to destroy the new one - detail::destroy_c_wrapped(&n, &::pthread_mutex_destroy); - if(!is_mutex_initialized(&old)) { - handle_runtime_error("Failed to init mutex by other thread"); - } - } else { - old = n; + if(atomic_compare_exchange_strong_explicit(p, &payload, (uintptr_t)mutex_ptr, + std::memory_order_release, std::memory_order_acquire)) [[likely]] { + return mutex_ptr; } + // Concurrent creation, we need to destroy the new one + free(mutex_ptr); + if(!is_mutex_initialized(payload)) [[unlikely]] { + handle_runtime_error("Failed to init mutex by other thread"); + } + return (::pthread_mutex_t*)payload; } void bionic::cond_static_initializer(shim::pthread_cond_t *cond, shim::pthread_cond_t &old) { @@ -289,15 +286,27 @@ int shim::pthread_setname_np(pthread_t thread, const char* name) { int shim::pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { host_mutexattr hattr (attr); - int ret = detail::make_c_wrapped(mutex, &::pthread_mutex_init, &hattr.attr); - return bionic::translate_errno_from_host(ret); + ::pthread_mutex_t *mutex_ptr = (::pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + + int ret = ::pthread_mutex_init(mutex_ptr, &hattr.attr); + if (ret != 0) { + free(mutex_ptr); + return bionic::translate_errno_from_host(ret); + } + + atomic_store(bionic::get_payload_pointer(mutex), (uintptr_t)mutex_ptr); + + return bionic::translate_errno_from_host(0); } int shim::pthread_mutex_destroy(pthread_mutex_t *wrapper) { - auto mutex = detail::load_wrapper(wrapper); - if (!bionic::is_mutex_initialized(mutex)) + auto p = bionic::get_payload_pointer(wrapper); + uintptr_t v = atomic_load(p); + if (!bionic::is_mutex_initialized(v)) return 0; - int ret = detail::destroy_c_wrapped(&mutex.value, &::pthread_mutex_destroy); + auto ret = ::pthread_mutex_destroy((::pthread_mutex_t *)v); + atomic_store(p, 0); + free((void *)v); return bionic::translate_errno_from_host(ret); } diff --git a/src/pthreads.h b/src/pthreads.h index f84680c..01a430a 100644 --- a/src/pthreads.h +++ b/src/pthreads.h @@ -11,32 +11,50 @@ namespace shim { namespace bionic { + using atomic_uintptr_t = std::atomic_uintptr_t; + + static_assert(alignof(atomic_uintptr_t) == alignof(uintptr_t)); + static_assert(sizeof(atomic_uintptr_t) == sizeof(uintptr_t)); struct pthread_mutex_t { #if defined(__LP64__) - size_t init_value; - ::pthread_mutex_t *wrapped; - int64_t priv[2]; + int32_t data[10]; #else - ::pthread_mutex_t *wrapped; + int32_t data[1]; #endif }; + static_assert(alignof(pthread_mutex_t) == 4); + constexpr size_t mutex_init_value = 0; constexpr size_t recursive_mutex_init_value = 0x4000; constexpr size_t errorcheck_mutex_init_value = 0x8000; - inline bool is_mutex_initialized(pthread_mutex_t const *m) { + atomic_uintptr_t *get_payload_pointer(pthread_mutex_t *p) { #if defined(__LP64__) - return (m->wrapped != nullptr); + uintptr_t v = (uintptr_t)p; + v += sizeof(int32_t); // leave the first 4 bytes untouched + v += alignof(atomic_uintptr_t) - 1; + v &= -alignof(atomic_uintptr_t); + p = (pthread_mutex_t *)v; #else - return ((size_t) m->wrapped != mutex_init_value && - (size_t) m->wrapped != recursive_mutex_init_value && - (size_t) m->wrapped != errorcheck_mutex_init_value); + static_assert(alignof(atomic_uintptr_t) == alignof(pthread_mutex_t)); + static_assert(sizeof(atomic_uintptr_t) == sizeof(pthread_mutex_t)); #endif + return (atomic_uintptr_t *)p; } - void mutex_static_initializer(pthread_mutex_t *mutex, pthread_mutex_t &old); + + inline bool is_mutex_initialized(uintptr_t v) { +#if defined(__LP64__) + return v != 0; +#else + constexpr uintptr_t INIT_MUTEX_MASK = ~(3u << 14); + return (v & INIT_MUTEX_MASK) != 0; +#endif + } + + ::pthread_mutex_t * mutex_static_initializer(int32_t init_value, bionic::atomic_uintptr_t *p, uintptr_t payload); struct pthread_cond_t { ::pthread_cond_t *wrapped; @@ -68,9 +86,12 @@ namespace shim { template <> inline auto to_host(pthread_mutex_t const *o) { - auto m = detail::load_wrapper(o); - mutex_static_initializer(const_cast(o), m.value); - return m.value.wrapped; + atomic_uintptr_t *payload_ptr = get_payload_pointer(const_cast(o)); + uintptr_t payload = atomic_load_explicit(payload_ptr, std::memory_order_relaxed); + if(is_mutex_initialized(payload)) [[likely]] { + return (::pthread_mutex_t *)payload; + } + return mutex_static_initializer(o->data[0], payload_ptr, payload); } template <> inline auto to_host(pthread_cond_t const *o) { From aee672d3621dd1a6a7a3dc9c49f621330e35ae69 Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sat, 24 Jan 2026 22:31:22 +0100 Subject: [PATCH 02/10] fix builds --- src/pthreads.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pthreads.h b/src/pthreads.h index 01a430a..a3e0c01 100644 --- a/src/pthreads.h +++ b/src/pthreads.h @@ -30,7 +30,7 @@ namespace shim { constexpr size_t recursive_mutex_init_value = 0x4000; constexpr size_t errorcheck_mutex_init_value = 0x8000; - atomic_uintptr_t *get_payload_pointer(pthread_mutex_t *p) { + inline atomic_uintptr_t *get_payload_pointer(pthread_mutex_t *p) { #if defined(__LP64__) uintptr_t v = (uintptr_t)p; v += sizeof(int32_t); // leave the first 4 bytes untouched From 573c50c9a383120db2efeead416c58eee10886dc Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sat, 24 Jan 2026 22:39:29 +0100 Subject: [PATCH 03/10] fixes --- src/pthreads.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pthreads.cpp b/src/pthreads.cpp index 288658b..d4650fd 100644 --- a/src/pthreads.cpp +++ b/src/pthreads.cpp @@ -25,7 +25,7 @@ bionic::pthread_cleanup_holder::~pthread_cleanup_holder() { ::pthread_mutex_t *shim::bionic::mutex_static_initializer(int32_t init_value, shim::bionic::atomic_uintptr_t *p, uintptr_t payload) { // assert((uintptr_t)p % 8 == 0); - ::pthread_mutex_t *mutex_ptr = (::pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + ::pthread_mutex_t *mutex_ptr = (::pthread_mutex_t *)malloc(sizeof(::pthread_mutex_t)); ::pthread_mutexattr_t attr; ::pthread_mutexattr_init(&attr); @@ -48,7 +48,7 @@ ::pthread_mutex_t *shim::bionic::mutex_static_initializer(int32_t init_value, sh if(!is_mutex_initialized(payload)) [[unlikely]] { handle_runtime_error("Failed to init mutex by other thread"); } - return (::pthread_mutex_t*)payload; + return (::pthread_mutex_t*)payload; } void bionic::cond_static_initializer(shim::pthread_cond_t *cond, shim::pthread_cond_t &old) { From b17e722342577efe23125fde5754f4426f998d5d Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sat, 24 Jan 2026 22:41:47 +0100 Subject: [PATCH 04/10] cond --- src/pthreads.cpp | 52 ++++++++++++++++++++++++++++++------------------ src/pthreads.h | 30 +++++++++++++++------------- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/src/pthreads.cpp b/src/pthreads.cpp index d4650fd..b07b3d3 100644 --- a/src/pthreads.cpp +++ b/src/pthreads.cpp @@ -51,23 +51,24 @@ ::pthread_mutex_t *shim::bionic::mutex_static_initializer(int32_t init_value, sh return (::pthread_mutex_t*)payload; } -void bionic::cond_static_initializer(shim::pthread_cond_t *cond, shim::pthread_cond_t &old) { - if (is_cond_initialized(&old)) - return; - shim::pthread_cond_t n = old; - if(pthread_cond_init(&n, nullptr) == 0) { - if(!detail::update_wrapper(cond, old, n)) { - // Concurrent creation, we need to destroy the new one - detail::destroy_c_wrapped(&n, &::pthread_cond_destroy); - if (!is_cond_initialized(&old)) { - handle_runtime_error("Failed to init cond by other thread"); - } - } else { - old = n; - } - } else { +::pthread_cond_t *shim::bionic::cond_static_initializer(shim::bionic::atomic_uintptr_t *p, uintptr_t payload) { + // assert((uintptr_t)p % 8 == 0); + + ::pthread_cond_t *cond_ptr = (::pthread_cond_t *)malloc(sizeof(::pthread_cond_t)); + + if (::pthread_cond_init(cond_ptr, nullptr) != 0) handle_runtime_error("Failed to init cond"); + + if(atomic_compare_exchange_strong_explicit(p, &payload, (uintptr_t)cond_ptr, + std::memory_order_release, std::memory_order_acquire)) [[likely]] { + return cond_ptr; } + // Concurrent creation, we need to destroy the new one + free(cond_ptr); + if(!is_cond_initialized(payload)) [[unlikely]] { + handle_runtime_error("Failed to init cond by other thread"); + } + return (::pthread_cond_t*)payload; } void bionic::rwlock_static_initializer(shim::pthread_rwlock_t *rwlock, shim::pthread_rwlock_t &old) { @@ -348,14 +349,27 @@ int shim::pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) int shim::pthread_cond_init(pthread_cond_t *cond, const shim::pthread_condattr_t *attr) { host_condattr hattr (attr); - int ret = detail::make_c_wrapped(cond, &::pthread_cond_init, &hattr.attr); - return bionic::translate_errno_from_host(ret); + ::pthread_cond_t *cond_ptr = (::pthread_cond_t *)malloc(sizeof(pthread_cond_t)); + + int ret = ::pthread_cond_init(cond_ptr, &hattr.attr); + if (ret != 0) { + free(cond_ptr); + return bionic::translate_errno_from_host(ret); + } + + atomic_store(bionic::get_payload_pointer(cond), (uintptr_t)cond_ptr); + return bionic::translate_errno_from_host(0); } int shim::pthread_cond_destroy(pthread_cond_t *cond) { - if (!bionic::is_cond_initialized(cond)) + auto p = bionic::get_payload_pointer(cond); + uintptr_t v = atomic_load(p); + if (!bionic::is_cond_initialized(v)) return 0; - return bionic::translate_errno_from_host(detail::destroy_c_wrapped(cond, &::pthread_cond_destroy)); + auto ret = ::pthread_cond_destroy((::pthread_cond_t *)v); + atomic_store(p, 0); + free((void *)v); + return bionic::translate_errno_from_host(ret); } int shim::pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { diff --git a/src/pthreads.h b/src/pthreads.h index a3e0c01..cdd0b6f 100644 --- a/src/pthreads.h +++ b/src/pthreads.h @@ -30,16 +30,16 @@ namespace shim { constexpr size_t recursive_mutex_init_value = 0x4000; constexpr size_t errorcheck_mutex_init_value = 0x8000; - inline atomic_uintptr_t *get_payload_pointer(pthread_mutex_t *p) { + template atomic_uintptr_t *get_payload_pointer(T *p) { #if defined(__LP64__) uintptr_t v = (uintptr_t)p; v += sizeof(int32_t); // leave the first 4 bytes untouched v += alignof(atomic_uintptr_t) - 1; v &= -alignof(atomic_uintptr_t); - p = (pthread_mutex_t *)v; + p = (T *)v; #else - static_assert(alignof(atomic_uintptr_t) == alignof(pthread_mutex_t)); - static_assert(sizeof(atomic_uintptr_t) == sizeof(pthread_mutex_t)); + static_assert(alignof(atomic_uintptr_t) == alignof(T)); + static_assert(sizeof(atomic_uintptr_t) == sizeof(T)); #endif return (atomic_uintptr_t *)p; } @@ -57,19 +57,18 @@ namespace shim { ::pthread_mutex_t * mutex_static_initializer(int32_t init_value, bionic::atomic_uintptr_t *p, uintptr_t payload); struct pthread_cond_t { - ::pthread_cond_t *wrapped; #if defined(__LP64__) - int64_t priv[5]; + int32_t data[12]; +#else + int32_t data[1]; #endif }; - inline bool is_cond_initialized(pthread_cond_t const *m) { - auto wrapped_ptr = reinterpret_cast *>(m); - auto val = wrapped_ptr->load(std::memory_order_relaxed); - return val.wrapped != nullptr; + inline bool is_cond_initialized(uintptr_t v) { + return v != 0; } - void cond_static_initializer(pthread_cond_t *cond, pthread_cond_t &old); + ::pthread_cond_t * cond_static_initializer(bionic::atomic_uintptr_t *p, uintptr_t payload); struct pthread_rwlock_t { ::pthread_rwlock_t *wrapped; @@ -95,9 +94,12 @@ namespace shim { } template <> inline auto to_host(pthread_cond_t const *o) { - auto m = detail::load_wrapper(o); - cond_static_initializer(const_cast(o), m.value); - return m.value.wrapped; + atomic_uintptr_t *payload_ptr = get_payload_pointer(const_cast(o)); + uintptr_t payload = atomic_load_explicit(payload_ptr, std::memory_order_relaxed); + if(is_cond_initialized(payload)) [[likely]] { + return (::pthread_cond_t *)payload; + } + return cond_static_initializer(payload_ptr, payload); } template <> inline auto to_host(pthread_rwlock_t const *o) { From 7f75f8ef5b7e720286acd54bf7618ccbc0b445d6 Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sat, 24 Jan 2026 22:42:20 +0100 Subject: [PATCH 05/10] fixes --- src/pthreads.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pthreads.cpp b/src/pthreads.cpp index b07b3d3..afe4d06 100644 --- a/src/pthreads.cpp +++ b/src/pthreads.cpp @@ -287,7 +287,7 @@ int shim::pthread_setname_np(pthread_t thread, const char* name) { int shim::pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { host_mutexattr hattr (attr); - ::pthread_mutex_t *mutex_ptr = (::pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + ::pthread_mutex_t *mutex_ptr = (::pthread_mutex_t *)malloc(sizeof(::pthread_mutex_t)); int ret = ::pthread_mutex_init(mutex_ptr, &hattr.attr); if (ret != 0) { @@ -349,7 +349,7 @@ int shim::pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) int shim::pthread_cond_init(pthread_cond_t *cond, const shim::pthread_condattr_t *attr) { host_condattr hattr (attr); - ::pthread_cond_t *cond_ptr = (::pthread_cond_t *)malloc(sizeof(pthread_cond_t)); + ::pthread_cond_t *cond_ptr = (::pthread_cond_t *)malloc(sizeof(::pthread_cond_t)); int ret = ::pthread_cond_init(cond_ptr, &hattr.attr); if (ret != 0) { From eeeeb5e446776f09cec39b36b61413506fbb6e5a Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sat, 24 Jan 2026 22:48:47 +0100 Subject: [PATCH 06/10] rwlock --- src/pthreads.cpp | 51 ++++++++++++++++++++++++++++++------------------ src/pthreads.h | 21 +++++++++++--------- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/pthreads.cpp b/src/pthreads.cpp index afe4d06..8ab6a58 100644 --- a/src/pthreads.cpp +++ b/src/pthreads.cpp @@ -71,23 +71,24 @@ ::pthread_cond_t *shim::bionic::cond_static_initializer(shim::bionic::atomic_uin return (::pthread_cond_t*)payload; } -void bionic::rwlock_static_initializer(shim::pthread_rwlock_t *rwlock, shim::pthread_rwlock_t &old) { - if (is_rwlock_initialized(&old)) - return; - shim::pthread_rwlock_t n = old; - if(pthread_rwlock_init(&n, nullptr) == 0) { - if(!detail::update_wrapper(rwlock, old, n)) { - // Concurrent creation, we need to destroy the new one - detail::destroy_c_wrapped(&n, &::pthread_rwlock_destroy); - if (!is_rwlock_initialized(&old)) { - handle_runtime_error("Failed to init rwlock by other thread"); - } - } else { - old = n; - } - } else { +::pthread_rwlock_t *bionic::rwlock_static_initializer(shim::bionic::atomic_uintptr_t *p, uintptr_t payload) { + // assert((uintptr_t)p % 8 == 0); + + ::pthread_rwlock_t *rwlock_ptr = (::pthread_rwlock_t *)malloc(sizeof(::pthread_rwlock_t)); + + if (::pthread_rwlock_init(rwlock_ptr, nullptr) != 0) handle_runtime_error("Failed to init rwlock"); + + if(atomic_compare_exchange_strong_explicit(p, &payload, (uintptr_t)rwlock_ptr, + std::memory_order_release, std::memory_order_acquire)) [[likely]] { + return rwlock_ptr; + } + // Concurrent creation, we need to destroy the new one + free(rwlock_ptr); + if(!is_rwlock_initialized(payload)) [[unlikely]] { + handle_runtime_error("Failed to init rwlock by other thread"); } + return (::pthread_rwlock_t*)payload; } int bionic::to_host_mutex_type(bionic::mutex_type type) { @@ -417,14 +418,26 @@ int shim::pthread_condattr_getclock(const pthread_condattr_t *attr, int *clock) int shim::pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { if (attr != nullptr) handle_runtime_error("non-NULL rwlock attr is currently not supported"); - int ret = detail::make_c_wrapped(rwlock, &::pthread_rwlock_init, nullptr); - return bionic::translate_errno_from_host(ret); + ::pthread_rwlock_t *rwlock_ptr = (::pthread_rwlock_t *)malloc(sizeof(::pthread_rwlock_t)); + + int ret = ::pthread_rwlock_init(rwlock_ptr, nullptr); + if (ret != 0) { + free(rwlock_ptr); + return bionic::translate_errno_from_host(ret); + } + + atomic_store(bionic::get_payload_pointer(rwlock), (uintptr_t)rwlock_ptr); + return bionic::translate_errno_from_host(0); } int shim::pthread_rwlock_destroy(pthread_rwlock_t *rwlock) { - if (!bionic::is_rwlock_initialized(rwlock)) + auto p = bionic::get_payload_pointer(rwlock); + uintptr_t v = atomic_load(p); + if (!bionic::is_rwlock_initialized(v)) return 0; - int ret = detail::destroy_c_wrapped(rwlock, &::pthread_rwlock_destroy); + auto ret = ::pthread_rwlock_destroy((::pthread_rwlock_t *)v); + atomic_store(p, 0); + free((void *)v); return bionic::translate_errno_from_host(ret); } diff --git a/src/pthreads.h b/src/pthreads.h index cdd0b6f..ccdc07e 100644 --- a/src/pthreads.h +++ b/src/pthreads.h @@ -71,18 +71,18 @@ namespace shim { ::pthread_cond_t * cond_static_initializer(bionic::atomic_uintptr_t *p, uintptr_t payload); struct pthread_rwlock_t { - ::pthread_rwlock_t *wrapped; #if defined(__LP64__) - int64_t priv[6]; + int32_t data[14]; +#else + int32_t data[1]; #endif }; - inline bool is_rwlock_initialized(pthread_rwlock_t const *m) { - return m->wrapped != nullptr; + inline bool is_rwlock_initialized(uintptr_t v) { + return v != 0; } - void rwlock_static_initializer(pthread_rwlock_t *rwlock, pthread_rwlock_t &old); - + ::pthread_rwlock_t * rwlock_static_initializer(bionic::atomic_uintptr_t *p, uintptr_t payload); template <> inline auto to_host(pthread_mutex_t const *o) { atomic_uintptr_t *payload_ptr = get_payload_pointer(const_cast(o)); @@ -103,9 +103,12 @@ namespace shim { } template <> inline auto to_host(pthread_rwlock_t const *o) { - auto m = detail::load_wrapper(o); - rwlock_static_initializer(const_cast(o), m.value); - return m.value.wrapped; + atomic_uintptr_t *payload_ptr = get_payload_pointer(const_cast(o)); + uintptr_t payload = atomic_load_explicit(payload_ptr, std::memory_order_relaxed); + if(is_rwlock_initialized(payload)) [[likely]] { + return (::pthread_rwlock_t *)payload; + } + return rwlock_static_initializer(payload_ptr, payload); } enum class mutex_type : uint32_t { From 9e845e4eac18774d361dfcea13563f65be7936ff Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 25 Jan 2026 13:47:48 +0100 Subject: [PATCH 07/10] cshim asserts --- src/pthreads.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/pthreads.cpp b/src/pthreads.cpp index 8ab6a58..6009319 100644 --- a/src/pthreads.cpp +++ b/src/pthreads.cpp @@ -23,7 +23,9 @@ bionic::pthread_cleanup_holder::~pthread_cleanup_holder() { } ::pthread_mutex_t *shim::bionic::mutex_static_initializer(int32_t init_value, shim::bionic::atomic_uintptr_t *p, uintptr_t payload) { - // assert((uintptr_t)p % 8 == 0); + if((uintptr_t)p % alignof(::pthread_mutex_t *) != 0) { + handle_runtime_error("unaligned mutex"); + } ::pthread_mutex_t *mutex_ptr = (::pthread_mutex_t *)malloc(sizeof(::pthread_mutex_t)); @@ -52,8 +54,9 @@ ::pthread_mutex_t *shim::bionic::mutex_static_initializer(int32_t init_value, sh } ::pthread_cond_t *shim::bionic::cond_static_initializer(shim::bionic::atomic_uintptr_t *p, uintptr_t payload) { - // assert((uintptr_t)p % 8 == 0); - + if((uintptr_t)p % alignof(::pthread_cond_t *) != 0) { + handle_runtime_error("unaligned cond"); + } ::pthread_cond_t *cond_ptr = (::pthread_cond_t *)malloc(sizeof(::pthread_cond_t)); if (::pthread_cond_init(cond_ptr, nullptr) != 0) @@ -72,8 +75,9 @@ ::pthread_cond_t *shim::bionic::cond_static_initializer(shim::bionic::atomic_uin } ::pthread_rwlock_t *bionic::rwlock_static_initializer(shim::bionic::atomic_uintptr_t *p, uintptr_t payload) { - // assert((uintptr_t)p % 8 == 0); - + if((uintptr_t)p % alignof(::pthread_rwlock_t *) != 0) { + handle_runtime_error("unaligned rwlock"); + } ::pthread_rwlock_t *rwlock_ptr = (::pthread_rwlock_t *)malloc(sizeof(::pthread_rwlock_t)); if (::pthread_rwlock_init(rwlock_ptr, nullptr) != 0) From 6fed0d29137eabb040066b843339af3c518808bb Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 25 Jan 2026 14:33:02 +0100 Subject: [PATCH 08/10] Remove pthread_once locking --- src/pthreads.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/pthreads.cpp b/src/pthreads.cpp index 6009319..1c9e5df 100644 --- a/src/pthreads.cpp +++ b/src/pthreads.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -482,11 +483,19 @@ void shim::pthread_cleanup_pop_impl(shim::bionic::pthread_cleanup_t *c, int exec } int shim::pthread_once(pthread_once_t *control, void (*routine)()) { - static std::recursive_mutex mutex; - std::unique_lock lock (mutex); - if (*control == 0) { - *control = 1; + auto acontrol = (std::atomic_int32_t*)(control); + int32_t c = 0; + if(atomic_compare_exchange_strong_explicit(acontrol, &c, 1, + std::memory_order_release, std::memory_order_acquire)) { routine(); + atomic_store_explicit(acontrol, 2, std::memory_order_release); + return 0; + } + if(c == 2) { + return 0; + } + while(atomic_load_explicit(acontrol, std::memory_order_acquire) == 1) { + std::this_thread::yield(); } return 0; } From edd58d202b47e72a0b88223f049a9b768617f3bc Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 25 Jan 2026 14:42:07 +0100 Subject: [PATCH 09/10] macOS stack_base is inverted --- src/pthreads.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pthreads.cpp b/src/pthreads.cpp index 1c9e5df..763be99 100644 --- a/src/pthreads.cpp +++ b/src/pthreads.cpp @@ -203,7 +203,7 @@ int shim::pthread_getattr_np(pthread_t th, pthread_attr_t* attr) { attr->sched_priority = hparam.sched_priority; void* stackaddr = pthread_get_stackaddr_np(th); size_t stacksize = pthread_get_stacksize_np(th); - attr->stack_base = stackaddr; + attr->stack_base = (void*)((intptr_t)stackaddr - stacksize); attr->stack_size = stacksize; #else ::pthread_attr_t hostattr; From 8de7d9bc61b5006d5405cea4f9bf0de7a69eb8d4 Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sun, 25 Jan 2026 17:59:07 +0100 Subject: [PATCH 10/10] add static_asserts to guard against api misuse --- src/pthreads.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/pthreads.h b/src/pthreads.h index ccdc07e..ab1a023 100644 --- a/src/pthreads.h +++ b/src/pthreads.h @@ -33,9 +33,13 @@ namespace shim { template atomic_uintptr_t *get_payload_pointer(T *p) { #if defined(__LP64__) uintptr_t v = (uintptr_t)p; - v += sizeof(int32_t); // leave the first 4 bytes untouched - v += alignof(atomic_uintptr_t) - 1; - v &= -alignof(atomic_uintptr_t); + // leave the first 4 bytes untouched (for init value) + static constexpr size_t header_size = sizeof(int32_t); + static constexpr size_t pointer_alignment = alignof(atomic_uintptr_t); + static constexpr size_t max_header_size = header_size + pointer_alignment - 1; + v += max_header_size; + v &= -pointer_alignment; + static_assert(max_header_size + sizeof(atomic_uintptr_t) < sizeof(*p), "Not enough space for payload pointer"); p = (T *)v; #else static_assert(alignof(atomic_uintptr_t) == alignof(T));