X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lnet%2Fselftest%2Ftimer.c;h=3ceec81bf1b087bc3bc5c41eab6ae860e9b7ee49;hp=97d92970542aebec26f8ac4eb2e8a7c85db68a03;hb=917655fc2938b90a9c246dd2d58408c42aa1658d;hpb=776615e6825e2c90c2635c8b55e7bb02da33726c diff --git a/lnet/selftest/timer.c b/lnet/selftest/timer.c index 97d9297..3ceec81 100644 --- a/lnet/selftest/timer.c +++ b/lnet/selftest/timer.c @@ -1,70 +1,92 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). * - * Copyright (C) 2001, 2002 Cluster File Systems, Inc. - * Author: Isaac Huang + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html * + * GPL HEADER END + */ +/* + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2011, 2013, Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * lnet/selftest/timer.c + * + * Author: Isaac Huang */ #define DEBUG_SUBSYSTEM S_LNET -#include -#include -#include - #include "selftest.h" /* - * Timers are implemented as a sorted queue of expiry times. The queue - * is slotted, with each slot holding timers which expire in a - * 2**STTIMER_MINPOLL (8) second period. The timers in each slot are + * Timers are implemented as a sorted queue of expiry times. The queue + * is slotted, with each slot holding timers which expire in a + * 2**STTIMER_MINPOLL (8) second period. The timers in each slot are * sorted by increasing expiry time. The number of slots is 2**7 (128), * to cover a time period of 1024 seconds into the future before wrapping. */ -#define STTIMER_MINPOLL 3 /* log2 min poll interval (8 s) */ -#define STTIMER_SLOTTIME (1 << STTIMER_MINPOLL) -#define STTIMER_SLOTTIMEMASK (~(STTIMER_SLOTTIME - 1)) -#define STTIMER_NSLOTS (1 << 7) -#define STTIMER_SLOT(t) (&stt_data.stt_hash[(((t) >> STTIMER_MINPOLL) & \ +#define STTIMER_MINPOLL 3 /* log2 min poll interval (8 s) */ +#define STTIMER_SLOTTIME (1 << STTIMER_MINPOLL) +#define STTIMER_SLOTTIMEMASK (~(STTIMER_SLOTTIME - 1)) +#define STTIMER_NSLOTS (1 << 7) +#define STTIMER_SLOT(t) (&stt_data.stt_hash[(((t) >> STTIMER_MINPOLL) & \ (STTIMER_NSLOTS - 1))]) -struct st_timer_data { - spinlock_t stt_lock; - /* start time of the slot processed previously */ - cfs_time_t stt_prev_slot; - struct list_head stt_hash[STTIMER_NSLOTS]; - int stt_shuttingdown; -#ifdef __KERNEL__ - int stt_nthreads; -#endif +static struct st_timer_data { + spinlock_t stt_lock; + /* start time of the slot processed previously */ + time64_t stt_prev_slot; + struct list_head stt_hash[STTIMER_NSLOTS]; + int stt_shuttingdown; + wait_queue_head_t stt_waitq; + int stt_nthreads; } stt_data; void -stt_add_timer (stt_timer_t *timer) +stt_add_timer(struct stt_timer *timer) { - struct list_head *pos; + struct list_head *pos; - spin_lock(&stt_data.stt_lock); + spin_lock(&stt_data.stt_lock); -#ifdef __KERNEL__ - LASSERT (stt_data.stt_nthreads > 0); -#endif - LASSERT (!stt_data.stt_shuttingdown); - LASSERT (timer->stt_func != NULL); - LASSERT (list_empty(&timer->stt_list)); - LASSERT (cfs_time_after(timer->stt_expires, cfs_time_current_sec())); + LASSERT(stt_data.stt_nthreads > 0); + LASSERT(!stt_data.stt_shuttingdown); + LASSERT(timer->stt_func != NULL); + LASSERT(list_empty(&timer->stt_list)); + LASSERT(timer->stt_expires > ktime_get_real_seconds()); - /* a simple insertion sort */ - list_for_each_prev (pos, STTIMER_SLOT(timer->stt_expires)) { - stt_timer_t *old = list_entry(pos, stt_timer_t, stt_list); + /* a simple insertion sort */ + list_for_each_prev(pos, STTIMER_SLOT(timer->stt_expires)) { + struct stt_timer *old = list_entry(pos, struct stt_timer, + stt_list); - if (cfs_time_aftereq(timer->stt_expires, old->stt_expires)) - break; - } - list_add(&timer->stt_list, pos); + if (timer->stt_expires >= old->stt_expires) + break; + } + list_add(&timer->stt_list, pos); - spin_unlock(&stt_data.stt_lock); + spin_unlock(&stt_data.stt_lock); } /* @@ -77,129 +99,110 @@ stt_add_timer (stt_timer_t *timer) * another CPU. */ int -stt_del_timer (stt_timer_t *timer) +stt_del_timer(struct stt_timer *timer) { - int ret = 0; + int ret = 0; - spin_lock(&stt_data.stt_lock); + spin_lock(&stt_data.stt_lock); -#ifdef __KERNEL__ - LASSERT (stt_data.stt_nthreads > 0); -#endif - LASSERT (!stt_data.stt_shuttingdown); + LASSERT(stt_data.stt_nthreads > 0); + LASSERT(!stt_data.stt_shuttingdown); - if (!list_empty(&timer->stt_list)) { - ret = 1; - list_del_init(&timer->stt_list); - } + if (!list_empty(&timer->stt_list)) { + ret = 1; + list_del_init(&timer->stt_list); + } - spin_unlock(&stt_data.stt_lock); - return ret; + spin_unlock(&stt_data.stt_lock); + return ret; } /* called with stt_data.stt_lock held */ -int -stt_expire_list (struct list_head *slot, cfs_time_t now) +static int +stt_expire_list(struct list_head *slot, time64_t now) { - int expired = 0; - stt_timer_t *timer; + int expired = 0; + struct stt_timer *timer; + + while (!list_empty(slot)) { + timer = list_entry(slot->next, struct stt_timer, stt_list); - while (!list_empty(slot)) { - timer = list_entry(slot->next, stt_timer_t, stt_list); + if (timer->stt_expires > now) + break; - if (cfs_time_after(timer->stt_expires, now)) - break; + list_del_init(&timer->stt_list); + spin_unlock(&stt_data.stt_lock); - list_del_init(&timer->stt_list); - spin_unlock(&stt_data.stt_lock); + expired++; + (*timer->stt_func) (timer->stt_data); - expired++; - (*timer->stt_func) (timer->stt_data); - - spin_lock(&stt_data.stt_lock); - } + spin_lock(&stt_data.stt_lock); + } - return expired; + return expired; } -int -stt_check_timers (cfs_time_t *last) +static int +stt_check_timers(time64_t *last) { - int expired = 0; - cfs_time_t now; - cfs_time_t this_slot; + int expired = 0; + time64_t now; + time64_t this_slot; - now = cfs_time_current_sec(); - this_slot = now & STTIMER_SLOTTIMEMASK; + now = ktime_get_real_seconds(); + this_slot = now & STTIMER_SLOTTIMEMASK; - spin_lock(&stt_data.stt_lock); + spin_lock(&stt_data.stt_lock); - while (cfs_time_aftereq(this_slot, *last)) { - expired += stt_expire_list(STTIMER_SLOT(this_slot), now); - this_slot = cfs_time_sub(this_slot, STTIMER_SLOTTIME); - } + while (this_slot >= *last) { + expired += stt_expire_list(STTIMER_SLOT(this_slot), now); + this_slot = this_slot - STTIMER_SLOTTIME; + } - *last = now & STTIMER_SLOTTIMEMASK; - spin_unlock(&stt_data.stt_lock); - return expired; + *last = now & STTIMER_SLOTTIMEMASK; + spin_unlock(&stt_data.stt_lock); + return expired; } -#ifdef __KERNEL__ -int +static int stt_timer_main (void *arg) { - UNUSED(arg); + int rc = 0; - cfs_daemonize("st_timer"); cfs_block_allsigs(); - while (!stt_data.stt_shuttingdown) { - stt_check_timers(&stt_data.stt_prev_slot); + while (!stt_data.stt_shuttingdown) { + stt_check_timers(&stt_data.stt_prev_slot); - set_current_state(CFS_TASK_INTERRUPTIBLE); - cfs_schedule_timeout(CFS_TASK_INTERRUPTIBLE, - cfs_time_seconds(STTIMER_SLOTTIME)); - } + rc = wait_event_timeout(stt_data.stt_waitq, + stt_data.stt_shuttingdown, + cfs_time_seconds(STTIMER_SLOTTIME)); + } - spin_lock(&stt_data.stt_lock); - stt_data.stt_nthreads--; - spin_unlock(&stt_data.stt_lock); - return 0; + spin_lock(&stt_data.stt_lock); + stt_data.stt_nthreads--; + spin_unlock(&stt_data.stt_lock); + return rc; } -int +static int stt_start_timer_thread (void) { - long pid; - - LASSERT (!stt_data.stt_shuttingdown); - - pid = cfs_kernel_thread(stt_timer_main, NULL, 0); - if (pid < 0) - return (int)pid; - - spin_lock(&stt_data.stt_lock); - stt_data.stt_nthreads++; - spin_unlock(&stt_data.stt_lock); - return 0; -} + struct task_struct *task; -#else /* !__KERNEL__ */ + LASSERT(!stt_data.stt_shuttingdown); -int -stt_check_events (void) -{ - return stt_check_timers(&stt_data.stt_prev_slot); -} + task = kthread_run(stt_timer_main, NULL, "st_timer"); + if (IS_ERR(task)) + return PTR_ERR(task); -int -stt_poll_interval (void) -{ - return STTIMER_SLOTTIME; + spin_lock(&stt_data.stt_lock); + stt_data.stt_nthreads++; + spin_unlock(&stt_data.stt_lock); + return 0; } -#endif int stt_startup (void) @@ -208,40 +211,37 @@ stt_startup (void) int i; stt_data.stt_shuttingdown = 0; - stt_data.stt_prev_slot = cfs_time_current_sec() & STTIMER_SLOTTIMEMASK; + stt_data.stt_prev_slot = ktime_get_real_seconds() & STTIMER_SLOTTIMEMASK; - spin_lock_init(&stt_data.stt_lock); + spin_lock_init(&stt_data.stt_lock); for (i = 0; i < STTIMER_NSLOTS; i++) - CFS_INIT_LIST_HEAD(&stt_data.stt_hash[i]); + INIT_LIST_HEAD(&stt_data.stt_hash[i]); -#ifdef __KERNEL__ - stt_data.stt_nthreads = 0; - rc = stt_start_timer_thread(); - if (rc != 0) - CERROR ("Can't spawn timer, stt_startup() has failed: %d\n", rc); -#endif + stt_data.stt_nthreads = 0; + init_waitqueue_head(&stt_data.stt_waitq); + rc = stt_start_timer_thread(); + if (rc != 0) + CERROR ("Can't spawn timer thread: %d\n", rc); return rc; } void -stt_shutdown (void) +stt_shutdown(void) { - int i; + int i; - spin_lock(&stt_data.stt_lock); + spin_lock(&stt_data.stt_lock); - for (i = 0; i < STTIMER_NSLOTS; i++) - LASSERT (list_empty(&stt_data.stt_hash[i])); + for (i = 0; i < STTIMER_NSLOTS; i++) + LASSERT(list_empty(&stt_data.stt_hash[i])); - stt_data.stt_shuttingdown = 1; + stt_data.stt_shuttingdown = 1; -#ifdef __KERNEL__ - lst_wait_until(stt_data.stt_nthreads == 0, stt_data.stt_lock, - "waiting for %d threads to terminate\n", - stt_data.stt_nthreads); -#endif + wake_up(&stt_data.stt_waitq); + lst_wait_until(stt_data.stt_nthreads == 0, stt_data.stt_lock, + "waiting for %d threads to terminate\n", + stt_data.stt_nthreads); - spin_unlock(&stt_data.stt_lock); - return; + spin_unlock(&stt_data.stt_lock); }