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_LNET
39 #include <libcfs/libcfs.h>
48 * To initialize the wait queue
51 * waitq: pointer to the cfs_waitq_t structure
60 void cfs_waitq_init(cfs_waitq_t *waitq)
62 waitq->magic = CFS_WAITQ_MAGIC;
64 CFS_INIT_LIST_HEAD(&(waitq->waiters));
65 cfs_spin_lock_init(&(waitq->guard));
70 * To initialize the wake link node
73 * link: pointer to the cfs_waitlink_t structure
82 void cfs_waitlink_init(cfs_waitlink_t *link)
84 cfs_task_t * task = cfs_current();
85 PTASK_SLOT slot = NULL;
88 /* should bugchk here */
93 slot = CONTAINING_RECORD(task, TASK_SLOT, task);
94 cfs_assert(slot->Magic == TASKSLT_MAGIC);
96 memset(link, 0, sizeof(cfs_waitlink_t));
98 link->magic = CFS_WAITLINK_MAGIC;
101 link->event = &(slot->Event);
102 link->hits = &(slot->hits);
104 cfs_atomic_inc(&slot->count);
106 CFS_INIT_LIST_HEAD(&(link->waitq[0].link));
107 CFS_INIT_LIST_HEAD(&(link->waitq[1].link));
109 link->waitq[0].waitl = link->waitq[1].waitl = link;
115 * To finilize the wake link node
118 * link: pointer to the cfs_waitlink_t structure
127 void cfs_waitlink_fini(cfs_waitlink_t *link)
129 cfs_task_t * task = cfs_current();
130 PTASK_SLOT slot = NULL;
133 /* should bugchk here */
134 cfs_enter_debugger();
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);
144 cfs_atomic_dec(&slot->count);
149 * cfs_waitq_add_internal
150 * To queue the wait link node to the wait queue
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)
164 void cfs_waitq_add_internal(cfs_waitq_t *waitq,
165 cfs_waitlink_t *link,
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);
174 cfs_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 cfs_list_add_tail(&link->waitq[waitqid].link, &waitq->waiters);
180 cfs_list_add(&link->waitq[waitqid].link, &waitq->waiters);
182 cfs_spin_unlock(&(waitq->guard));
186 * To queue the wait link node to the wait queue
189 * waitq: pointer to the cfs_waitq_t structure
190 * link: pointer to the cfs_waitlink_t structure
199 void cfs_waitq_add(cfs_waitq_t *waitq,
200 cfs_waitlink_t *link)
202 cfs_waitq_add_internal(waitq, link, CFS_WAITQ_CHAN_NORMAL);
206 * cfs_waitq_add_exclusive
207 * To set the wait link node to exclusive mode
208 * and queue it to the wait queue
211 * waitq: pointer to the cfs_waitq_t structure
212 * link: pointer to the cfs_wait_link structure
221 void cfs_waitq_add_exclusive( cfs_waitq_t *waitq,
222 cfs_waitlink_t *link)
224 LASSERT(waitq != NULL);
225 LASSERT(link != NULL);
226 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
227 LASSERT(link->magic == CFS_WAITLINK_MAGIC);
229 link->flags |= CFS_WAITQ_EXCLUSIVE;
230 cfs_waitq_add(waitq, link);
235 * To remove the wait link node from the waitq
238 * waitq: pointer to the cfs_ waitq_t structure
239 * link: pointer to the cfs_waitlink_t structure
248 void cfs_waitq_del( cfs_waitq_t *waitq,
249 cfs_waitlink_t *link)
253 LASSERT(waitq != NULL);
254 LASSERT(link != NULL);
256 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
257 LASSERT(link->magic == CFS_WAITLINK_MAGIC);
259 cfs_spin_lock(&(waitq->guard));
261 for (i=0; i < CFS_WAITQ_CHANNELS; i++) {
262 if (link->waitq[i].waitq == waitq)
266 if (i < CFS_WAITQ_CHANNELS) {
267 link->waitq[i].waitq = NULL;
268 cfs_list_del_init(&link->waitq[i].link);
270 cfs_enter_debugger();
273 cfs_spin_unlock(&(waitq->guard));
278 * Is the waitq active (not empty) ?
281 * waitq: pointer to the cfs_ waitq_t structure
284 * Zero: the waitq is empty
285 * Non-Zero: the waitq is active
288 * We always returns TRUE here, the same to Darwin.
291 int cfs_waitq_active(cfs_waitq_t *waitq)
293 LASSERT(waitq != NULL);
294 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
300 * cfs_waitq_signal_nr
301 * To wake up all the non-exclusive tasks plus nr exclusive
305 * waitq: pointer to the cfs_waitq_t structure
306 * nr: number of exclusive tasks to be woken up
316 void cfs_waitq_signal_nr(cfs_waitq_t *waitq, int nr)
319 cfs_waitlink_channel_t * scan;
321 LASSERT(waitq != NULL);
322 LASSERT(waitq->magic == CFS_WAITQ_MAGIC);
324 cfs_spin_lock(&waitq->guard);
325 cfs_list_for_each_entry_typed(scan, &waitq->waiters,
326 cfs_waitlink_channel_t,
329 cfs_waitlink_t *waitl = scan->waitl;
331 result = cfs_wake_event(waitl->event);
332 LASSERT( result == FALSE || result == TRUE );
335 cfs_atomic_inc(waitl->hits);
338 if ((waitl->flags & CFS_WAITQ_EXCLUSIVE) && --nr == 0)
342 cfs_spin_unlock(&waitq->guard);
348 * To wake up all the non-exclusive tasks and 1 exclusive
351 * waitq: pointer to the cfs_waitq_t structure
360 void cfs_waitq_signal(cfs_waitq_t *waitq)
362 cfs_waitq_signal_nr(waitq, 1);
367 * cfs_waitq_broadcast
368 * To wake up all the tasks in the waitq
371 * waitq: pointer to the cfs_waitq_t structure
380 void cfs_waitq_broadcast(cfs_waitq_t *waitq)
382 LASSERT(waitq != NULL);
383 LASSERT(waitq->magic ==CFS_WAITQ_MAGIC);
385 cfs_waitq_signal_nr(waitq, 0);
390 * To wait on the link node until it is signaled.
393 * link: pointer to the cfs_waitlink_t structure
402 void cfs_waitq_wait(cfs_waitlink_t *link, cfs_task_state_t state)
404 LASSERT(link != NULL);
405 LASSERT(link->magic == CFS_WAITLINK_MAGIC);
407 if (cfs_atomic_read(link->hits) > 0) {
408 cfs_atomic_dec(link->hits);
409 LASSERT((__u32)cfs_atomic_read(link->hits) < (__u32)0xFFFFFF00);
411 cfs_wait_event_internal(link->event, 0);
416 * cfs_waitq_timedwait
417 * To wait the link node to be signaled with a timeout limit
420 * link: pointer to the cfs_waitlink_t structure
421 * timeout: the timeout limitation
424 * Woken up: return the difference of the current time and
429 * What if it happens to be woken up at the just timeout time !?
432 int64_t cfs_waitq_timedwait( cfs_waitlink_t *link,
433 cfs_task_state_t state,
437 if (cfs_atomic_read(link->hits) > 0) {
438 cfs_atomic_dec(link->hits);
439 LASSERT((__u32)cfs_atomic_read(link->hits) < (__u32)0xFFFFFF00);
440 return (int64_t)TRUE;
443 return (int64_t)cfs_wait_event_internal(link->event, timeout);