4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
31 * This file is part of Lustre, http://www.lustre.org/
32 * Lustre is a trademark of Sun Microsystems, Inc.
35 #define DEBUG_SUBSYSTEM S_LNET
37 #include <libcfs/libcfs.h>
46 * To initialize the wait queue
49 * waitq: pointer to the cfs_waitq_t structure
58 void cfs_waitq_init(cfs_waitq_t *waitq)
60 waitq->magic = CFS_WAITQ_MAGIC;
62 CFS_INIT_LIST_HEAD(&(waitq->waiters));
63 cfs_spin_lock_init(&(waitq->guard));
68 * To initialize the wake link node
71 * link: pointer to the cfs_waitlink_t structure
80 void cfs_waitlink_init(cfs_waitlink_t *link)
82 cfs_task_t * task = cfs_current();
83 PTASK_SLOT slot = NULL;
86 /* should bugchk here */
91 slot = CONTAINING_RECORD(task, TASK_SLOT, task);
92 cfs_assert(slot->Magic == TASKSLT_MAGIC);
94 memset(link, 0, sizeof(cfs_waitlink_t));
96 link->magic = CFS_WAITLINK_MAGIC;
99 link->event = &(slot->Event);
100 link->hits = &(slot->hits);
102 cfs_atomic_inc(&slot->count);
104 CFS_INIT_LIST_HEAD(&(link->waitq[0].link));
105 CFS_INIT_LIST_HEAD(&(link->waitq[1].link));
107 link->waitq[0].waitl = link->waitq[1].waitl = link;
113 * To finilize the wake link node
116 * link: pointer to the cfs_waitlink_t structure
125 void cfs_waitlink_fini(cfs_waitlink_t *link)
127 cfs_task_t * task = cfs_current();
128 PTASK_SLOT slot = NULL;
131 /* should bugchk here */
132 cfs_enter_debugger();
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);
142 cfs_atomic_dec(&slot->count);
147 * cfs_waitq_add_internal
148 * To queue the wait link node to the wait queue
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)
162 void cfs_waitq_add_internal(cfs_waitq_t *waitq,
163 cfs_waitlink_t *link,
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);
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);
178 cfs_list_add(&link->waitq[waitqid].link, &waitq->waiters);
180 cfs_spin_unlock(&(waitq->guard));
184 * To queue the wait link node to the wait queue
187 * waitq: pointer to the cfs_waitq_t structure
188 * link: pointer to the cfs_waitlink_t structure
197 void cfs_waitq_add(cfs_waitq_t *waitq,
198 cfs_waitlink_t *link)
200 cfs_waitq_add_internal(waitq, link, CFS_WAITQ_CHAN_NORMAL);
204 * cfs_waitq_add_exclusive
205 * To set the wait link node to exclusive mode
206 * and queue it to the wait queue
209 * waitq: pointer to the cfs_waitq_t structure
210 * link: pointer to the cfs_wait_link structure
219 void cfs_waitq_add_exclusive( cfs_waitq_t *waitq,
220 cfs_waitlink_t *link)
222 LASSERT(waitq != NULL);
223 LASSERT(link != NULL);
224 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
225 LASSERT(link->magic == CFS_WAITLINK_MAGIC);
227 link->flags |= CFS_WAITQ_EXCLUSIVE;
228 cfs_waitq_add(waitq, link);
233 * To remove the wait link node from the waitq
236 * waitq: pointer to the cfs_ waitq_t structure
237 * link: pointer to the cfs_waitlink_t structure
246 void cfs_waitq_del( cfs_waitq_t *waitq,
247 cfs_waitlink_t *link)
251 LASSERT(waitq != NULL);
252 LASSERT(link != NULL);
254 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
255 LASSERT(link->magic == CFS_WAITLINK_MAGIC);
257 cfs_spin_lock(&(waitq->guard));
259 for (i=0; i < CFS_WAITQ_CHANNELS; i++) {
260 if (link->waitq[i].waitq == waitq)
264 if (i < CFS_WAITQ_CHANNELS) {
265 link->waitq[i].waitq = NULL;
266 cfs_list_del_init(&link->waitq[i].link);
268 cfs_enter_debugger();
271 cfs_spin_unlock(&(waitq->guard));
276 * Is the waitq active (not empty) ?
279 * waitq: pointer to the cfs_ waitq_t structure
282 * Zero: the waitq is empty
283 * Non-Zero: the waitq is active
286 * We always returns TRUE here, the same to Darwin.
289 int cfs_waitq_active(cfs_waitq_t *waitq)
291 LASSERT(waitq != NULL);
292 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
298 * cfs_waitq_signal_nr
299 * To wake up all the non-exclusive tasks plus nr exclusive
303 * waitq: pointer to the cfs_waitq_t structure
304 * nr: number of exclusive tasks to be woken up
314 void cfs_waitq_signal_nr(cfs_waitq_t *waitq, int nr)
317 cfs_waitlink_channel_t * scan;
319 LASSERT(waitq != NULL);
320 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
322 cfs_spin_lock(&waitq->guard);
323 cfs_list_for_each_entry_typed(scan, &waitq->waiters,
324 cfs_waitlink_channel_t,
327 cfs_waitlink_t *waitl = scan->waitl;
329 result = cfs_wake_event(waitl->event);
330 LASSERT( result == FALSE || result == TRUE );
333 cfs_atomic_inc(waitl->hits);
336 if ((waitl->flags & CFS_WAITQ_EXCLUSIVE) && --nr == 0)
340 cfs_spin_unlock(&waitq->guard);
346 * To wake up all the non-exclusive tasks and 1 exclusive
349 * waitq: pointer to the cfs_waitq_t structure
358 void cfs_waitq_signal(cfs_waitq_t *waitq)
360 cfs_waitq_signal_nr(waitq, 1);
365 * cfs_waitq_broadcast
366 * To wake up all the tasks in the waitq
369 * waitq: pointer to the cfs_waitq_t structure
378 void cfs_waitq_broadcast(cfs_waitq_t *waitq)
380 LASSERT(waitq != NULL);
381 LASSERT(waitq->magic ==CFS_WAITQ_MAGIC);
383 cfs_waitq_signal_nr(waitq, 0);
388 * To wait on the link node until it is signaled.
391 * link: pointer to the cfs_waitlink_t structure
400 void cfs_waitq_wait(cfs_waitlink_t *link, cfs_task_state_t state)
402 LASSERT(link != NULL);
403 LASSERT(link->magic == CFS_WAITLINK_MAGIC);
405 if (cfs_atomic_read(link->hits) > 0) {
406 cfs_atomic_dec(link->hits);
407 LASSERT((__u32)cfs_atomic_read(link->hits) < (__u32)0xFFFFFF00);
409 cfs_wait_event_internal(link->event, 0);
414 * cfs_waitq_timedwait
415 * To wait the link node to be signaled with a timeout limit
418 * link: pointer to the cfs_waitlink_t structure
419 * timeout: the timeout limitation
422 * Woken up: return the difference of the current time and
427 * What if it happens to be woken up at the just timeout time !?
430 int64_t cfs_waitq_timedwait( cfs_waitlink_t *link,
431 cfs_task_state_t state,
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;
441 return (int64_t)cfs_wait_event_internal(link->event, timeout);