Release 4.11 drivers/staging/lustre/lnet/selftest/timer.c
/*
* 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).
*
* 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, 2012, 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 <isaac@clusterfs.com>
*/
#define DEBUG_SUBSYSTEM S_LNET
#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
* 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 BIT(STTIMER_MINPOLL)
#define STTIMER_SLOTTIMEMASK (~(STTIMER_SLOTTIME - 1))
#define STTIMER_NSLOTS BIT(7)
#define STTIMER_SLOT(t) (&stt_data.stt_hash[(((t) >> STTIMER_MINPOLL) & \
(STTIMER_NSLOTS - 1))])
static struct st_timer_data {
spinlock_t stt_lock;
unsigned long stt_prev_slot; /* start time of the slot processed
* previously
*/
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(struct stt_timer *timer)
{
struct list_head *pos;
spin_lock(&stt_data.stt_lock);
LASSERT(stt_data.stt_nthreads > 0);
LASSERT(!stt_data.stt_shuttingdown);
LASSERT(timer->stt_func);
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)) {
struct stt_timer *old = list_entry(pos, struct stt_timer,
stt_list);
if (timer->stt_expires >= old->stt_expires)
break;
}
list_add(&timer->stt_list, pos);
spin_unlock(&stt_data.stt_lock);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peng Tao | 112 | 92.56% | 1 | 33.33% |
Bhumika Goyal | 6 | 4.96% | 1 | 33.33% |
Arnd Bergmann | 3 | 2.48% | 1 | 33.33% |
Total | 121 | 100.00% | 3 | 100.00% |
/*
* The function returns whether it has deactivated a pending timer or not.
* (ie. del_timer() of an inactive timer returns 0, del_timer() of an
* active timer returns 1.)
*
* CAVEAT EMPTOR:
* When 0 is returned, it is possible that timer->stt_func _is_ running on
* another CPU.
*/
int
stt_del_timer(struct stt_timer *timer)
{
int ret = 0;
spin_lock(&stt_data.stt_lock);
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);
}
spin_unlock(&stt_data.stt_lock);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peng Tao | 74 | 97.37% | 1 | 50.00% |
Bhumika Goyal | 2 | 2.63% | 1 | 50.00% |
Total | 76 | 100.00% | 2 | 100.00% |
/* called with stt_data.stt_lock held */
static int
stt_expire_list(struct list_head *slot, time64_t now)
{
int expired = 0;
struct stt_timer *timer;
while (!list_empty(slot)) {
timer = list_entry(slot->next, struct stt_timer, stt_list);
if (timer->stt_expires > now)
break;
list_del_init(&timer->stt_list);
spin_unlock(&stt_data.stt_lock);
expired++;
(*timer->stt_func) (timer->stt_data);
spin_lock(&stt_data.stt_lock);
}
return expired;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peng Tao | 92 | 92.93% | 1 | 25.00% |
Bhumika Goyal | 4 | 4.04% | 1 | 25.00% |
Arnd Bergmann | 2 | 2.02% | 1 | 25.00% |
Anton Saraev | 1 | 1.01% | 1 | 25.00% |
Total | 99 | 100.00% | 4 | 100.00% |
static int
stt_check_timers(unsigned long *last)
{
int expired = 0;
time64_t now;
unsigned long this_slot;
now = ktime_get_real_seconds();
this_slot = now & STTIMER_SLOTTIMEMASK;
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);
}
*last = now & STTIMER_SLOTTIMEMASK;
spin_unlock(&stt_data.stt_lock);
return expired;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peng Tao | 86 | 92.47% | 1 | 25.00% |
Greg Kroah-Hartman | 4 | 4.30% | 1 | 25.00% |
Arnd Bergmann | 2 | 2.15% | 1 | 25.00% |
Anton Saraev | 1 | 1.08% | 1 | 25.00% |
Total | 93 | 100.00% | 4 | 100.00% |
static int
stt_timer_main(void *arg)
{
int rc = 0;
cfs_block_allsigs();
while (!stt_data.stt_shuttingdown) {
stt_check_timers(&stt_data.stt_prev_slot);
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 rc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peng Tao | 68 | 88.31% | 1 | 33.33% |
James Simmons | 8 | 10.39% | 1 | 33.33% |
Anton Saraev | 1 | 1.30% | 1 | 33.33% |
Total | 77 | 100.00% | 3 | 100.00% |
static int
stt_start_timer_thread(void)
{
struct task_struct *task;
LASSERT(!stt_data.stt_shuttingdown);
task = kthread_run(stt_timer_main, NULL, "st_timer");
if (IS_ERR(task))
return PTR_ERR(task);
spin_lock(&stt_data.stt_lock);
stt_data.stt_nthreads++;
spin_unlock(&stt_data.stt_lock);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peng Tao | 66 | 95.65% | 1 | 33.33% |
Greg Kroah-Hartman | 2 | 2.90% | 1 | 33.33% |
Anton Saraev | 1 | 1.45% | 1 | 33.33% |
Total | 69 | 100.00% | 3 | 100.00% |
int
stt_startup(void)
{
int rc = 0;
int i;
stt_data.stt_shuttingdown = 0;
stt_data.stt_prev_slot = ktime_get_real_seconds() & STTIMER_SLOTTIMEMASK;
spin_lock_init(&stt_data.stt_lock);
for (i = 0; i < STTIMER_NSLOTS; i++)
INIT_LIST_HEAD(&stt_data.stt_hash[i]);
stt_data.stt_nthreads = 0;
init_waitqueue_head(&stt_data.stt_waitq);
rc = stt_start_timer_thread();
if (rc)
CERROR("Can't spawn timer thread: %d\n", rc);
return rc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peng Tao | 94 | 98.95% | 1 | 50.00% |
Arnd Bergmann | 1 | 1.05% | 1 | 50.00% |
Total | 95 | 100.00% | 2 | 100.00% |
void
stt_shutdown(void)
{
int i;
spin_lock(&stt_data.stt_lock);
for (i = 0; i < STTIMER_NSLOTS; i++)
LASSERT(list_empty(&stt_data.stt_hash[i]));
stt_data.stt_shuttingdown = 1;
wake_up(&stt_data.stt_waitq);
lst_wait_until(!stt_data.stt_nthreads, stt_data.stt_lock,
"waiting for %d threads to terminate\n",
stt_data.stt_nthreads);
spin_unlock(&stt_data.stt_lock);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peng Tao | 84 | 98.82% | 1 | 50.00% |
James Simmons | 1 | 1.18% | 1 | 50.00% |
Total | 85 | 100.00% | 2 | 100.00% |
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peng Tao | 737 | 94.13% | 1 | 8.33% |
James Simmons | 12 | 1.53% | 4 | 33.33% |
Bhumika Goyal | 12 | 1.53% | 1 | 8.33% |
Arnd Bergmann | 8 | 1.02% | 1 | 8.33% |
Greg Kroah-Hartman | 8 | 1.02% | 2 | 16.67% |
Anton Saraev | 4 | 0.51% | 1 | 8.33% |
Jeremiah Mahler | 1 | 0.13% | 1 | 8.33% |
Oleg Drokin | 1 | 0.13% | 1 | 8.33% |
Total | 783 | 100.00% | 12 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.