Whamcloud - gitweb
b=16098
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-sync.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 [sun.com URL with a
20  * copy of GPLv2].
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 #define DEBUG_SUBSYSTEM S_LIBCFS
38
39 #include <libcfs/libcfs.h>
40
41
42 /*
43  * Wait queue routines
44  */
45
46 /*
47  * cfs_waitq_init
48  *   To initialize the wait queue
49  *
50  * Arguments:
51  *   waitq:  pointer to the cfs_waitq_t structure
52  *
53  * Return Value:
54  *   N/A
55  *
56  * Notes: 
57  *   N/A
58  */
59
60 void cfs_waitq_init(cfs_waitq_t *waitq)
61 {
62     waitq->magic = CFS_WAITQ_MAGIC;
63     waitq->flags = 0;
64     INIT_LIST_HEAD(&(waitq->waiters));
65     spin_lock_init(&(waitq->guard));
66 }
67
68 /*
69  * cfs_waitlink_init
70  *   To initialize the wake link node
71  *
72  * Arguments:
73  *   link:  pointer to the cfs_waitlink_t structure
74  *
75  * Return Value:
76  *   N/A
77  *
78  * Notes: 
79  *   N/A
80  */
81
82 void cfs_waitlink_init(cfs_waitlink_t *link)
83 {
84     cfs_task_t * task = cfs_current();
85     PTASK_SLOT   slot = NULL;
86
87     if (!task) {
88         /* should bugchk here */
89         cfs_enter_debugger();
90         return;
91     }
92
93     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
94     cfs_assert(slot->Magic == TASKSLT_MAGIC);
95
96     memset(link, 0, sizeof(cfs_waitlink_t));
97
98     link->magic = CFS_WAITLINK_MAGIC;
99     link->flags = 0;
100
101     link->event = &(slot->Event);
102     link->hits  = &(slot->hits);
103
104     atomic_inc(&slot->count);
105
106     INIT_LIST_HEAD(&(link->waitq[0].link));
107     INIT_LIST_HEAD(&(link->waitq[1].link));
108
109     link->waitq[0].waitl = link->waitq[1].waitl = link;
110 }
111
112
113 /*
114  * cfs_waitlink_fini
115  *   To finilize the wake link node
116  *
117  * Arguments:
118  *   link:  pointer to the cfs_waitlink_t structure
119  *
120  * Return Value:
121  *   N/A
122  *
123  * Notes: 
124  *   N/A
125  */
126
127 void cfs_waitlink_fini(cfs_waitlink_t *link)
128 {
129     cfs_task_t * task = cfs_current();
130     PTASK_SLOT   slot = NULL;
131
132     if (!task) {
133         /* should bugchk here */
134         cfs_enter_debugger();
135         return;
136     }
137
138     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
139     cfs_assert(slot->Magic == TASKSLT_MAGIC);
140     cfs_assert(link->magic == CFS_WAITLINK_MAGIC);
141     cfs_assert(link->waitq[0].waitq == NULL);
142     cfs_assert(link->waitq[1].waitq == NULL);
143
144     atomic_dec(&slot->count);
145 }
146
147
148 /*
149  * cfs_waitq_add_internal
150  *   To queue the wait link node to the wait queue
151  *
152  * Arguments:
153  *   waitq:  pointer to the cfs_waitq_t structure
154  *   link:   pointer to the cfs_waitlink_t structure
155  *   int:    queue no (Normal or Forward waitq)
156  *
157  * Return Value:
158  *   N/A
159  *
160  * Notes: 
161  *   N/A
162  */
163
164 void cfs_waitq_add_internal(cfs_waitq_t *waitq,
165                             cfs_waitlink_t *link,
166                             __u32 waitqid )
167
168     LASSERT(waitq != NULL);
169     LASSERT(link != NULL);
170     LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
171     LASSERT(link->magic == CFS_WAITLINK_MAGIC);
172     LASSERT(waitqid < CFS_WAITQ_CHANNELS);
173
174     spin_lock(&(waitq->guard));
175     LASSERT(link->waitq[waitqid].waitq == NULL);
176     link->waitq[waitqid].waitq = waitq;
177     if (link->flags & CFS_WAITQ_EXCLUSIVE) {
178         list_add_tail(&link->waitq[waitqid].link, &waitq->waiters);
179     } else {
180         list_add(&link->waitq[waitqid].link, &waitq->waiters);
181     }
182     spin_unlock(&(waitq->guard));
183 }
184 /*
185  * cfs_waitq_add
186  *   To queue the wait link node to the wait queue
187  *
188  * Arguments:
189  *   waitq:  pointer to the cfs_waitq_t structure
190  *   link:  pointer to the cfs_waitlink_t structure
191  *
192  * Return Value:
193  *   N/A
194  *
195  * Notes: 
196  *   N/A
197  */
198
199 void cfs_waitq_add(cfs_waitq_t *waitq,
200                    cfs_waitlink_t *link)
201
202     cfs_waitq_add_internal(waitq, link, CFS_WAITQ_CHAN_NORMAL);
203 }
204
205 /*
206  * cfs_waitq_add_exclusive
207  *   To set the wait link node to exclusive mode
208  *   and queue it to the wait queue
209  *
210  * Arguments:
211  *   waitq:  pointer to the cfs_waitq_t structure
212  *   link:  pointer to the cfs_wait_link structure
213  *
214  * Return Value:
215  *   N/A
216  *
217  * Notes: 
218  *   N/A
219  */
220
221 void cfs_waitq_add_exclusive( cfs_waitq_t *waitq,
222                               cfs_waitlink_t *link)
223 {
224     LASSERT(waitq != NULL);
225     LASSERT(link != NULL);
226     LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
227     LASSERT(link->magic == CFS_WAITLINK_MAGIC);
228
229         link->flags |= CFS_WAITQ_EXCLUSIVE;
230     cfs_waitq_add(waitq, link);
231 }
232
233 /*
234  * cfs_waitq_forward
235  *   To be determinated.
236  *
237  * Arguments:
238  *   waitq:  pointer to the cfs_waitq_t structure
239  *   link:  pointer to the cfs_waitlink_t structure
240  *
241  * Return Value:
242  *   N/A
243  *
244  * Notes: 
245  *   N/A
246  */
247
248 void cfs_waitq_forward( cfs_waitlink_t *link,
249                         cfs_waitq_t *waitq)
250 {
251     cfs_waitq_add_internal(waitq, link, CFS_WAITQ_CHAN_FORWARD);
252 }
253
254 /*
255  * cfs_waitq_del
256  *   To remove the wait link node from the waitq
257  *
258  * Arguments:
259  *   waitq:  pointer to the cfs_ waitq_t structure
260  *   link:  pointer to the cfs_waitlink_t structure
261  *
262  * Return Value:
263  *   N/A
264  *
265  * Notes: 
266  *   N/A
267  */
268
269 void cfs_waitq_del( cfs_waitq_t *waitq,
270                     cfs_waitlink_t *link)
271 {
272     int i = 0;
273
274     LASSERT(waitq != NULL);
275     LASSERT(link != NULL);
276
277     LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
278     LASSERT(link->magic == CFS_WAITLINK_MAGIC);
279
280     spin_lock(&(waitq->guard));
281
282     for (i=0; i < CFS_WAITQ_CHANNELS; i++) {
283         if (link->waitq[i].waitq == waitq)
284             break;
285     }
286
287     if (i < CFS_WAITQ_CHANNELS) {
288         link->waitq[i].waitq = NULL;
289         list_del_init(&link->waitq[i].link);
290     } else {
291         cfs_enter_debugger();
292     }
293
294     spin_unlock(&(waitq->guard));
295 }
296
297 /*
298  * cfs_waitq_active
299  *   Is the waitq active (not empty) ?
300  *
301  * Arguments:
302  *   waitq:  pointer to the cfs_ waitq_t structure
303  *
304  * Return Value:
305  *   Zero: the waitq is empty
306  *   Non-Zero: the waitq is active
307  *
308  * Notes: 
309  *   We always returns TRUE here, the same to Darwin.
310  */
311
312 int cfs_waitq_active(cfs_waitq_t *waitq)
313 {
314     LASSERT(waitq != NULL);
315     LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
316
317         return (1);
318 }
319
320 /*
321  * cfs_waitq_signal_nr
322  *   To wake up all the non-exclusive tasks plus nr exclusive
323  *   ones in the waitq
324  *
325  * Arguments:
326  *   waitq:  pointer to the cfs_waitq_t structure
327  *   nr:    number of exclusive tasks to be woken up
328  *
329  * Return Value:
330  *   N/A
331  *
332  * Notes: 
333  *   N/A
334  */
335
336
337 void cfs_waitq_signal_nr(cfs_waitq_t *waitq, int nr)
338 {
339     int     result;
340     cfs_waitlink_channel_t * scan;
341
342     LASSERT(waitq != NULL);
343     LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
344
345     spin_lock(&waitq->guard);
346
347     list_for_each_entry(scan, &waitq->waiters, cfs_waitlink_channel_t, link) {
348
349         cfs_waitlink_t *waitl = scan->waitl;
350
351         result = cfs_wake_event(waitl->event);
352         LASSERT( result == FALSE || result == TRUE );
353
354         if (result) {
355             atomic_inc(waitl->hits);
356         }
357
358         if ((waitl->flags & CFS_WAITQ_EXCLUSIVE) && --nr == 0)
359             break;
360     }
361
362     spin_unlock(&waitq->guard);
363     return;
364 }
365
366 /*
367  * cfs_waitq_signal
368  *   To wake up all the non-exclusive tasks and 1 exclusive
369  *
370  * Arguments:
371  *   waitq:  pointer to the cfs_waitq_t structure
372  *
373  * Return Value:
374  *   N/A
375  *
376  * Notes: 
377  *   N/A
378  */
379
380 void cfs_waitq_signal(cfs_waitq_t *waitq)
381 {
382     cfs_waitq_signal_nr(waitq, 1);
383 }
384
385
386 /*
387  * cfs_waitq_broadcast
388  *   To wake up all the tasks in the waitq
389  *
390  * Arguments:
391  *   waitq:  pointer to the cfs_waitq_t structure
392  *
393  * Return Value:
394  *   N/A
395  *
396  * Notes: 
397  *   N/A
398  */
399
400 void cfs_waitq_broadcast(cfs_waitq_t *waitq)
401 {
402     LASSERT(waitq != NULL);
403     LASSERT(waitq->magic ==CFS_WAITQ_MAGIC);
404
405         cfs_waitq_signal_nr(waitq, 0);
406 }
407
408 /*
409  * cfs_waitq_wait
410  *   To wait on the link node until it is signaled.
411  *
412  * Arguments:
413  *   link:  pointer to the cfs_waitlink_t structure
414  *
415  * Return Value:
416  *   N/A
417  *
418  * Notes: 
419  *   N/A
420  */
421
422 void cfs_waitq_wait(cfs_waitlink_t *link, cfs_task_state_t state)
423
424     LASSERT(link != NULL);
425     LASSERT(link->magic == CFS_WAITLINK_MAGIC);
426
427     if (atomic_read(link->hits) > 0) {
428         atomic_dec(link->hits);
429         LASSERT((__u32)atomic_read(link->hits) < (__u32)0xFFFFFF00);
430     } else {
431         cfs_wait_event(link->event, 0);
432     }
433 }
434
435 /*
436  * cfs_waitq_timedwait
437  *   To wait the link node to be signaled with a timeout limit
438  *
439  * Arguments:
440  *   link:   pointer to the cfs_waitlink_t structure
441  *   timeout: the timeout limitation
442  *
443  * Return Value:
444  *   Woken up: return the difference of the current time and
445  *             the timeout
446  *   Timeout:  return 0
447  *
448  * Notes: 
449  *   What if it happens to be woken up at the just timeout time !?
450  */
451
452 cfs_duration_t cfs_waitq_timedwait( cfs_waitlink_t *link,
453                                     cfs_task_state_t state,
454                                     cfs_duration_t timeout)
455
456
457     if (atomic_read(link->hits) > 0) {
458         atomic_dec(link->hits);
459         LASSERT((__u32)atomic_read(link->hits) < (__u32)0xFFFFFF00);
460         return TRUE;
461     }
462
463     return (cfs_duration_t)cfs_wait_event(link->event, timeout);
464 }