Whamcloud - gitweb
fc62f39b15500f0fcc3f3a3bcdd2f2c90606c6c4
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-sync.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  */
34
35 #define DEBUG_SUBSYSTEM S_LNET
36
37 #include <libcfs/libcfs.h>
38
39
40 /*
41  * Wait queue routines
42  */
43
44 /*
45  * cfs_waitq_init
46  *   To initialize the wait queue
47  *
48  * Arguments:
49  *   waitq:  pointer to the cfs_waitq_t structure
50  *
51  * Return Value:
52  *   N/A
53  *
54  * Notes: 
55  *   N/A
56  */
57
58 void cfs_waitq_init(cfs_waitq_t *waitq)
59 {
60     waitq->magic = CFS_WAITQ_MAGIC;
61     waitq->flags = 0;
62     CFS_INIT_LIST_HEAD(&(waitq->waiters));
63     cfs_spin_lock_init(&(waitq->guard));
64 }
65
66 /*
67  * cfs_waitlink_init
68  *   To initialize the wake link node
69  *
70  * Arguments:
71  *   link:  pointer to the cfs_waitlink_t structure
72  *
73  * Return Value:
74  *   N/A
75  *
76  * Notes: 
77  *   N/A
78  */
79
80 void cfs_waitlink_init(cfs_waitlink_t *link)
81 {
82     cfs_task_t * task = cfs_current();
83     PTASK_SLOT   slot = NULL;
84
85     if (!task) {
86         /* should bugchk here */
87         cfs_enter_debugger();
88         return;
89     }
90
91     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
92     cfs_assert(slot->Magic == TASKSLT_MAGIC);
93
94     memset(link, 0, sizeof(cfs_waitlink_t));
95
96     link->magic = CFS_WAITLINK_MAGIC;
97     link->flags = 0;
98
99     link->event = &(slot->Event);
100     link->hits  = &(slot->hits);
101
102     cfs_atomic_inc(&slot->count);
103
104     CFS_INIT_LIST_HEAD(&(link->waitq[0].link));
105     CFS_INIT_LIST_HEAD(&(link->waitq[1].link));
106
107     link->waitq[0].waitl = link->waitq[1].waitl = link;
108 }
109
110
111 /*
112  * cfs_waitlink_fini
113  *   To finilize the wake link node
114  *
115  * Arguments:
116  *   link:  pointer to the cfs_waitlink_t structure
117  *
118  * Return Value:
119  *   N/A
120  *
121  * Notes: 
122  *   N/A
123  */
124
125 void cfs_waitlink_fini(cfs_waitlink_t *link)
126 {
127     cfs_task_t * task = cfs_current();
128     PTASK_SLOT   slot = NULL;
129
130     if (!task) {
131         /* should bugchk here */
132         cfs_enter_debugger();
133         return;
134     }
135
136     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
137     cfs_assert(slot->Magic == TASKSLT_MAGIC);
138     cfs_assert(link->magic == CFS_WAITLINK_MAGIC);
139     cfs_assert(link->waitq[0].waitq == NULL);
140     cfs_assert(link->waitq[1].waitq == NULL);
141
142     cfs_atomic_dec(&slot->count);
143 }
144
145
146 /*
147  * cfs_waitq_add_internal
148  *   To queue the wait link node to the wait queue
149  *
150  * Arguments:
151  *   waitq:  pointer to the cfs_waitq_t structure
152  *   link:   pointer to the cfs_waitlink_t structure
153  *   int:    queue no (Normal or Forward waitq)
154  *
155  * Return Value:
156  *   N/A
157  *
158  * Notes: 
159  *   N/A
160  */
161
162 void cfs_waitq_add_internal(cfs_waitq_t *waitq,
163                             cfs_waitlink_t *link,
164                             __u32 waitqid )
165
166     LASSERT(waitq != NULL);
167     LASSERT(link != NULL);
168     LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
169     LASSERT(link->magic == CFS_WAITLINK_MAGIC);
170     LASSERT(waitqid < CFS_WAITQ_CHANNELS);
171
172     cfs_spin_lock(&(waitq->guard));
173     LASSERT(link->waitq[waitqid].waitq == NULL);
174     link->waitq[waitqid].waitq = waitq;
175     if (link->flags & CFS_WAITQ_EXCLUSIVE) {
176         cfs_list_add_tail(&link->waitq[waitqid].link, &waitq->waiters);
177     } else {
178         cfs_list_add(&link->waitq[waitqid].link, &waitq->waiters);
179     }
180     cfs_spin_unlock(&(waitq->guard));
181 }
182 /*
183  * cfs_waitq_add
184  *   To queue the wait link node to the wait queue
185  *
186  * Arguments:
187  *   waitq:  pointer to the cfs_waitq_t structure
188  *   link:  pointer to the cfs_waitlink_t structure
189  *
190  * Return Value:
191  *   N/A
192  *
193  * Notes: 
194  *   N/A
195  */
196
197 void cfs_waitq_add(cfs_waitq_t *waitq,
198                    cfs_waitlink_t *link)
199
200     cfs_waitq_add_internal(waitq, link, CFS_WAITQ_CHAN_NORMAL);
201 }
202
203 /*
204  * cfs_waitq_add_exclusive
205  *   To set the wait link node to exclusive mode
206  *   and queue it to the wait queue
207  *
208  * Arguments:
209  *   waitq:  pointer to the cfs_waitq_t structure
210  *   link:  pointer to the cfs_wait_link structure
211  *
212  * Return Value:
213  *   N/A
214  *
215  * Notes: 
216  *   N/A
217  */
218
219 void cfs_waitq_add_exclusive( cfs_waitq_t *waitq,
220                               cfs_waitlink_t *link)
221 {
222     LASSERT(waitq != NULL);
223     LASSERT(link != NULL);
224     LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
225     LASSERT(link->magic == CFS_WAITLINK_MAGIC);
226
227         link->flags |= CFS_WAITQ_EXCLUSIVE;
228     cfs_waitq_add(waitq, link);
229 }
230
231 /*
232  * cfs_waitq_del
233  *   To remove the wait link node from the waitq
234  *
235  * Arguments:
236  *   waitq:  pointer to the cfs_ waitq_t structure
237  *   link:  pointer to the cfs_waitlink_t structure
238  *
239  * Return Value:
240  *   N/A
241  *
242  * Notes: 
243  *   N/A
244  */
245
246 void cfs_waitq_del( cfs_waitq_t *waitq,
247                     cfs_waitlink_t *link)
248 {
249     int i = 0;
250
251     LASSERT(waitq != NULL);
252     LASSERT(link != NULL);
253
254     LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
255     LASSERT(link->magic == CFS_WAITLINK_MAGIC);
256
257     cfs_spin_lock(&(waitq->guard));
258
259     for (i=0; i < CFS_WAITQ_CHANNELS; i++) {
260         if (link->waitq[i].waitq == waitq)
261             break;
262     }
263
264     if (i < CFS_WAITQ_CHANNELS) {
265         link->waitq[i].waitq = NULL;
266         cfs_list_del_init(&link->waitq[i].link);
267     } else {
268         cfs_enter_debugger();
269     }
270
271     cfs_spin_unlock(&(waitq->guard));
272 }
273
274 /*
275  * cfs_waitq_active
276  *   Is the waitq active (not empty) ?
277  *
278  * Arguments:
279  *   waitq:  pointer to the cfs_ waitq_t structure
280  *
281  * Return Value:
282  *   Zero: the waitq is empty
283  *   Non-Zero: the waitq is active
284  *
285  * Notes: 
286  *   We always returns TRUE here, the same to Darwin.
287  */
288
289 int cfs_waitq_active(cfs_waitq_t *waitq)
290 {
291     LASSERT(waitq != NULL);
292     LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
293
294         return (1);
295 }
296
297 /*
298  * cfs_waitq_signal_nr
299  *   To wake up all the non-exclusive tasks plus nr exclusive
300  *   ones in the waitq
301  *
302  * Arguments:
303  *   waitq:  pointer to the cfs_waitq_t structure
304  *   nr:    number of exclusive tasks to be woken up
305  *
306  * Return Value:
307  *   N/A
308  *
309  * Notes: 
310  *   N/A
311  */
312
313
314 void cfs_waitq_signal_nr(cfs_waitq_t *waitq, int nr)
315 {
316     int     result;
317     cfs_waitlink_channel_t * scan;
318
319     LASSERT(waitq != NULL);
320     LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
321
322     cfs_spin_lock(&waitq->guard);
323     cfs_list_for_each_entry_typed(scan, &waitq->waiters, 
324                             cfs_waitlink_channel_t,
325                             link) {
326
327         cfs_waitlink_t *waitl = scan->waitl;
328
329         result = cfs_wake_event(waitl->event);
330         LASSERT( result == FALSE || result == TRUE );
331
332         if (result) {
333             cfs_atomic_inc(waitl->hits);
334         }
335
336         if ((waitl->flags & CFS_WAITQ_EXCLUSIVE) && --nr == 0)
337             break;
338     }
339
340     cfs_spin_unlock(&waitq->guard);
341     return;
342 }
343
344 /*
345  * cfs_waitq_signal
346  *   To wake up all the non-exclusive tasks and 1 exclusive
347  *
348  * Arguments:
349  *   waitq:  pointer to the cfs_waitq_t structure
350  *
351  * Return Value:
352  *   N/A
353  *
354  * Notes: 
355  *   N/A
356  */
357
358 void cfs_waitq_signal(cfs_waitq_t *waitq)
359 {
360     cfs_waitq_signal_nr(waitq, 1);
361 }
362
363
364 /*
365  * cfs_waitq_broadcast
366  *   To wake up all the tasks in the waitq
367  *
368  * Arguments:
369  *   waitq:  pointer to the cfs_waitq_t structure
370  *
371  * Return Value:
372  *   N/A
373  *
374  * Notes: 
375  *   N/A
376  */
377
378 void cfs_waitq_broadcast(cfs_waitq_t *waitq)
379 {
380     LASSERT(waitq != NULL);
381     LASSERT(waitq->magic ==CFS_WAITQ_MAGIC);
382
383         cfs_waitq_signal_nr(waitq, 0);
384 }
385
386 /*
387  * cfs_waitq_wait
388  *   To wait on the link node until it is signaled.
389  *
390  * Arguments:
391  *   link:  pointer to the cfs_waitlink_t structure
392  *
393  * Return Value:
394  *   N/A
395  *
396  * Notes: 
397  *   N/A
398  */
399
400 void cfs_waitq_wait(cfs_waitlink_t *link, cfs_task_state_t state)
401
402     LASSERT(link != NULL);
403     LASSERT(link->magic == CFS_WAITLINK_MAGIC);
404
405     if (cfs_atomic_read(link->hits) > 0) {
406         cfs_atomic_dec(link->hits);
407         LASSERT((__u32)cfs_atomic_read(link->hits) < (__u32)0xFFFFFF00);
408     } else {
409         cfs_wait_event_internal(link->event, 0);
410     }
411 }
412
413 /*
414  * cfs_waitq_timedwait
415  *   To wait the link node to be signaled with a timeout limit
416  *
417  * Arguments:
418  *   link:   pointer to the cfs_waitlink_t structure
419  *   timeout: the timeout limitation
420  *
421  * Return Value:
422  *   Woken up: return the difference of the current time and
423  *             the timeout
424  *   Timeout:  return 0
425  *
426  * Notes: 
427  *   What if it happens to be woken up at the just timeout time !?
428  */
429
430 int64_t cfs_waitq_timedwait( cfs_waitlink_t *link,
431                              cfs_task_state_t state,
432                              int64_t timeout)
433
434
435     if (cfs_atomic_read(link->hits) > 0) {
436         cfs_atomic_dec(link->hits);
437         LASSERT((__u32)cfs_atomic_read(link->hits) < (__u32)0xFFFFFF00);
438         return (int64_t)TRUE;
439     }
440
441     return (int64_t)cfs_wait_event_internal(link->event, timeout);
442 }