Whamcloud - gitweb
Landing b_hd_newconfig on HEAD
[fs/lustre-release.git] / lnet / libcfs / winnt / winnt-lock.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=4:tabstop=4:
3  *
4  *  Copyright (c) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or modify it under
9  *   the terms of version 2 of the GNU General Public License as published by
10  *   the Free Software Foundation. Lustre is distributed in the hope that it
11  *   will be useful, but WITHOUT ANY WARRANTY; without even the implied
12  *   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details. You should have received a
14  *   copy of the GNU General Public License along with Lustre; if not, write
15  *   to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
16  *   USA.
17  */
18
19
20 # define DEBUG_SUBSYSTEM S_LNET
21
22 #include <libcfs/libcfs.h>
23
24
25 #if _X86_
26
27 void __declspec (naked) FASTCALL
28 atomic_add(
29     int i,
30     atomic_t *v
31     )
32 {
33     // ECX = i
34     // EDX = v ; [EDX][0] = v->counter
35
36     __asm {
37         lock add dword ptr [edx][0], ecx
38         ret
39     }
40 }
41
42 void __declspec (naked) FASTCALL
43 atomic_sub(
44     int i,
45     atomic_t *v
46    ) 
47 {
48     // ECX = i
49     // EDX = v ; [EDX][0] = v->counter
50
51     __asm {
52         lock sub dword ptr [edx][0], ecx
53         ret
54     }
55 }
56
57 void __declspec (naked) FASTCALL
58 atomic_inc(
59     atomic_t *v
60     )
61 {
62     //InterlockedIncrement((PULONG)(&((v)->counter)));
63
64     //` ECX = v ; [ECX][0] = v->counter
65
66     __asm {
67         lock inc dword ptr [ecx][0]
68         ret
69     }
70 }
71
72 void __declspec (naked) FASTCALL
73 atomic_dec(
74     atomic_t *v
75     )
76 {
77     // ECX = v ; [ECX][0] = v->counter
78
79     __asm {
80         lock dec dword ptr [ecx][0]
81         ret
82     }
83 }
84
85 int __declspec (naked) FASTCALL 
86 atomic_sub_and_test(
87     int i,
88     atomic_t *v
89     )
90 {
91
92     // ECX = i
93     // EDX = v ; [EDX][0] = v->counter
94
95     __asm {
96         xor eax, eax
97         lock sub dword ptr [edx][0], ecx
98         sete al
99         ret
100     }
101 }
102
103 int __declspec (naked) FASTCALL
104 atomic_inc_and_test(
105     atomic_t *v
106     )
107 {
108     // ECX = v ; [ECX][0] = v->counter
109
110     __asm {
111         xor eax, eax
112         lock inc dword ptr [ecx][0]
113         sete al
114         ret
115     }
116 }
117
118 int __declspec (naked) FASTCALL
119 atomic_dec_and_test(
120     atomic_t *v
121     )
122 {
123     // ECX = v ; [ECX][0] = v->counter
124
125     __asm {
126         xor eax, eax
127         lock dec dword ptr [ecx][0]
128         sete al
129         ret
130     }
131 }
132
133 #else
134
135 void FASTCALL
136 atomic_add(
137     int i,
138     atomic_t *v
139     )
140 {
141     InterlockedExchangeAdd( (PULONG)(&((v)->counter)) , (LONG) (i));
142 }
143
144 void FASTCALL
145 atomic_sub(
146     int i,
147     atomic_t *v
148    ) 
149 {
150     InterlockedExchangeAdd( (PULONG)(&((v)->counter)) , (LONG) (-1*i));
151 }
152
153 void FASTCALL
154 atomic_inc(
155     atomic_t *v
156     )
157 {
158    InterlockedIncrement((PULONG)(&((v)->counter)));
159 }
160
161 void FASTCALL
162 atomic_dec(
163     atomic_t *v
164     )
165 {
166     InterlockedDecrement((PULONG)(&((v)->counter)));
167 }
168
169 int FASTCALL 
170 atomic_sub_and_test(
171     int i,
172     atomic_t *v
173     )
174 {
175     int counter, result;
176
177     do {
178
179         counter = v->counter;
180         result = counter - i;
181
182     } while ( InterlockedCompareExchange(
183                 &(v->counter),
184                 result,
185                 counter) !=  counter);
186
187     return (result == 0);
188 }
189
190 int FASTCALL
191 atomic_inc_and_test(
192     atomic_t *v
193     )
194 {
195     int counter, result;
196
197     do {
198
199         counter = v->counter;
200         result = counter + 1;
201
202     } while ( InterlockedCompareExchange(
203                 &(v->counter),
204                 result,
205                 counter) !=  counter);
206
207     return (result == 0);
208 }
209
210 int FASTCALL
211 atomic_dec_and_test(
212     atomic_t *v
213     )
214 {
215     int counter, result;
216
217     do {
218
219         counter = v->counter;
220         result = counter + 1;
221
222     } while ( InterlockedCompareExchange(
223                 &(v->counter),
224                 result,
225                 counter) !=  counter);
226
227     return (result == 0);
228 }
229
230 #endif
231
232
233 /*
234  * rw spinlock
235  */
236
237
238 void
239 rwlock_init(rwlock_t * rwlock)
240 {
241     spin_lock_init(&rwlock->guard);
242     rwlock->count = 0;
243 }
244
245 void
246 rwlock_fini(rwlock_t * rwlock)
247 {
248 }
249
250 void
251 read_lock(rwlock_t * rwlock)
252 {
253     cfs_task_t * task = cfs_current();
254     PTASK_SLOT   slot = NULL;
255
256     if (!task) {
257         /* should bugchk here */
258         cfs_enter_debugger();
259         return;
260     }
261
262     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
263     ASSERT(slot->Magic == TASKSLT_MAGIC);
264    
265     slot->irql = KeRaiseIrqlToDpcLevel();
266
267     while (TRUE) {
268             spin_lock(&rwlock->guard);
269         if (rwlock->count >= 0)
270             break;
271         spin_unlock(&rwlock->guard);
272     }
273
274         rwlock->count++;
275         spin_unlock(&rwlock->guard);
276 }
277
278 void
279 read_unlock(rwlock_t * rwlock)
280 {
281     cfs_task_t * task = cfs_current();
282     PTASK_SLOT   slot = NULL;
283
284     if (!task) {
285         /* should bugchk here */
286         cfs_enter_debugger();
287         return;
288     }
289
290     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
291     ASSERT(slot->Magic == TASKSLT_MAGIC);
292    
293     spin_lock(&rwlock->guard);
294         ASSERT(rwlock->count > 0);
295     rwlock->count--;
296     if (rwlock < 0) {
297         cfs_enter_debugger();
298     }
299         spin_unlock(&rwlock->guard);
300
301     KeLowerIrql(slot->irql);
302 }
303
304 void
305 write_lock(rwlock_t * rwlock)
306 {
307     cfs_task_t * task = cfs_current();
308     PTASK_SLOT   slot = NULL;
309
310     if (!task) {
311         /* should bugchk here */
312         cfs_enter_debugger();
313         return;
314     }
315
316     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
317     ASSERT(slot->Magic == TASKSLT_MAGIC);
318    
319     slot->irql = KeRaiseIrqlToDpcLevel();
320
321     while (TRUE) {
322             spin_lock(&rwlock->guard);
323         if (rwlock->count == 0)
324             break;
325         spin_unlock(&rwlock->guard);
326     }
327
328         rwlock->count = -1;
329         spin_unlock(&rwlock->guard);
330 }
331
332 void
333 write_unlock(rwlock_t * rwlock)
334 {
335     cfs_task_t * task = cfs_current();
336     PTASK_SLOT   slot = NULL;
337
338     if (!task) {
339         /* should bugchk here */
340         cfs_enter_debugger();
341         return;
342     }
343
344     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
345     ASSERT(slot->Magic == TASKSLT_MAGIC);
346    
347     spin_lock(&rwlock->guard);
348         ASSERT(rwlock->count == -1);
349     rwlock->count = 0;
350         spin_unlock(&rwlock->guard);
351
352     KeLowerIrql(slot->irql);
353 }