1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3 * See COPYRIGHT in top-level directory.
4 */
5
6 #include "lock/zm_ticket.h"
7
zm_ticket_init(zm_ticket_t * lock)8 int zm_ticket_init(zm_ticket_t *lock)
9 {
10 zm_atomic_store(&lock->next_ticket, 0, zm_memord_release);
11 zm_atomic_store(&lock->now_serving, 0, zm_memord_release);
12 return 0;
13 }
14
15 /* Atomically increment the nex_ticket counter and get my ticket.
16 Then spin on now_serving until it equals my ticket. */
zm_ticket_acquire(zm_ticket_t * lock)17 int zm_ticket_acquire(zm_ticket_t* lock) {
18 unsigned my_ticket = zm_atomic_fetch_add(&lock->next_ticket, 1, zm_memord_acq_rel);
19 while(zm_atomic_load(&lock->now_serving, zm_memord_acquire) != my_ticket)
20 ; /* SPIN */
21 return 0;
22 }
23
zm_ticket_tryacq(zm_ticket_t * lock,int * success)24 int zm_ticket_tryacq(zm_ticket_t* lock, int *success) {
25 int acquired = 0;
26 unsigned my_ticket = zm_atomic_load(&lock->next_ticket, zm_memord_acquire);
27 unsigned serving = zm_atomic_load(&lock->now_serving, zm_memord_acquire);
28 if (my_ticket == serving) {
29 if(zm_atomic_compare_exchange_strong(&lock->next_ticket,
30 &my_ticket,
31 my_ticket + 1,
32 zm_memord_acq_rel,
33 zm_memord_acquire))
34 acquired = 1;
35 }
36 *success = acquired;
37 return 0;
38 }
39
40 /* Release the lock */
zm_ticket_release(zm_ticket_t * lock)41 int zm_ticket_release(zm_ticket_t* lock) {
42 zm_atomic_fetch_add(&lock->now_serving, 1, zm_memord_release);
43 return 0;
44 }
45
zm_ticket_nowaiters(zm_ticket_t * lock)46 int zm_ticket_nowaiters(zm_ticket_t* lock) {
47 return (zm_atomic_load(&lock->next_ticket, zm_memord_acquire) -
48 zm_atomic_load(&lock->now_serving, zm_memord_acquire) == 1);
49 }
50
zm_ticket_destroy(zm_ticket_t * lock)51 int zm_ticket_destroy(zm_ticket_t *lock) {
52 return 0;
53 }
54
55