summaryrefslogtreecommitdiff
path: root/lib/libc/internal/include/atomic.h
blob: d40c1eae9d3435746e8857830ef938b648ab0b69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#ifndef __LIBC_ATOMIC_H
#define __LIBC_ATOMIC_H

#include <libc/futex.h>
#include <sched.h>
#include <stdatomic.h>
#include <unistd.h>

#define LIBC_LOCK(__lock)   __libc_lock(&((__lock)))
#define LIBC_UNLOCK(__lock) __libc_unlock(&((__lock)))

__attribute__((__always_inline__)) __inline void __libc_unlock(volatile atomic_flag *lock)
{
	atomic_flag_clear_explicit(lock, memory_order_release);
	__futex_wake((volatile int *)lock, 1);
}

__attribute__((__always_inline__)) __inline void __libc_lock(volatile atomic_flag *lock)
{
	if (atomic_flag_test_and_set_explicit(lock, memory_order_acquire) == 0)
		return;

	while (1) {
		__futex_wait((volatile int *)lock, 1);

		if (atomic_flag_test_and_set_explicit(lock, memory_order_acquire) == 0)
			return;

		sched_yield();
	}
}

#endif