1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 #include <stdlib.h>
7 #include "lock/zm_mcsp.h"
8 
zm_mcsp_init(zm_mcsp_t * L)9 int zm_mcsp_init(zm_mcsp_t *L) {
10     zm_mcs_init(&L->high_p);
11     L->go_straight = 0;
12     L->low_p_acq = 0;
13     zm_ticket_init(&L->filter);
14     zm_mcs_init(&L->low_p);
15     return 0;
16 }
17 
zm_mcsp_acquire(zm_mcsp_t * L)18 int zm_mcsp_acquire(zm_mcsp_t *L) {
19     zm_mcs_acquire(L->high_p);
20     if (!L->go_straight) {
21         zm_ticket_acquire(&L->filter);
22         L->go_straight = 1;
23     }
24     return 0;
25 }
26 
zm_mcsp_tryacq(zm_mcsp_t * L,int * success)27 int zm_mcsp_tryacq(zm_mcsp_t *L, int *success) {
28     zm_mcs_tryacq(L->high_p, success);
29     if (success) {
30         if (!L->go_straight) {
31             zm_ticket_tryacq(&L->filter, success);
32             if (success)
33                 L->go_straight = 1;
34             else
35                 zm_mcs_release(L->high_p);
36         }
37     }
38     return 0;
39 }
40 
zm_mcsp_acquire_low(zm_mcsp_t * L)41 int zm_mcsp_acquire_low(zm_mcsp_t *L) {
42     zm_mcs_acquire(L->low_p);
43     zm_ticket_acquire(&L->filter);
44     L->low_p_acq = 1;
45     return 0;
46 }
47 
zm_mcsp_tryacq_low(zm_mcsp_t * L,int * success)48 int zm_mcsp_tryacq_low(zm_mcsp_t *L, int *success) {
49     zm_mcs_tryacq(L->low_p, success);
50     if (success) {
51         zm_ticket_tryacq(&L->filter, success);
52         if (success)
53                 L->low_p_acq = 1;
54         else
55                 zm_mcs_release(L->low_p);
56     }
57     return 0;
58 }
59 
zm_mcsp_release(zm_mcsp_t * L)60 int zm_mcsp_release(zm_mcsp_t *L) {
61     if (!L->low_p_acq) {
62         if (zm_mcs_nowaiters(L->high_p)) {
63             L->go_straight = 0;
64             zm_ticket_release(&L->filter);
65         }
66         zm_mcs_release(L->high_p);
67     } else {
68         L->low_p_acq = 0;
69         zm_ticket_release(&L->filter);
70         zm_mcs_release(L->low_p);
71     }
72     return 0;
73 }
74 
zm_mcsp_acquire_c(zm_mcsp_t * L,zm_mcs_qnode_t * I)75 int zm_mcsp_acquire_c(zm_mcsp_t *L, zm_mcs_qnode_t* I) {
76     zm_mcs_acquire_c(L->high_p, I);
77     if (!L->go_straight) {
78         zm_ticket_acquire(&L->filter);
79         L->go_straight = 1;
80     }
81     return 0;
82 }
83 
zm_mcsp_acquire_low_c(zm_mcsp_t * L,zm_mcs_qnode_t * I)84 int zm_mcsp_acquire_low_c(zm_mcsp_t *L, zm_mcs_qnode_t* I) {
85     zm_mcs_acquire_c(L->low_p, I);
86     zm_ticket_acquire(&L->filter);
87     L->low_p_acq = 1;
88     return 0;
89 }
90 
zm_mcsp_release_c(zm_mcsp_t * L,zm_mcs_qnode_t * I)91 int zm_mcsp_release_c(zm_mcsp_t *L, zm_mcs_qnode_t *I) {
92     if (!L->low_p_acq) {
93         if (zm_mcs_nowaiters_c(L->high_p, I)) {
94             L->go_straight = 0;
95             zm_ticket_release(&L->filter);
96         }
97         zm_mcs_release_c(L->high_p, I);
98     } else {
99         L->low_p_acq = 0;
100         zm_ticket_release(&L->filter);
101         zm_mcs_release_c(L->low_p, I);
102     }
103     return 0;
104 }
105 
zm_mcsp_destroy(zm_mcsp_t * L)106 int zm_mcsp_destroy(zm_mcsp_t *L) {
107     zm_mcs_destroy(&L->high_p);
108     zm_ticket_destroy(&L->filter);
109     zm_mcs_destroy(&L->low_p);
110     return 0;
111 }
112