1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 #define DEBUG_SUBSYSTEM S_LIBCFS
39 #include <libcfs/libcfs.h>
40 #include <libcfs/kp30.h>
49 * To initialize the wait queue
52 * waitq: pointer to the cfs_waitq_t structure
61 void cfs_waitq_init(cfs_waitq_t *waitq)
63 waitq->magic = CFS_WAITQ_MAGIC;
65 INIT_LIST_HEAD(&(waitq->waiters));
66 spin_lock_init(&(waitq->guard));
71 * To initialize the wake link node
74 * link: pointer to the cfs_waitlink_t structure
83 void cfs_waitlink_init(cfs_waitlink_t *link)
85 cfs_task_t * task = cfs_current();
86 PTASK_SLOT slot = NULL;
89 /* should bugchk here */
94 slot = CONTAINING_RECORD(task, TASK_SLOT, task);
95 cfs_assert(slot->Magic == TASKSLT_MAGIC);
97 memset(link, 0, sizeof(cfs_waitlink_t));
99 link->magic = CFS_WAITLINK_MAGIC;
102 link->event = &(slot->Event);
103 link->hits = &(slot->hits);
105 atomic_inc(&slot->count);
107 INIT_LIST_HEAD(&(link->waitq[0].link));
108 INIT_LIST_HEAD(&(link->waitq[1].link));
110 link->waitq[0].waitl = link->waitq[1].waitl = link;
116 * To finilize the wake link node
119 * link: pointer to the cfs_waitlink_t structure
128 void cfs_waitlink_fini(cfs_waitlink_t *link)
130 cfs_task_t * task = cfs_current();
131 PTASK_SLOT slot = NULL;
134 /* should bugchk here */
135 cfs_enter_debugger();
139 slot = CONTAINING_RECORD(task, TASK_SLOT, task);
140 cfs_assert(slot->Magic == TASKSLT_MAGIC);
141 cfs_assert(link->magic == CFS_WAITLINK_MAGIC);
142 cfs_assert(link->waitq[0].waitq == NULL);
143 cfs_assert(link->waitq[1].waitq == NULL);
145 atomic_dec(&slot->count);
150 * cfs_waitq_add_internal
151 * To queue the wait link node to the wait queue
154 * waitq: pointer to the cfs_waitq_t structure
155 * link: pointer to the cfs_waitlink_t structure
156 * int: queue no (Normal or Forward waitq)
165 void cfs_waitq_add_internal(cfs_waitq_t *waitq,
166 cfs_waitlink_t *link,
169 LASSERT(waitq != NULL);
170 LASSERT(link != NULL);
171 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
172 LASSERT(link->magic == CFS_WAITLINK_MAGIC);
173 LASSERT(waitqid < CFS_WAITQ_CHANNELS);
175 spin_lock(&(waitq->guard));
176 LASSERT(link->waitq[waitqid].waitq == NULL);
177 link->waitq[waitqid].waitq = waitq;
178 if (link->flags & CFS_WAITQ_EXCLUSIVE) {
179 list_add_tail(&link->waitq[waitqid].link, &waitq->waiters);
181 list_add(&link->waitq[waitqid].link, &waitq->waiters);
183 spin_unlock(&(waitq->guard));
187 * To queue the wait link node to the wait queue
190 * waitq: pointer to the cfs_waitq_t structure
191 * link: pointer to the cfs_waitlink_t structure
200 void cfs_waitq_add(cfs_waitq_t *waitq,
201 cfs_waitlink_t *link)
203 cfs_waitq_add_internal(waitq, link, CFS_WAITQ_CHAN_NORMAL);
207 * cfs_waitq_add_exclusive
208 * To set the wait link node to exclusive mode
209 * and queue it to the wait queue
212 * waitq: pointer to the cfs_waitq_t structure
213 * link: pointer to the cfs_wait_link structure
222 void cfs_waitq_add_exclusive( cfs_waitq_t *waitq,
223 cfs_waitlink_t *link)
225 LASSERT(waitq != NULL);
226 LASSERT(link != NULL);
227 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
228 LASSERT(link->magic == CFS_WAITLINK_MAGIC);
230 link->flags |= CFS_WAITQ_EXCLUSIVE;
231 cfs_waitq_add(waitq, link);
236 * To be determinated.
239 * waitq: pointer to the cfs_waitq_t structure
240 * link: pointer to the cfs_waitlink_t structure
249 void cfs_waitq_forward( cfs_waitlink_t *link,
252 cfs_waitq_add_internal(waitq, link, CFS_WAITQ_CHAN_FORWARD);
257 * To remove the wait link node from the waitq
260 * waitq: pointer to the cfs_ waitq_t structure
261 * link: pointer to the cfs_waitlink_t structure
270 void cfs_waitq_del( cfs_waitq_t *waitq,
271 cfs_waitlink_t *link)
275 LASSERT(waitq != NULL);
276 LASSERT(link != NULL);
278 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
279 LASSERT(link->magic == CFS_WAITLINK_MAGIC);
281 spin_lock(&(waitq->guard));
283 for (i=0; i < CFS_WAITQ_CHANNELS; i++) {
284 if (link->waitq[i].waitq == waitq)
288 if (i < CFS_WAITQ_CHANNELS) {
289 link->waitq[i].waitq = NULL;
290 list_del_init(&link->waitq[i].link);
292 cfs_enter_debugger();
295 spin_unlock(&(waitq->guard));
300 * Is the waitq active (not empty) ?
303 * waitq: pointer to the cfs_ waitq_t structure
306 * Zero: the waitq is empty
307 * Non-Zero: the waitq is active
310 * We always returns TRUE here, the same to Darwin.
313 int cfs_waitq_active(cfs_waitq_t *waitq)
315 LASSERT(waitq != NULL);
316 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
322 * cfs_waitq_signal_nr
323 * To wake up all the non-exclusive tasks plus nr exclusive
327 * waitq: pointer to the cfs_waitq_t structure
328 * nr: number of exclusive tasks to be woken up
338 void cfs_waitq_signal_nr(cfs_waitq_t *waitq, int nr)
341 cfs_waitlink_channel_t * scan;
343 LASSERT(waitq != NULL);
344 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
346 spin_lock(&waitq->guard);
348 list_for_each_entry(scan, &waitq->waiters, cfs_waitlink_channel_t, link) {
350 cfs_waitlink_t *waitl = scan->waitl;
352 result = cfs_wake_event(waitl->event);
353 LASSERT( result == FALSE || result == TRUE );
356 atomic_inc(waitl->hits);
359 if ((waitl->flags & CFS_WAITQ_EXCLUSIVE) && --nr == 0)
363 spin_unlock(&waitq->guard);
369 * To wake up all the non-exclusive tasks and 1 exclusive
372 * waitq: pointer to the cfs_waitq_t structure
381 void cfs_waitq_signal(cfs_waitq_t *waitq)
383 cfs_waitq_signal_nr(waitq, 1);
388 * cfs_waitq_broadcast
389 * To wake up all the tasks in the waitq
392 * waitq: pointer to the cfs_waitq_t structure
401 void cfs_waitq_broadcast(cfs_waitq_t *waitq)
403 LASSERT(waitq != NULL);
404 LASSERT(waitq->magic ==CFS_WAITQ_MAGIC);
406 cfs_waitq_signal_nr(waitq, 0);
411 * To wait on the link node until it is signaled.
414 * link: pointer to the cfs_waitlink_t structure
423 void cfs_waitq_wait(cfs_waitlink_t *link, cfs_task_state_t state)
425 LASSERT(link != NULL);
426 LASSERT(link->magic == CFS_WAITLINK_MAGIC);
428 if (atomic_read(link->hits) > 0) {
429 atomic_dec(link->hits);
430 LASSERT((__u32)atomic_read(link->hits) < (__u32)0xFFFFFF00);
432 cfs_wait_event(link->event, 0);
437 * cfs_waitq_timedwait
438 * To wait the link node to be signaled with a timeout limit
441 * link: pointer to the cfs_waitlink_t structure
442 * timeout: the timeout limitation
445 * Woken up: return the difference of the current time and
450 * What if it happens to be woken up at the just timeout time !?
453 cfs_duration_t cfs_waitq_timedwait( cfs_waitlink_t *link,
454 cfs_task_state_t state,
455 cfs_duration_t timeout)
458 if (atomic_read(link->hits) > 0) {
459 atomic_dec(link->hits);
460 LASSERT((__u32)atomic_read(link->hits) < (__u32)0xFFFFFF00);
464 return (cfs_duration_t)cfs_wait_event(link->event, timeout);