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_tlp.h"
8
9 /* The algorithm follows this logic
10
11 acquire()
12 lock(high_p)
13 do {
14 if(CAS(common, FREE, GRANTED);
15 break;
16 if (CAS(common, GRANTED, REQUEST {
17 while(common != GRANTED) ;
18 break;
}
19 } while (1)
20 unlock(high_p)
21
22 CS
23
24 release()
25 if(!CAS(common, REQUEST, GRANTED); //optimistic
26 common = FREE
27
28 acquire_low()
29 lock(low_p)
30 do {
31 while(common != FREE) ;
32 if(CAS(common, FREE, GRANTED);
33 break;
34 } whil (1)
35
36
37 CS
38
39 release_low()
40 if(!CAS(common, REQUEST, GRANTED); //optimistic
41 common = FREE;
42 unlock(low_p)
43 */
44
45 /* Helper functions */
46
47 #if (ZM_TLP_HIGH_P == ZM_TICKET)
48 #define zm_tlp_init_high_p(L) zm_ticket_init(&L->high_p)
49 #elif (ZM_TLP_HIGH_P == ZM_MCS)
50 #define zm_tlp_init_high_p(L) zm_mcs_init(&L->high_p)
51 #elif (ZM_TLP_HIGH_P == ZM_HMCS)
52 #define zm_tlp_init_high_p(L) zm_hmcs_init(&L->high_p)
53 #endif
54
55 #if (ZM_TLP_HIGH_P == ZM_TICKET)
56 #define zm_tlp_destroy_high_p(L) zm_ticket_destroy(&L->high_p)
57 #elif (ZM_TLP_HIGH_P == ZM_MCS)
58 #define zm_tlp_destroy_high_p(L) zm_mcs_destroy(&L->high_p)
59 #elif (ZM_TLP_HIGH_P == ZM_HMCS)
60 #define zm_tlp_destroy_high_p(L) zm_hmcs_destroy(&L->high_p)
61 #endif
62
63 #if (ZM_TLP_HIGH_P == ZM_TICKET)
64 #define zm_tlp_acquire_high_p(L) zm_ticket_acquire(&L->high_p)
65 #define zm_tlp_acquire_high_pc(L, local_ctxt) zm_ticket_acquire(&L->high_p)
66 #elif (ZM_TLP_HIGH_P == ZM_MCS)
67 #define zm_tlp_acquire_high_p(L) zm_mcs_acquire(L->high_p)
68 #define zm_tlp_acquire_high_pc(L, local_ctxt) zm_mcs_acquire_c(L->high_p, local_ctxt)
69 #elif (ZM_TLP_HIGH_P == ZM_HMCS)
70 #define zm_tlp_acquire_high_p(L) zm_hmcs_acquire(L->high_p)
71 #define zm_tlp_acquire_high_pc(L, local_ctxt) zm_hmcs_acquire(L->high_p)
72 #endif
73
74 #if (ZM_TLP_HIGH_P == ZM_TICKET)
75 #define zm_tlp_tryacq_high_p(L, s) zm_ticket_tryacq(&L->high_p, s)
76 #define zm_tlp_tryacq_high_pc(L, local_ctxt, s) zm_ticket_tryacq(&L->high_p, s)
77 #elif (ZM_TLP_HIGH_P == ZM_MCS)
78 #define zm_tlp_tryacq_high_p(L, s) zm_mcs_tryacq(&L->high_p, local_ctxt, s)
79 #define zm_tlp_tryacq_high_pc(L, local_ctxt, s) zm_mcs_tryacq(&L->high_p, local_ctxt, s)
80 #elif (ZM_TLP_HIGH_P == ZM_HMCS)
81 #define zm_tlp_tryacq_high_p(L, s) zm_hmcs_tryacq(L->high_p, s)
82 #define zm_tlp_tryacq_high_pc(L, local_ctxt, s) zm_hmcs_tryacq(L->high_p, s)
83 #endif
84
85 #if (ZM_TLP_HIGH_P == ZM_TICKET)
86 #define zm_tlp_release_high_p(L) zm_ticket_release(&L->high_p)
87 #define zm_tlp_release_high_pc(L, ctxt) zm_ticket_release(&L->high_p)
88 #elif (ZM_TLP_HIGH_P == ZM_MCS)
89 #define zm_tlp_release_high_p(L) zm_mcs_release(L->high_p);
90 #define zm_tlp_release_high_pc(L, ctxt) zm_mcs_release_c(L->high_p, ctxt);
91 #elif (ZM_TLP_HIGH_P == ZM_HMCS)
92 #define zm_tlp_release_high_p(L) zm_hmcs_release(L->high_p);
93 #define zm_tlp_release_high_pc(L, ctxt) zm_hmcs_release(L->high_p);
94 #endif
95
96 #if (ZM_TLP_LOW_P == ZM_TICKET)
97 #define zm_tlp_init_low_p(L) zm_ticket_init(&L->low_p)
98 #elif (ZM_TLP_LOW_P == ZM_MCS)
99 #define zm_tlp_init_low_p(L) zm_mcs_init(&L->low_p)
100 #elif (ZM_TLP_LOW_P == ZM_HMCS)
101 #define zm_tlp_init_low_p(L) zm_hmcs_init(&L->low_p)
102 #endif
103
104 #if (ZM_TLP_LOW_P == ZM_TICKET)
105 #define zm_tlp_destroy_low_p(L) zm_ticket_destroy(&L->low_p)
106 #elif (ZM_TLP_LOW_P == ZM_MCS)
107 #define zm_tlp_destroy_low_p(L) zm_mcs_destroy(&L->low_p)
108 #elif (ZM_TLP_LOW_P == ZM_HMCS)
109 #define zm_tlp_destroy_low_p(L) zm_hmcs_destroy(&L->low_p)
110 #endif
111
112 #if (ZM_TLP_LOW_P == ZM_TICKET)
113 #define zm_tlp_acquire_low_p(L) zm_ticket_acquire(&L->low_p)
114 #define zm_tlp_acquire_low_pc(L, local_ctxt) zm_ticket_acquire(&L->low_p)
115 #elif (ZM_TLP_LOW_P == ZM_MCS)
116 #define zm_tlp_acquire_low_p(L) zm_mcs_acquire(L->low_p)
117 #define zm_tlp_acquire_low_pc(L, local_ctxt) zm_mcs_acquire_c(L->low_p, local_ctxt)
118 #elif (ZM_TLP_LOW_P == ZM_HMCS)
119 #define zm_tlp_acquire_low_p(L) zm_hmcs_acquire(L->low_p)
120 #define zm_tlp_acquire_low_pc(L, local_ctxt) zm_hmcs_acquire(L->low_p)
121 #endif
122
123 #if (ZM_TLP_LOW_P == ZM_TICKET)
124 #define zm_tlp_tryacq_low_p(L, s) zm_ticket_tryacq(&L->low_p, s)
125 #define zm_tlp_tryacq_low_pc(L, local_ctxt, s) zm_ticket_tryacq(&L->low_p, s)
126 #elif (ZM_TLP_LOW_P == ZM_MCS)
127 #define zm_tlp_tryacq_low_p(L, s) zm_mcs_tryacq(L->low_p, s)
128 #define zm_tlp_tryacq_low_pc(L, local_ctxt, s) zm_mcs_tryacq(L->low_p, s)
129 #elif (ZM_TLP_LOW_P == ZM_HMCS)
130 #define zm_tlp_tryacq_low_p(L, s) zm_hmcs_tryacq(L->low_p, s)
131 #define zm_tlp_tryacq_low_pc(L, local_ctxt, s) zm_hmcs_tryacq(L->low_p, s)
132 #endif
133
134 #if (ZM_TLP_LOW_P == ZM_TICKET)
135 #define zm_tlp_release_low_p(L) zm_ticket_release(&L->low_p)
136 #define zm_tlp_release_low_pc(L, ctxt) zm_ticket_release(&L->low_p)
137 #elif (ZM_TLP_LOW_P == ZM_MCS)
138 #define zm_tlp_release_low_p(L) zm_mcs_release(L->low_p);
139 #define zm_tlp_release_low_pc(L, ctxt) zm_mcs_release_c(L->low_p, ctxt);
140 #elif (ZM_TLP_LOW_P == ZM_HMCS)
141 #define zm_tlp_release_low_p(L) zm_hmcs_release(L->low_p)
142 #define zm_tlp_release_low_pc(L, ctxt) zm_hmcs_release(L->low_p)
143 #endif
144
145 #if (ZM_TLP_HIGH_P == ZM_TICKET)
146 #define zm_tlp_nowaiters_high_p(L) zm_ticket_nowaiters(&L->high_p)
147 #define zm_tlp_nowaiters_high_pc(L, ctxt) zm_ticket_nowaiters(&L->high_p)
148 #elif (ZM_TLP_HIGH_P == ZM_MCS)
149 #define zm_tlp_nowaiters_high_p(L) zm_mcs_nowaiters(L->high_p)
150 #define zm_tlp_nowaiters_high_pc(L, ctxt) zm_mcs_nowaiters_c(L->high_p, ctxt)
151 #elif (ZM_TLP_HIGH_P == ZM_HMCS)
152 #define zm_tlp_nowaiters_high_p(L) zm_hmcs_nowaiters(L->high_p)
153 #define zm_tlp_nowaiters_high_pc(L, ctxt) zm_hmcs_nowaiters(L->high_p)
154 #endif
155
zm_tlp_init(zm_tlp_t * L)156 int zm_tlp_init(zm_tlp_t *L)
157 {
158 zm_tlp_init_high_p(L);
159 L->go_straight = 0;
160 L->low_p_acq = 0;
161 zm_ticket_init(&L->filter);
162 zm_tlp_init_low_p(L);
163 return 0;
164 }
165
zm_tlp_destroy(zm_tlp_t * L)166 int zm_tlp_destroy(zm_tlp_t *L)
167 {
168 zm_tlp_destroy_high_p(L);
169 zm_ticket_destroy(&L->filter);
170 zm_tlp_destroy_low_p(L);
171 return 0;
172 }
173
zm_tlp_acquire(zm_tlp_t * L)174 int zm_tlp_acquire(zm_tlp_t *L) {
175 /* Acquire the high priority lock */
176 zm_tlp_acquire_high_p(L);
177 if (!L->go_straight) {
178 zm_ticket_acquire(&L->filter);
179 L->go_straight = 1;
180 }
181 return 0;
182 }
183
zm_tlp_tryacq(zm_tlp_t * L,int * success)184 int zm_tlp_tryacq(zm_tlp_t *L, int *success) {
185 int acquired = 0;
186 zm_tlp_tryacq_high_p(L, &acquired);
187 if(acquired) {
188 if (!L->go_straight) {
189 zm_ticket_tryacq(&L->filter, &acquired);
190 if (acquired)
191 L->go_straight = 1;
192 }
193 }
194 return 0;
195 }
196
zm_tlp_acquire_low(zm_tlp_t * L)197 int zm_tlp_acquire_low(zm_tlp_t *L) {
198 /* Acquire the low priority lock */
199 zm_tlp_acquire_low_p(L);
200 zm_ticket_acquire(&L->filter);
201 L->low_p_acq = 1;
202 return 0;
203 }
204
zm_tlp_tryacq_low(zm_tlp_t * L,int * success)205 int zm_tlp_tryacq_low(zm_tlp_t *L, int *success) {
206 int acquired = 0;
207 zm_tlp_tryacq_low_p(L, &acquired);
208 if(acquired) {
209 if (!L->go_straight) {
210 zm_ticket_tryacq(&L->filter, &acquired);
211 if (acquired)
212 L->go_straight = 1;
213 }
214 }
215 return 0;
216 }
217
218 /* Release the lock */
zm_tlp_release(zm_tlp_t * L)219 int zm_tlp_release(zm_tlp_t *L) {
220 if (!L->low_p_acq) {
221 if (zm_tlp_nowaiters_high_p(L)) {
222 L->go_straight = 0;
223 zm_ticket_release(&L->filter);
224 }
225 zm_tlp_release_high_p(L);
226 } else {
227 L->low_p_acq = 0;
228 zm_ticket_release(&L->filter);
229 zm_tlp_release_low_p(L);
230 }
231 return 0;
232 }
233
zm_tlp_acquire_c(zm_tlp_t * L,zm_mcs_qnode_t * local_ctxt)234 int zm_tlp_acquire_c(zm_tlp_t *L, zm_mcs_qnode_t *local_ctxt) {
235 /* Acquire the high priority lock */
236 zm_tlp_acquire_high_pc(L, local_ctxt);
237 if (!L->go_straight) {
238 zm_ticket_acquire(&L->filter);
239 L->go_straight = 1;
240 }
241 return 0;
242 }
243
zm_tlp_acquire_low_c(zm_tlp_t * L,zm_mcs_qnode_t * local_ctxt)244 int zm_tlp_acquire_low_c(zm_tlp_t *L, zm_mcs_qnode_t *local_ctxt) {
245 /* Acquire the low priority lock */
246 zm_tlp_acquire_low_pc(L, local_ctxt);
247 zm_ticket_acquire(&L->filter);
248 L->low_p_acq = 1;
249 return 0;
250 }
251
252 /* Release the lock */
zm_tlp_release_c(zm_tlp_t * L,zm_mcs_qnode_t * ctxt)253 int zm_tlp_release_c(zm_tlp_t *L, zm_mcs_qnode_t* ctxt) {
254 if (!L->low_p_acq) {
255 if (zm_tlp_nowaiters_high_pc(L, ctxt)) {
256 L->go_straight = 0;
257 zm_ticket_release(&L->filter);
258 }
259 zm_tlp_release_high_pc(L, ctxt);
260 } else {
261 L->low_p_acq = 0;
262 zm_ticket_release(&L->filter);
263 zm_tlp_release_low_pc(L, ctxt);
264 }
265 return 0;
266 }
267