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