locks wip
This commit is contained in:
parent
a9bcab1b78
commit
32b82f4417
@ -35,7 +35,7 @@
|
||||
#define FIBER_STACK_SIZE MEGABYTE(4)
|
||||
|
||||
struct win32_mutex {
|
||||
volatile LONG state; /* Lower 30 bits = reader count, bit 30 = writer waiting, bit 31 = writer held */
|
||||
struct atomic_i32 v; /* Bits 0-30 = shared lock count, bit 30 = is exclusive lock pending, bit 31 = is exclusive locked */
|
||||
struct win32_mutex *next_free;
|
||||
};
|
||||
|
||||
@ -2552,20 +2552,23 @@ struct sys_lock sys_mutex_lock_e(struct sys_mutex *mutex)
|
||||
{
|
||||
__prof;
|
||||
struct win32_mutex *m = (struct win32_mutex *)mutex;
|
||||
{
|
||||
while (true) {
|
||||
//LONG expected = 0;
|
||||
if (InterlockedCompareExchange(&m->state, 0x80000000, 0) == 0) {
|
||||
break; /* Acquired exclusive */
|
||||
} else {
|
||||
/* Set writer pending */
|
||||
LONG old;
|
||||
do {
|
||||
old = m->state;
|
||||
if (old & 0x40000000) break; /* Already pending */
|
||||
} while (InterlockedCompareExchange(&m->state, old | 0x40000000, old) != old);
|
||||
sys_wait((void *)&m->state, (void *)&old, sizeof(old));
|
||||
b32 locked = false;
|
||||
while (!locked) {
|
||||
i32 v = atomic_i32_fetch_test_set(&m->v, 0, (1 << 31));
|
||||
if (v == 0) {
|
||||
locked = true;
|
||||
} else {
|
||||
/* Set pending */
|
||||
if ((v & (1 << 30)) == 0) {
|
||||
i32 old = atomic_i32_fetch_test_set(&m->v, v | (1 << 30), v);
|
||||
while (old != v && (old & (1 << 30)) == 0) {
|
||||
v = old;
|
||||
old = atomic_i32_fetch_test_set(&m->v, v | (1 << 30), v);
|
||||
}
|
||||
v = old;
|
||||
}
|
||||
/* Wait for change */
|
||||
sys_wait(&m->v, &v, 4);
|
||||
}
|
||||
}
|
||||
struct sys_lock lock = ZI;
|
||||
@ -2578,18 +2581,19 @@ struct sys_lock sys_mutex_lock_s(struct sys_mutex *mutex)
|
||||
{
|
||||
__prof;
|
||||
struct win32_mutex *m = (struct win32_mutex *)mutex;
|
||||
{
|
||||
while (true) {
|
||||
LONG old = m->state;
|
||||
/* If writer not held or pending */
|
||||
if ((old & 0xC0000000) == 0) {
|
||||
if (InterlockedCompareExchange(&m->state, old + 1, old) == old) {
|
||||
break; /* Acquired shared */
|
||||
}
|
||||
} else {
|
||||
sys_wait((void *)&m->state, &old, sizeof(old));
|
||||
b32 locked = false;
|
||||
while (!locked) {
|
||||
i32 v = atomic_i32_fetch(&m->v);
|
||||
while (!locked && (v & 0xC0000000) == 0) {
|
||||
/* Increment shared lock count */
|
||||
i32 old = atomic_i32_fetch_test_set(&m->v, v, v + 1);
|
||||
if (v == old) {
|
||||
locked = true;
|
||||
}
|
||||
}
|
||||
if (!locked) {
|
||||
sys_wait(&m->v, &v, 4);
|
||||
}
|
||||
}
|
||||
struct sys_lock lock = ZI;
|
||||
lock.mutex = mutex;
|
||||
@ -2601,15 +2605,11 @@ void sys_mutex_unlock(struct sys_lock *lock)
|
||||
__prof;
|
||||
struct win32_mutex *m = (struct win32_mutex *)lock->mutex;
|
||||
if (lock->exclusive) {
|
||||
//LONG old = m->state;
|
||||
InterlockedExchange(&m->state, 0); /* Clear all bits */
|
||||
sys_wake_all((void *)&m->state);
|
||||
atomic_i32_fetch_set(&m->v, 0);
|
||||
} else {
|
||||
LONG old = InterlockedDecrement(&m->state);
|
||||
if (old == 1) {
|
||||
sys_wake_all((void *)&m->state);
|
||||
}
|
||||
atomic_i32_fetch_add(&m->v, -1);
|
||||
}
|
||||
sys_wake_all(&m->v);
|
||||
MEMZERO_STRUCT(lock);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user