lkml.org 
[lkml]   [2016]   [Dec]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC 11/32] mars: add new module lib_timing
    Date
    Signed-off-by: Thomas Schoebel-Theuer <tst@schoebel-theuer.de>
    ---
    drivers/staging/mars/lib/lib_timing.c | 68 +++++++++++++
    include/linux/brick/lib_timing.h | 182 ++++++++++++++++++++++++++++++++++
    2 files changed, 250 insertions(+)
    create mode 100644 drivers/staging/mars/lib/lib_timing.c
    create mode 100644 include/linux/brick/lib_timing.h

    diff --git a/drivers/staging/mars/lib/lib_timing.c b/drivers/staging/mars/lib/lib_timing.c
    new file mode 100644
    index 000000000000..1996052cb647
    --- /dev/null
    +++ b/drivers/staging/mars/lib/lib_timing.c
    @@ -0,0 +1,68 @@
    +/*
    + * MARS Long Distance Replication Software
    + *
    + * Copyright (C) 2010-2014 Thomas Schoebel-Theuer
    + * Copyright (C) 2011-2014 1&1 Internet AG
    + *
    + * This program is free software; you can redistribute it and/or modify
    + * it under the terms of the GNU General Public License as published by
    + * the Free Software Foundation; either version 2 of the License, or
    + * (at your option) any later version.
    + *
    + * 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 for more details.
    + */
    +
    +#include <linux/brick/lib_timing.h>
    +
    +#include <linux/kernel.h>
    +#include <linux/module.h>
    +
    +#ifdef CONFIG_DEBUG_KERNEL
    +
    +int report_timing(struct timing_stats *tim, char *str, int maxlen)
    +{
    + int len = 0;
    + int time = 1;
    + int resol = 1;
    +
    + static const char * const units[] = {
    + "us",
    + "ms",
    + "s",
    + "ERROR"
    + };
    + const char *unit = units[0];
    + int unit_index = 0;
    + int i;
    +
    + for (i = 0; i < TIMING_MAX; i++) {
    + int this_len = scnprintf(
    +
    + str, maxlen, "<%d%s = %d (%lld) ", resol, unit, tim->tim_count[i], (
    + long long)tim->tim_count[i] * time);
    +
    + str += this_len;
    + len += this_len;
    + maxlen -= this_len;
    + if (maxlen <= 1)
    + break;
    + resol <<= 1;
    + time <<= 1;
    + if (resol >= 1000) {
    + resol = 1;
    + unit = units[++unit_index];
    + }
    + }
    + return len;
    +}
    +
    +#endif /* CONFIG_DEBUG_KERNEL */
    +
    +struct threshold global_io_threshold = {
    + .thr_limit = 30 * 1000000, /* 30 seconds */
    + .thr_factor = 100,
    + .thr_plus = 0,
    +};
    diff --git a/include/linux/brick/lib_timing.h b/include/linux/brick/lib_timing.h
    new file mode 100644
    index 000000000000..7081d984a2ce
    --- /dev/null
    +++ b/include/linux/brick/lib_timing.h
    @@ -0,0 +1,182 @@
    +/*
    + * MARS Long Distance Replication Software
    + *
    + * Copyright (C) 2010-2014 Thomas Schoebel-Theuer
    + * Copyright (C) 2011-2014 1&1 Internet AG
    + *
    + * This program is free software; you can redistribute it and/or modify
    + * it under the terms of the GNU General Public License as published by
    + * the Free Software Foundation; either version 2 of the License, or
    + * (at your option) any later version.
    + *
    + * 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 for more details.
    + */
    +
    +#ifndef LIB_TIMING_H
    +#define LIB_TIMING_H
    +
    +#include <linux/sched.h>
    +
    +/* Simple infrastructure for timing of arbitrary operations and creation
    + * of some simple histogram statistics.
    + */
    +
    +#define TIMING_MAX 24
    +
    +struct timing_stats {
    +#ifdef CONFIG_DEBUG_KERNEL
    + int tim_count[TIMING_MAX];
    +
    +#endif
    +};
    +
    +#define _TIME_THIS(_stamp1, _stamp2, _CODE) \
    + ({ \
    + (_stamp1) = cpu_clock(raw_smp_processor_id()); \
    + \
    + _CODE; \
    + \
    + (_stamp2) = cpu_clock(raw_smp_processor_id()); \
    + (_stamp2) - (_stamp1); \
    + })
    +
    +#define TIME_THIS(_CODE) \
    + ({ \
    + unsigned long long _stamp1; \
    + unsigned long long _stamp2; \
    + _TIME_THIS(_stamp1, _stamp2, _CODE); \
    + })
    +
    +#ifdef CONFIG_DEBUG_KERNEL
    +
    +#define _TIME_STATS(_timing, _stamp1, _stamp2, _CODE) \
    + ({ \
    + unsigned long long _time; \
    + unsigned long _tmp; \
    + int _i; \
    + \
    + _time = _TIME_THIS(_stamp1, _stamp2, _CODE); \
    + \
    + _tmp = _time / 1000; /* convert to us */ \
    + _i = 0; \
    + while (_tmp > 0 && _i < TIMING_MAX - 1) { \
    + _tmp >>= 1; \
    + _i++; \
    + } \
    + (_timing)->tim_count[_i]++; \
    + _time; \
    + })
    +
    +#define TIME_STATS(_timing, _CODE) \
    + ({ \
    + unsigned long long _stamp1; \
    + unsigned long long _stamp2; \
    + _TIME_STATS(_timing, _stamp1, _stamp2, _CODE); \
    + })
    +
    +extern int report_timing(struct timing_stats *tim, char *str, int maxlen);
    +
    +#else /* CONFIG_DEBUG_KERNEL */
    +
    +#define _TIME_STATS(_timing, _stamp1, _stamp2, _CODE) \
    + ((void)_timing, (_stamp1) = (_stamp2) = cpu_clock(raw_smp_processor_id()), _CODE, 0)
    +
    +#define TIME_STATS(_timing, _CODE) \
    + ((void)_timing, _CODE, 0)
    +
    +#define report_timing(tim, str, maxlen) ((void)tim, 0)
    +
    +#endif /* CONFIG_DEBUG_KERNEL */
    +
    +/* A banning represents some overloaded resource.
    + *
    + * Whenever overload is detected, you should call banning_hit()
    + * telling that the overload is assumed / estimated to continue
    + * for some duration in time.
    + *
    + * ATTENTION! These operations are deliberately raceful.
    + * They are meant to deliver _hints_ (e.g. for IO scheduling
    + * decisions etc), not hard facts!
    + *
    + * If you need locking, just surround these operations
    + * with locking by yourself.
    + */
    +struct banning {
    + long long ban_last_hit;
    +
    + /* statistical */
    + int ban_renew_count;
    + int ban_count;
    +};
    +
    +static inline
    +bool banning_hit(struct banning *ban, long long duration)
    +{
    + long long now = cpu_clock(raw_smp_processor_id());
    + bool hit = ban->ban_last_hit >= now;
    + long long new_hit = now + duration;
    +
    + ban->ban_renew_count++;
    + if (!ban->ban_last_hit || ban->ban_last_hit < new_hit) {
    + ban->ban_last_hit = new_hit;
    + ban->ban_count++;
    + }
    + return hit;
    +}
    +
    +static inline
    +bool banning_is_hit(struct banning *ban)
    +{
    + long long now = cpu_clock(raw_smp_processor_id());
    +
    + return (ban->ban_last_hit && ban->ban_last_hit >= now);
    +}
    +
    +extern inline
    +void banning_reset(struct banning *ban)
    +{
    + ban->ban_last_hit = 0;
    +}
    +
    +/* Threshold: trigger a banning whenever some latency threshold
    + * is exceeded.
    + */
    +struct threshold {
    + struct banning *thr_ban;
    +
    + struct threshold *thr_parent; /* support hierarchies */
    + /* tunables */
    + int thr_limit; /* in us */
    + int thr_factor; /* in % */
    + int thr_plus; /* in us */
    + /* statistical */
    + int thr_max; /* in ms */
    + int thr_triggered;
    + int thr_true_hit;
    +};
    +
    +static inline
    +void threshold_check(struct threshold *thr, long long latency)
    +{
    + int ms = latency >> 6; /* ignore small rounding error */
    +
    + while (thr) {
    + if (ms > thr->thr_max)
    + thr->thr_max = ms;
    + if (thr->thr_limit &&
    + latency > (long long)thr->thr_limit * 1000) {
    + thr->thr_triggered++;
    + if (thr->thr_ban &&
    + !banning_hit(thr->thr_ban, latency * thr->thr_factor / 100 + thr->thr_plus * 1000))
    + thr->thr_true_hit++;
    + }
    + thr = thr->thr_parent;
    + }
    +}
    +
    +extern struct threshold global_io_threshold;
    +
    +#endif
    --
    2.11.0
    \
     
     \ /
      Last update: 2016-12-31 00:04    [W:5.680 / U:0.324 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site