mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-04 14:39:31 +03:00
move lock code to atomic.h
This commit is contained in:
parent
0b3cd51249
commit
f93fb900b7
8 changed files with 92 additions and 174 deletions
|
@ -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);
|
return (intptr_t)mi_atomic_addi(p, -sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Once and Guard
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
typedef _Atomic(uintptr_t) mi_atomic_once_t;
|
typedef _Atomic(uintptr_t) mi_atomic_once_t;
|
||||||
|
|
||||||
// Returns true only on the first invocation
|
// Returns true only on the first invocation
|
||||||
|
@ -329,7 +334,9 @@ typedef _Atomic(uintptr_t) mi_atomic_guard_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
// Yield
|
// Yield
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
#include <thread>
|
#include <thread>
|
||||||
static inline void mi_atomic_yield(void) {
|
static inline void mi_atomic_yield(void) {
|
||||||
|
@ -393,4 +400,88 @@ static inline void mi_atomic_yield(void) {
|
||||||
#endif
|
#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 <mutex>
|
||||||
|
#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
|
#endif // __MIMALLOC_ATOMIC_H
|
||||||
|
|
|
@ -114,23 +114,6 @@ void _mi_prim_thread_done_auto_done(void);
|
||||||
// Called when the default heap for a thread changes
|
// Called when the default heap for a thread changes
|
||||||
void _mi_prim_thread_associate_default_heap(mi_heap_t* heap);
|
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);
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|
|
@ -612,8 +612,6 @@ struct mi_subproc_s {
|
||||||
mi_memid_t memid; // provenance
|
mi_memid_t memid; // provenance
|
||||||
};
|
};
|
||||||
|
|
||||||
mi_subproc_t* mi_subproc_from_id(mi_subproc_id_t subproc_id);
|
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// Thread Local data
|
// Thread Local data
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
|
@ -193,7 +193,7 @@ mi_subproc_id_t mi_subproc_new(void) {
|
||||||
return subproc;
|
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);
|
return (subproc_id == NULL ? &mi_subproc_default : (mi_subproc_t*)subproc_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -242,50 +242,3 @@ void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) {
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#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 <emscripten.h>
|
|
||||||
|
|
||||||
// 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
|
|
|
@ -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.h"
|
||||||
#include "mimalloc/internal.h"
|
#include "mimalloc/internal.h"
|
||||||
#include "mimalloc/atomic.h"
|
|
||||||
#include "mimalloc/prim.h"
|
#include "mimalloc/prim.h"
|
||||||
|
|
||||||
#include <sys/mman.h> // mmap
|
#include <sys/mman.h> // mmap
|
||||||
|
@ -880,49 +879,3 @@ void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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
|
|
||||||
|
|
|
@ -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.h"
|
||||||
#include "mimalloc/internal.h"
|
#include "mimalloc/internal.h"
|
||||||
#include "mimalloc/atomic.h"
|
|
||||||
#include "mimalloc/prim.h"
|
#include "mimalloc/prim.h"
|
||||||
|
|
||||||
#include <stdio.h> // fputs
|
#include <stdio.h> // fputs
|
||||||
|
@ -278,43 +277,3 @@ void _mi_prim_thread_done_auto_done(void) {
|
||||||
void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) {
|
void _mi_prim_thread_associate_default_heap(mi_heap_t* heap) {
|
||||||
MI_UNUSED(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
|
|
|
@ -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.h"
|
||||||
#include "mimalloc/internal.h"
|
#include "mimalloc/internal.h"
|
||||||
#include "mimalloc/atomic.h"
|
|
||||||
#include "mimalloc/prim.h"
|
#include "mimalloc/prim.h"
|
||||||
#include <stdio.h> // fputs, stderr
|
#include <stdio.h> // 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
|
// Random
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
Loading…
Add table
Reference in a new issue