2
* QemuLockCnt implementation
4
* Copyright Red Hat, Inc. 2017
7
* Paolo Bonzini <pbonzini@redhat.com>
10
#include "qemu/thread.h"
11
#include "qemu/atomic.h"
15
#include "qemu/futex.h"
17
/* On Linux, bits 0-1 are a futex-based lock, bits 2-31 are the counter.
18
* For the mutex algorithm see Ulrich Drepper's "Futexes Are Tricky" (ok,
19
* this is not the most relaxing citation I could make...). It is similar
20
* to mutex2 in the paper.
23
#define QEMU_LOCKCNT_STATE_MASK 3
24
#define QEMU_LOCKCNT_STATE_FREE 0 /* free, uncontended */
25
#define QEMU_LOCKCNT_STATE_LOCKED 1 /* locked, uncontended */
26
#define QEMU_LOCKCNT_STATE_WAITING 2 /* locked, contended */
28
#define QEMU_LOCKCNT_COUNT_STEP 4
29
#define QEMU_LOCKCNT_COUNT_SHIFT 2
31
void qemu_lockcnt_init(QemuLockCnt *lockcnt)
36
void qemu_lockcnt_destroy(QemuLockCnt *lockcnt)
40
/* *val is the current value of lockcnt->count.
42
* If the lock is free, try a cmpxchg from *val to new_if_free; return
43
* true and set *val to the old value found by the cmpxchg in
46
* If the lock is taken, wait for it to be released and return false
47
* *without trying again to take the lock*. Again, set *val to the
48
* new value of lockcnt->count.
50
* If *waited is true on return, new_if_free's bottom two bits must not
51
* be QEMU_LOCKCNT_STATE_LOCKED on subsequent calls, because the caller
52
* does not know if there are other waiters. Furthermore, after *waited
53
* is set the caller has effectively acquired the lock. If it returns
54
* with the lock not taken, it must wake another futex waiter.
56
static bool qemu_lockcnt_cmpxchg_or_wait(QemuLockCnt *lockcnt, int *val,
57
int new_if_free, bool *waited)
59
/* Fast path for when the lock is free. */
60
if ((*val & QEMU_LOCKCNT_STATE_MASK) == QEMU_LOCKCNT_STATE_FREE) {
63
trace_lockcnt_fast_path_attempt(lockcnt, expected, new_if_free);
64
*val = qatomic_cmpxchg(&lockcnt->count, expected, new_if_free);
65
if (*val == expected) {
66
trace_lockcnt_fast_path_success(lockcnt, expected, new_if_free);
72
/* The slow path moves from locked to waiting if necessary, then
73
* does a futex wait. Both steps can be repeated ad nauseam,
74
* only getting out of the loop if we can have another shot at the
75
* fast path. Once we can, get out to compute the new destination
76
* value for the fast path.
78
while ((*val & QEMU_LOCKCNT_STATE_MASK) != QEMU_LOCKCNT_STATE_FREE) {
79
if ((*val & QEMU_LOCKCNT_STATE_MASK) == QEMU_LOCKCNT_STATE_LOCKED) {
81
int new = expected - QEMU_LOCKCNT_STATE_LOCKED + QEMU_LOCKCNT_STATE_WAITING;
83
trace_lockcnt_futex_wait_prepare(lockcnt, expected, new);
84
*val = qatomic_cmpxchg(&lockcnt->count, expected, new);
85
if (*val == expected) {
91
if ((*val & QEMU_LOCKCNT_STATE_MASK) == QEMU_LOCKCNT_STATE_WAITING) {
93
trace_lockcnt_futex_wait(lockcnt, *val);
94
qemu_futex_wait(&lockcnt->count, *val);
95
*val = qatomic_read(&lockcnt->count);
96
trace_lockcnt_futex_wait_resume(lockcnt, *val);
105
static void lockcnt_wake(QemuLockCnt *lockcnt)
107
trace_lockcnt_futex_wake(lockcnt);
108
qemu_futex_wake(&lockcnt->count, 1);
111
void qemu_lockcnt_inc(QemuLockCnt *lockcnt)
113
int val = qatomic_read(&lockcnt->count);
117
if (val >= QEMU_LOCKCNT_COUNT_STEP) {
119
val = qatomic_cmpxchg(&lockcnt->count, val,
120
val + QEMU_LOCKCNT_COUNT_STEP);
121
if (val == expected) {
125
/* The fast path is (0, unlocked)->(1, unlocked). */
126
if (qemu_lockcnt_cmpxchg_or_wait(lockcnt, &val, QEMU_LOCKCNT_COUNT_STEP,
133
/* If we were woken by another thread, we should also wake one because
134
* we are effectively releasing the lock that was given to us. This is
135
* the case where qemu_lockcnt_lock would leave QEMU_LOCKCNT_STATE_WAITING
136
* in the low bits, and qemu_lockcnt_inc_and_unlock would find it and
140
lockcnt_wake(lockcnt);
144
void qemu_lockcnt_dec(QemuLockCnt *lockcnt)
146
qatomic_sub(&lockcnt->count, QEMU_LOCKCNT_COUNT_STEP);
149
/* Decrement a counter, and return locked if it is decremented to zero.
150
* If the function returns true, it is impossible for the counter to
151
* become nonzero until the next qemu_lockcnt_unlock.
153
bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt)
155
int val = qatomic_read(&lockcnt->count);
156
int locked_state = QEMU_LOCKCNT_STATE_LOCKED;
160
if (val >= 2 * QEMU_LOCKCNT_COUNT_STEP) {
162
val = qatomic_cmpxchg(&lockcnt->count, val,
163
val - QEMU_LOCKCNT_COUNT_STEP);
164
if (val == expected) {
168
/* If count is going 1->0, take the lock. The fast path is
169
* (1, unlocked)->(0, locked) or (1, unlocked)->(0, waiting).
171
if (qemu_lockcnt_cmpxchg_or_wait(lockcnt, &val, locked_state, &waited)) {
176
/* At this point we do not know if there are more waiters. Assume
179
locked_state = QEMU_LOCKCNT_STATE_WAITING;
184
/* If we were woken by another thread, but we're returning in unlocked
185
* state, we should also wake a thread because we are effectively
186
* releasing the lock that was given to us. This is the case where
187
* qemu_lockcnt_lock would leave QEMU_LOCKCNT_STATE_WAITING in the low
188
* bits, and qemu_lockcnt_unlock would find it and wake someone.
191
lockcnt_wake(lockcnt);
196
/* If the counter is one, decrement it and return locked. Otherwise do
199
* If the function returns true, it is impossible for the counter to
200
* become nonzero until the next qemu_lockcnt_unlock.
202
bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt)
204
int val = qatomic_read(&lockcnt->count);
205
int locked_state = QEMU_LOCKCNT_STATE_LOCKED;
208
while (val < 2 * QEMU_LOCKCNT_COUNT_STEP) {
209
/* If count is going 1->0, take the lock. The fast path is
210
* (1, unlocked)->(0, locked) or (1, unlocked)->(0, waiting).
212
if (qemu_lockcnt_cmpxchg_or_wait(lockcnt, &val, locked_state, &waited)) {
217
/* At this point we do not know if there are more waiters. Assume
220
locked_state = QEMU_LOCKCNT_STATE_WAITING;
224
/* If we were woken by another thread, but we're returning in unlocked
225
* state, we should also wake a thread because we are effectively
226
* releasing the lock that was given to us. This is the case where
227
* qemu_lockcnt_lock would leave QEMU_LOCKCNT_STATE_WAITING in the low
228
* bits, and qemu_lockcnt_inc_and_unlock would find it and wake someone.
231
lockcnt_wake(lockcnt);
236
void qemu_lockcnt_lock(QemuLockCnt *lockcnt)
238
int val = qatomic_read(&lockcnt->count);
239
int step = QEMU_LOCKCNT_STATE_LOCKED;
242
/* The third argument is only used if the low bits of val are 0
243
* (QEMU_LOCKCNT_STATE_FREE), so just blindly mix in the desired
246
while (!qemu_lockcnt_cmpxchg_or_wait(lockcnt, &val, val + step, &waited)) {
248
/* At this point we do not know if there are more waiters. Assume
251
step = QEMU_LOCKCNT_STATE_WAITING;
256
void qemu_lockcnt_inc_and_unlock(QemuLockCnt *lockcnt)
258
int expected, new, val;
260
val = qatomic_read(&lockcnt->count);
263
new = (val + QEMU_LOCKCNT_COUNT_STEP) & ~QEMU_LOCKCNT_STATE_MASK;
264
trace_lockcnt_unlock_attempt(lockcnt, val, new);
265
val = qatomic_cmpxchg(&lockcnt->count, val, new);
266
} while (val != expected);
268
trace_lockcnt_unlock_success(lockcnt, val, new);
269
if (val & QEMU_LOCKCNT_STATE_WAITING) {
270
lockcnt_wake(lockcnt);
274
void qemu_lockcnt_unlock(QemuLockCnt *lockcnt)
276
int expected, new, val;
278
val = qatomic_read(&lockcnt->count);
281
new = val & ~QEMU_LOCKCNT_STATE_MASK;
282
trace_lockcnt_unlock_attempt(lockcnt, val, new);
283
val = qatomic_cmpxchg(&lockcnt->count, val, new);
284
} while (val != expected);
286
trace_lockcnt_unlock_success(lockcnt, val, new);
287
if (val & QEMU_LOCKCNT_STATE_WAITING) {
288
lockcnt_wake(lockcnt);
292
unsigned qemu_lockcnt_count(QemuLockCnt *lockcnt)
294
return qatomic_read(&lockcnt->count) >> QEMU_LOCKCNT_COUNT_SHIFT;
297
void qemu_lockcnt_init(QemuLockCnt *lockcnt)
299
qemu_mutex_init(&lockcnt->mutex);
303
void qemu_lockcnt_destroy(QemuLockCnt *lockcnt)
305
qemu_mutex_destroy(&lockcnt->mutex);
308
void qemu_lockcnt_inc(QemuLockCnt *lockcnt)
312
old = qatomic_read(&lockcnt->count);
314
qemu_lockcnt_lock(lockcnt);
315
qemu_lockcnt_inc_and_unlock(lockcnt);
318
if (qatomic_cmpxchg(&lockcnt->count, old, old + 1) == old) {
325
void qemu_lockcnt_dec(QemuLockCnt *lockcnt)
327
qatomic_dec(&lockcnt->count);
330
/* Decrement a counter, and return locked if it is decremented to zero.
331
* It is impossible for the counter to become nonzero while the mutex
334
bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt)
336
int val = qatomic_read(&lockcnt->count);
338
int old = qatomic_cmpxchg(&lockcnt->count, val, val - 1);
347
qemu_lockcnt_lock(lockcnt);
348
if (qatomic_fetch_dec(&lockcnt->count) == 1) {
352
qemu_lockcnt_unlock(lockcnt);
356
/* Decrement a counter and return locked if it is decremented to zero.
357
* Otherwise do nothing.
359
* It is impossible for the counter to become nonzero while the mutex
362
bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt)
364
/* No need for acquire semantics if we return false. */
365
int val = qatomic_read(&lockcnt->count);
370
qemu_lockcnt_lock(lockcnt);
371
if (qatomic_fetch_dec(&lockcnt->count) == 1) {
375
qemu_lockcnt_inc_and_unlock(lockcnt);
379
void qemu_lockcnt_lock(QemuLockCnt *lockcnt)
381
qemu_mutex_lock(&lockcnt->mutex);
384
void qemu_lockcnt_inc_and_unlock(QemuLockCnt *lockcnt)
386
qatomic_inc(&lockcnt->count);
387
qemu_mutex_unlock(&lockcnt->mutex);
390
void qemu_lockcnt_unlock(QemuLockCnt *lockcnt)
392
qemu_mutex_unlock(&lockcnt->mutex);
395
unsigned qemu_lockcnt_count(QemuLockCnt *lockcnt)
397
return qatomic_read(&lockcnt->count);