2 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch.
3 * Distributed under the terms of the MIT License.
12 #include <user_thread.h>
15 typedef struct rw_lock_waiter
{
16 rw_lock_waiter
* next
;
23 rw_lock_wait(rw_lock
*lock
, bool writer
)
25 rw_lock_waiter waiter
;
26 waiter
.thread
= find_thread(NULL
);
28 waiter
.writer
= writer
;
30 if (lock
->waiters
!= NULL
)
31 lock
->last_waiter
->next
= &waiter
;
33 lock
->waiters
= &waiter
;
35 lock
->last_waiter
= &waiter
;
37 // the rw_lock is locked when entering, release it before blocking
38 get_user_thread()->wait_status
= 1;
39 mutex_unlock(&lock
->lock
);
43 result
= _kern_block_thread(0, 0);
44 } while (result
== B_INTERRUPTED
);
46 // and lock it again before returning
47 mutex_lock(&lock
->lock
);
53 rw_lock_unblock(rw_lock
*lock
)
55 // this is called locked
56 if (lock
->holder
>= 0)
59 rw_lock_waiter
*waiter
= lock
->waiters
;
64 if (lock
->reader_count
> 0)
67 lock
->waiters
= waiter
->next
;
68 lock
->holder
= waiter
->thread
;
69 _kern_unblock_thread(waiter
->thread
, B_OK
);
73 while (waiter
!= NULL
&& !waiter
->writer
) {
75 lock
->waiters
= waiter
->next
;
76 _kern_unblock_thread(waiter
->thread
, B_OK
);
77 waiter
= lock
->waiters
;
83 __rw_lock_init(rw_lock
*lock
, const char *name
)
85 rw_lock_init_etc(lock
, name
, 0);
90 __rw_lock_init_etc(rw_lock
*lock
, const char *name
, uint32 flags
)
94 lock
->reader_count
= 0;
95 lock
->writer_count
= 0;
96 lock
->owner_count
= 0;
97 mutex_init_etc(&lock
->lock
, name
, flags
);
102 __rw_lock_destroy(rw_lock
*lock
)
104 mutex_lock(&lock
->lock
);
106 rw_lock_waiter
*waiter
= lock
->waiters
;
107 while (waiter
!= NULL
) {
108 _kern_unblock_thread(waiter
->thread
, B_ERROR
);
109 waiter
= waiter
->next
;
112 mutex_destroy(&lock
->lock
);
117 __rw_lock_read_lock(rw_lock
*lock
)
119 MutexLocker
locker(lock
->lock
);
121 if (lock
->writer_count
== 0) {
122 lock
->reader_count
++;
126 if (lock
->holder
== find_thread(NULL
)) {
131 return rw_lock_wait(lock
, false);
136 __rw_lock_read_unlock(rw_lock
*lock
)
138 MutexLocker
locker(lock
->lock
);
140 if (lock
->holder
== find_thread(NULL
)) {
141 if (--lock
->owner_count
> 0)
144 // this originally has been a write lock
145 lock
->writer_count
--;
148 rw_lock_unblock(lock
);
152 if (lock
->reader_count
<= 0) {
153 debugger("rw_lock not read locked");
157 lock
->reader_count
--;
158 rw_lock_unblock(lock
);
164 __rw_lock_write_lock(rw_lock
*lock
)
166 MutexLocker
locker(lock
->lock
);
168 if (lock
->reader_count
== 0 && lock
->writer_count
== 0) {
169 lock
->writer_count
++;
170 lock
->holder
= find_thread(NULL
);
171 lock
->owner_count
= 1;
175 if (lock
->holder
== find_thread(NULL
)) {
180 lock
->writer_count
++;
182 status_t result
= rw_lock_wait(lock
, true);
186 if (lock
->holder
!= find_thread(NULL
)) {
187 debugger("write locked but holder not set");
191 lock
->owner_count
= 1;
197 __rw_lock_write_unlock(rw_lock
*lock
)
199 MutexLocker
locker(lock
->lock
);
201 if (lock
->holder
!= find_thread(NULL
)) {
202 debugger("rw_lock not write locked");
206 if (--lock
->owner_count
> 0)
209 lock
->writer_count
--;
211 rw_lock_unblock(lock
);