diff --git a/include/mimalloc/atomic.h b/include/mimalloc/atomic.h index 2c313fdb..4e3250f9 100644 --- a/include/mimalloc/atomic.h +++ b/include/mimalloc/atomic.h @@ -309,6 +309,11 @@ static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub) { return (intptr_t)mi_atomic_addi(p, -sub); } + +// ---------------------------------------------------------------------- +// Once and Guard +// ---------------------------------------------------------------------- + typedef _Atomic(uintptr_t) mi_atomic_once_t; // Returns true only on the first invocation @@ -329,7 +334,9 @@ typedef _Atomic(uintptr_t) mi_atomic_guard_t; +// ---------------------------------------------------------------------- // Yield +// ---------------------------------------------------------------------- #if defined(__cplusplus) #include static inline void mi_atomic_yield(void) { @@ -393,4 +400,88 @@ static inline void mi_atomic_yield(void) { #endif +// ---------------------------------------------------------------------- +// Locks are only used for abandoned segment visiting +// ---------------------------------------------------------------------- +#if defined(_WIN32) + +#define mi_lock_t CRITICAL_SECTION + +static inline bool _mi_prim_lock(mi_lock_t* lock) { + EnterCriticalSection(lock); + return true; +} + +static inline bool _mi_prim_try_lock(mi_lock_t* lock) { + return TryEnterCriticalSection(lock); +} + +static inline void _mi_prim_unlock(mi_lock_t* lock) { + LeaveCriticalSection(lock); +} + + +#elif defined(MI_USE_PTHREADS) + +#define mi_lock_t pthread_mutex_t + +static inline bool _mi_prim_lock(mi_lock_t* lock) { + return (pthread_mutex_lock(lock) == 0); +} + +static inline bool _mi_prim_try_lock(mi_lock_t* lock) { + return (pthread_mutex_trylock(lock) == 0); +} + +static inline void _mi_prim_unlock(mi_lock_t* lock) { + pthread_mutex_unlock(lock); +} + +#elif defined(__cplusplus) + +#include +#define mi_lock_t std::mutex + +static inline bool _mi_prim_lock(mi_lock_t* lock) { + lock->lock(); + return true; +} + +static inline bool _mi_prim_try_lock(mi_lock_t* lock) { + return (lock->try_lock(); +} + +static inline void _mi_prim_unlock(mi_lock_t* lock) { + lock->unlock(); +} + +#else + +// fall back to poor man's locks. +// this should only be the case in a single-threaded environment (like __wasi__) + +#define mi_lock_t _Atomic(uintptr_t) + +static inline bool _mi_prim_try_lock(mi_lock_t* lock) { + uintptr_t expected = 0; + return mi_atomic_cas_strong_acq_rel(lock, &expected, (uintptr_t)1); +} + +static inline bool _mi_prim_lock(mi_lock_t* lock) { + for (int i = 0; i < 1000; i++) { // for at most 1000 tries? + if (_mi_prim_try_lock(lock)) return true; + mi_atomic_yield(); + } + return true; +} + +static inline void _mi_prim_unlock(mi_lock_t* lock) { + mi_atomic_store_release(lock, (uintptr_t)0); +} + +#endif + + + + #endif // __MIMALLOC_ATOMIC_H diff --git a/include/mimalloc/prim.h b/include/mimalloc/prim.h index ba305dc1..640c966f 100644 --- a/include/mimalloc/prim.h +++ b/include/mimalloc/prim.h @@ -114,23 +114,6 @@ void _mi_prim_thread_done_auto_done(void); // Called when the default heap for a thread changes void _mi_prim_thread_associate_default_heap(mi_heap_t* heap); -// Locks are only used if abandoned segment visiting is permitted -#if defined(_WIN32) -#define mi_lock_t CRITICAL_SECTION -#elif defined(MI_USE_PTHREADS) -#define mi_lock_t pthread_mutex_t -#else -#define mi_lock_t _Atomic(uintptr_t) -#endif - -// Take a lock (blocking). Return `true` on success. -bool _mi_prim_lock(mi_lock_t* lock); - -// Try to take lock and return `true` if successful. -bool _mi_prim_try_lock(mi_lock_t* lock); - -// Release a lock. -void _mi_prim_unlock(mi_lock_t* lock); //------------------------------------------------------------------- diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index 6b90bf5d..f4ba6739 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -612,8 +612,6 @@ struct mi_subproc_s { mi_memid_t memid; // provenance }; -mi_subproc_t* mi_subproc_from_id(mi_subproc_id_t subproc_id); - // ------------------------------------------------------ // Thread Local data // ------------------------------------------------------ diff --git a/src/init.c b/src/init.c index 1922907b..01625891 100644 --- a/src/init.c +++ b/src/init.c @@ -193,7 +193,7 @@ mi_subproc_id_t mi_subproc_new(void) { return subproc; } -mi_subproc_t* mi_subproc_from_id(mi_subproc_id_t subproc_id) { +static mi_subproc_t* mi_subproc_from_id(mi_subproc_id_t subproc_id) { return (subproc_id == NULL ? &mi_subproc_default : (mi_subproc_t*)subproc_id); } diff --git a/src/prim/emscripten/prim.c b/src/prim/emscripten/prim.c index 6b5aa452..944c0cb4 100644 --- a/src/prim/emscripten/prim.c +++ b/src/prim/emscripten/prim.c @@ -242,50 +242,3 @@ void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { } #endif - -//---------------------------------------------------------------- -// Locks -//---------------------------------------------------------------- - -#if defined(MI_USE_PTHREADS) - -bool _mi_prim_lock(mi_lock_t* lock) { - return (pthread_mutex_lock(lock) == 0); -} - -bool _mi_prim_try_lock(mi_lock_t* lock) { - return (pthread_mutex_trylock(lock) == 0); -} - -void _mi_prim_unlock(mi_lock_t* lock) { - pthread_mutex_unlock(lock); -} - -#else - -#include - -// fall back to poor man's locks. -bool _mi_prim_lock(mi_lock_t* lock) { - for(int i = 0; i < 1000; i++) { // for at most 1 second? - if (_mi_prim_try_lock(lock)) return true; - if (i < 25) { - mi_atomic_yield(); // first yield a bit - } - else { - emscripten_sleep(1); // then sleep for 1ms intervals - } - } - return true; -} - -bool _mi_prim_try_lock(mi_lock_t* lock) { - uintptr_t expected = 0; - return mi_atomic_cas_strong_acq_rel(lock,&expected,(uintptr_t)1); -} - -void _mi_prim_unlock(mi_lock_t* lock) { - mi_atomic_store_release(lock,(uintptr_t)0); -} - -#endif \ No newline at end of file diff --git a/src/prim/unix/prim.c b/src/prim/unix/prim.c index 7935c1c6..93785b22 100644 --- a/src/prim/unix/prim.c +++ b/src/prim/unix/prim.c @@ -22,7 +22,6 @@ terms of the MIT license. A copy of the license can be found in the file #include "mimalloc.h" #include "mimalloc/internal.h" -#include "mimalloc/atomic.h" #include "mimalloc/prim.h" #include // mmap @@ -880,49 +879,3 @@ void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { } #endif - - -//---------------------------------------------------------------- -// Locks -//---------------------------------------------------------------- - -#if defined(MI_USE_PTHREADS) - -bool _mi_prim_lock(mi_lock_t* lock) { - return (pthread_mutex_lock(lock) == 0); -} - -bool _mi_prim_try_lock(mi_lock_t* lock) { - return (pthread_mutex_trylock(lock) == 0); -} - -void _mi_prim_unlock(mi_lock_t* lock) { - pthread_mutex_unlock(lock); -} - -#else - -// fall back to poor man's locks. -bool _mi_prim_lock(mi_lock_t* lock) { - for(int i = 0; i < 1000; i++) { // for at most 1 second? - if (_mi_prim_try_lock(lock)) return true; - if (i < 25) { - mi_atomic_yield(); // first yield a bit - } - else { - usleep(1000); // then sleep for 1ms intervals - } - } - return true; -} - -bool _mi_prim_try_lock(mi_lock_t* lock) { - uintptr_t expected = 0; - return mi_atomic_cas_strong_acq_rel(lock,&expected,(uintptr_t)1); -} - -void _mi_prim_unlock(mi_lock_t* lock) { - mi_atomic_store_release(lock,(uintptr_t)0); -} - -#endif diff --git a/src/prim/wasi/prim.c b/src/prim/wasi/prim.c index 3f3a2ea1..5d7a8132 100644 --- a/src/prim/wasi/prim.c +++ b/src/prim/wasi/prim.c @@ -9,7 +9,6 @@ terms of the MIT license. A copy of the license can be found in the file #include "mimalloc.h" #include "mimalloc/internal.h" -#include "mimalloc/atomic.h" #include "mimalloc/prim.h" #include // fputs @@ -278,43 +277,3 @@ void _mi_prim_thread_done_auto_done(void) { void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) { MI_UNUSED(heap); } - -//---------------------------------------------------------------- -// Locks -//---------------------------------------------------------------- - -#if defined(MI_USE_PTHREADS) - -bool _mi_prim_lock(mi_lock_t* lock) { - return (pthread_mutex_lock(lock) == 0); -} - -bool _mi_prim_try_lock(mi_lock_t* lock) { - return (pthread_mutex_trylock(lock) == 0); -} - -void _mi_prim_unlock(mi_lock_t* lock) { - pthread_mutex_unlock(lock); -} - -#else - -// fall back to poor man's locks. -bool _mi_prim_lock(mi_lock_t* lock) { - for(int i = 0; i < 1000; i++) { // for at most 1 second? - if (_mi_prim_try_lock(lock)) return true; - mi_atomic_yield(); // this should never happen as wasi is single threaded? - } - return true; -} - -bool _mi_prim_try_lock(mi_lock_t* lock) { - uintptr_t expected = 0; - return mi_atomic_cas_strong_acq_rel(lock,&expected,(uintptr_t)1); -} - -void _mi_prim_unlock(mi_lock_t* lock) { - mi_atomic_store_release(lock,(uintptr_t)0); -} - -#endif \ No newline at end of file diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index 760debb3..bd874f9b 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -9,7 +9,6 @@ terms of the MIT license. A copy of the license can be found in the file #include "mimalloc.h" #include "mimalloc/internal.h" -#include "mimalloc/atomic.h" #include "mimalloc/prim.h" #include // fputs, stderr @@ -563,24 +562,6 @@ bool _mi_prim_getenv(const char* name, char* result, size_t result_size) { } -//---------------------------------------------------------------- -// Locks -//---------------------------------------------------------------- - -bool _mi_prim_lock(mi_lock_t* lock) { - EnterCriticalSection(lock); - return true; -} - -bool _mi_prim_try_lock(mi_lock_t* lock) { - return TryEnterCriticalSection(lock); -} - -void _mi_prim_unlock(mi_lock_t* lock) { - LeaveCriticalSection(lock); -} - - //---------------------------------------------------------------- // Random //----------------------------------------------------------------