frusa 0.1.3

A system allocator with reclaim.
Documentation
use core::sync::atomic::*;

const READER: u32 = 2;
const WRITER: u32 = 1;

const MAX_LOCK_VALUE: u32 = u32::MAX / 2;

pub const fn rwlock_new() -> AtomicU32 {
    AtomicU32::new(0)
}

pub fn try_read_lock(lock: &AtomicU32) -> bool {
    let val = lock.fetch_add(READER, Ordering::SeqCst);
    if val > MAX_LOCK_VALUE || val & WRITER != 0 {
        lock.fetch_sub(READER, Ordering::SeqCst);
        false
    } else {
        true
    }
}

pub fn read_lock(lock: &AtomicU32) {
    loop {
        if try_read_lock(lock) {
            return;
        }
        core::hint::spin_loop();
    }
}

pub fn read_unlock(lock: &AtomicU32) {
    lock.fetch_sub(READER, Ordering::SeqCst);
}

pub fn single_write_lock(lock: &AtomicU32) -> bool {
    let mut val = lock.fetch_or(WRITER, Ordering::SeqCst);
    if val & WRITER != 0 {
        return false;
    }

    while val != WRITER {
        core::hint::spin_loop();
        val = lock.load(Ordering::Relaxed);
    }

    true
}

pub fn write_unlock(lock: &AtomicU32) {
    let val = lock.fetch_xor(WRITER, Ordering::SeqCst);
    assert_eq!(val & WRITER, WRITER);
}