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