Skip to content

Commit

Permalink
move lock code to atomic.h
Browse files Browse the repository at this point in the history
  • Loading branch information
daanx committed Jun 2, 2024
1 parent 0b3cd51 commit f93fb90
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 174 deletions.
91 changes: 91 additions & 0 deletions include/mimalloc/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -329,7 +334,9 @@ typedef _Atomic(uintptr_t) mi_atomic_guard_t;



// ----------------------------------------------------------------------
// Yield
// ----------------------------------------------------------------------
#if defined(__cplusplus)
#include <thread>
static inline void mi_atomic_yield(void) {
Expand Down Expand Up @@ -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 <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
17 changes: 0 additions & 17 deletions include/mimalloc/prim.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);


//-------------------------------------------------------------------
Expand Down
2 changes: 0 additions & 2 deletions include/mimalloc/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
// ------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
47 changes: 0 additions & 47 deletions src/prim/emscripten/prim.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <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
47 changes: 0 additions & 47 deletions src/prim/unix/prim.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <sys/mman.h> // mmap
Expand Down Expand Up @@ -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
41 changes: 0 additions & 41 deletions src/prim/wasi/prim.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <stdio.h> // fputs
Expand Down Expand Up @@ -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
19 changes: 0 additions & 19 deletions src/prim/windows/prim.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <stdio.h> // fputs, stderr

Expand Down Expand Up @@ -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
//----------------------------------------------------------------
Expand Down

0 comments on commit f93fb90

Please sign in to comment.