sweep through entire page table to free up intermediate tables
[lunaix-os.git] / lunaix-os / kernel / ds / rwlock.c
1 #include <lunaix/ds/rwlock.h>
2 #include <lunaix/spike.h>
3
4 void
5 rwlock_init(rwlock_t* rwlock)
6 {
7     waitq_init(&rwlock->waiting_readers);
8     waitq_init(&rwlock->waiting_writers);
9     atomic_init(&rwlock->readers, 0);
10     atomic_flag_clear(&rwlock->writer);
11 }
12
13 void
14 rwlock_begin_read(rwlock_t* rwlock)
15 {
16     while (atomic_flag_test_and_set(&rwlock->writer)) {
17         pwait(&rwlock->waiting_readers);
18     }
19     atomic_fetch_add(&rwlock->readers, 1);
20     atomic_flag_clear(&rwlock->writer);
21     pwake_all(&rwlock->waiting_readers);
22 }
23
24 void
25 rwlock_end_read(rwlock_t* rwlock)
26 {
27     assert(atomic_load(&rwlock->readers) > 0);
28     atomic_fetch_sub(&rwlock->readers, 1);
29
30     if (!atomic_load(&rwlock->readers)) {
31         pwake_one(&rwlock->waiting_writers);
32     }
33 }
34
35 void
36 rwlock_begin_write(rwlock_t* rwlock)
37 {
38     // first, acquire writer lock, prevent any incoming readers
39     while (atomic_flag_test_and_set(&rwlock->writer)) {
40         pwait(&rwlock->waiting_writers);
41     }
42
43     // then, wait for reader finish the read.
44     while (atomic_load(&rwlock->readers)) {
45         pwait(&rwlock->waiting_writers);
46     }
47 }
48
49 void
50 rwlock_end_write(rwlock_t* rwlock)
51 {
52     atomic_flag_clear(&rwlock->writer);
53     if (waitq_empty(&rwlock->waiting_writers)) {
54         pwake_all(&rwlock->waiting_readers);
55     } else {
56         pwake_one(&rwlock->waiting_writers);
57     }
58 }