License cleanup: add SPDX GPL-2.0 license identifier to files with no license
Many source files in the tree are missing licensing information, which
makes it harder for compliance tools to determine the correct license.
By default all files without license information are under the default
license of the kernel, which is GPL version 2.
Update the files which contain no license information with the 'GPL-2.0'
SPDX license identifier. The SPDX identifier is a legally binding
shorthand, which can be used instead of the full boiler plate text.
This patch is based on work done by Thomas Gleixner and Kate Stewart and
Philippe Ombredanne.
How this work was done:
Patches were generated and checked against linux-4.14-rc6 for a subset of
the use cases:
- file had no licensing information it it.
- file was a */uapi/* one with no licensing information in it,
- file was a */uapi/* one with existing licensing information,
Further patches will be generated in subsequent months to fix up cases
where non-standard license headers were used, and references to license
had to be inferred by heuristics based on keywords.
The analysis to determine which SPDX License Identifier to be applied to
a file was done in a spreadsheet of side by side results from of the
output of two independent scanners (ScanCode & Windriver) producing SPDX
tag:value files created by Philippe Ombredanne. Philippe prepared the
base worksheet, and did an initial spot review of a few 1000 files.
The 4.13 kernel was the starting point of the analysis with 60,537 files
assessed. Kate Stewart did a file by file comparison of the scanner
results in the spreadsheet to determine which SPDX license identifier(s)
to be applied to the file. She confirmed any determination that was not
immediately clear with lawyers working with the Linux Foundation.
Criteria used to select files for SPDX license identifier tagging was:
- Files considered eligible had to be source code files.
- Make and config files were included as candidates if they contained >5
lines of source
- File already had some variant of a license header in it (even if <5
lines).
All documentation files were explicitly excluded.
The following heuristics were used to determine which SPDX license
identifiers to apply.
- when both scanners couldn't find any license traces, file was
considered to have no license information in it, and the top level
COPYING file license applied.
For non */uapi/* files that summary was:
SPDX license identifier # files
---------------------------------------------------|-------
GPL-2.0 11139
and resulted in the first patch in this series.
If that file was a */uapi/* path one, it was "GPL-2.0 WITH
Linux-syscall-note" otherwise it was "GPL-2.0". Results of that was:
SPDX license identifier # files
---------------------------------------------------|-------
GPL-2.0 WITH Linux-syscall-note 930
and resulted in the second patch in this series.
- if a file had some form of licensing information in it, and was one
of the */uapi/* ones, it was denoted with the Linux-syscall-note if
any GPL family license was found in the file or had no licensing in
it (per prior point). Results summary:
SPDX license identifier # files
---------------------------------------------------|------
GPL-2.0 WITH Linux-syscall-note 270
GPL-2.0+ WITH Linux-syscall-note 169
((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) 21
((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) 17
LGPL-2.1+ WITH Linux-syscall-note 15
GPL-1.0+ WITH Linux-syscall-note 14
((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) 5
LGPL-2.0+ WITH Linux-syscall-note 4
LGPL-2.1 WITH Linux-syscall-note 3
((GPL-2.0 WITH Linux-syscall-note) OR MIT) 3
((GPL-2.0 WITH Linux-syscall-note) AND MIT) 1
and that resulted in the third patch in this series.
- when the two scanners agreed on the detected license(s), that became
the concluded license(s).
- when there was disagreement between the two scanners (one detected a
license but the other didn't, or they both detected different
licenses) a manual inspection of the file occurred.
- In most cases a manual inspection of the information in the file
resulted in a clear resolution of the license that should apply (and
which scanner probably needed to revisit its heuristics).
- When it was not immediately clear, the license identifier was
confirmed with lawyers working with the Linux Foundation.
- If there was any question as to the appropriate license identifier,
the file was flagged for further research and to be revisited later
in time.
In total, over 70 hours of logged manual review was done on the
spreadsheet to determine the SPDX license identifiers to apply to the
source files by Kate, Philippe, Thomas and, in some cases, confirmation
by lawyers working with the Linux Foundation.
Kate also obtained a third independent scan of the 4.13 code base from
FOSSology, and compared selected files where the other two scanners
disagreed against that SPDX file, to see if there was new insights. The
Windriver scanner is based on an older version of FOSSology in part, so
they are related.
Thomas did random spot checks in about 500 files from the spreadsheets
for the uapi headers and agreed with SPDX license identifier in the
files he inspected. For the non-uapi files Thomas did random spot checks
in about 15000 files.
In initial set of patches against 4.14-rc6, 3 files were found to have
copy/paste license identifier errors, and have been fixed to reflect the
correct identifier.
Additionally Philippe spent 10 hours this week doing a detailed manual
inspection and review of the 12,461 patched files from the initial patch
version early this week with:
- a full scancode scan run, collecting the matched texts, detected
license ids and scores
- reviewing anything where there was a license detected (about 500+
files) to ensure that the applied SPDX license was correct
- reviewing anything where there was no detection but the patch license
was not GPL-2.0 WITH Linux-syscall-note to ensure that the applied
SPDX license was correct
This produced a worksheet with 20 files needing minor correction. This
worksheet was then exported into 3 different .csv files for the
different types of files to be modified.
These .csv files were then reviewed by Greg. Thomas wrote a script to
parse the csv files and add the proper SPDX tag to the file, in the
format that the file expected. This script was further refined by Greg
based on the output to detect more types of files automatically and to
distinguish between header and source .c files (which need different
comment types.) Finally Greg ran the script using the .csv files to
generate the patches.
Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org>
Reviewed-by: Philippe Ombredanne <pombredanne@nexb.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-11-01 22:07:57 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2013-04-20 03:10:49 +08:00
|
|
|
/*
|
2015-04-14 19:19:42 +08:00
|
|
|
* kernel/sched/loadavg.c
|
2013-04-20 03:10:49 +08:00
|
|
|
*
|
2015-04-14 19:19:42 +08:00
|
|
|
* This file contains the magic bits required to compute the global loadavg
|
|
|
|
* figure. Its a silly number but people think its important. We go through
|
|
|
|
* great pains to make it work on big machines and tickless kernels.
|
2013-04-20 03:10:49 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/export.h>
|
2017-02-08 15:45:17 +08:00
|
|
|
#include <linux/sched/loadavg.h>
|
2013-04-20 03:10:49 +08:00
|
|
|
|
|
|
|
#include "sched.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Global load-average calculations
|
|
|
|
*
|
|
|
|
* We take a distributed and async approach to calculating the global load-avg
|
|
|
|
* in order to minimize overhead.
|
|
|
|
*
|
|
|
|
* The global load average is an exponentially decaying average of nr_running +
|
|
|
|
* nr_uninterruptible.
|
|
|
|
*
|
|
|
|
* Once every LOAD_FREQ:
|
|
|
|
*
|
|
|
|
* nr_active = 0;
|
|
|
|
* for_each_possible_cpu(cpu)
|
|
|
|
* nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible;
|
|
|
|
*
|
|
|
|
* avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n)
|
|
|
|
*
|
|
|
|
* Due to a number of reasons the above turns in the mess below:
|
|
|
|
*
|
|
|
|
* - for_each_possible_cpu() is prohibitively expensive on machines with
|
|
|
|
* serious number of cpus, therefore we need to take a distributed approach
|
|
|
|
* to calculating nr_active.
|
|
|
|
*
|
|
|
|
* \Sum_i x_i(t) = \Sum_i x_i(t) - x_i(t_0) | x_i(t_0) := 0
|
|
|
|
* = \Sum_i { \Sum_j=1 x_i(t_j) - x_i(t_j-1) }
|
|
|
|
*
|
|
|
|
* So assuming nr_active := 0 when we start out -- true per definition, we
|
|
|
|
* can simply take per-cpu deltas and fold those into a global accumulate
|
|
|
|
* to obtain the same result. See calc_load_fold_active().
|
|
|
|
*
|
|
|
|
* Furthermore, in order to avoid synchronizing all per-cpu delta folding
|
|
|
|
* across the machine, we assume 10 ticks is sufficient time for every
|
|
|
|
* cpu to have completed this task.
|
|
|
|
*
|
|
|
|
* This places an upper-bound on the IRQ-off latency of the machine. Then
|
|
|
|
* again, being late doesn't loose the delta, just wrecks the sample.
|
|
|
|
*
|
|
|
|
* - cpu_rq()->nr_uninterruptible isn't accurately tracked per-cpu because
|
|
|
|
* this would add another cross-cpu cacheline miss and atomic operation
|
|
|
|
* to the wakeup path. Instead we increment on whatever cpu the task ran
|
|
|
|
* when it went into uninterruptible state and decrement on whatever cpu
|
|
|
|
* did the wakeup. This means that only the sum of nr_uninterruptible over
|
|
|
|
* all cpus yields the correct result.
|
|
|
|
*
|
|
|
|
* This covers the NO_HZ=n code, for extra head-aches, see the comment below.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Variables and functions for calc_load */
|
|
|
|
atomic_long_t calc_load_tasks;
|
|
|
|
unsigned long calc_load_update;
|
|
|
|
unsigned long avenrun[3];
|
|
|
|
EXPORT_SYMBOL(avenrun); /* should be removed */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get_avenrun - get the load average array
|
|
|
|
* @loads: pointer to dest load array
|
|
|
|
* @offset: offset to add
|
|
|
|
* @shift: shift count to shift the result left
|
|
|
|
*
|
|
|
|
* These values are estimates at best, so no need for locking.
|
|
|
|
*/
|
|
|
|
void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
|
|
|
|
{
|
|
|
|
loads[0] = (avenrun[0] + offset) << shift;
|
|
|
|
loads[1] = (avenrun[1] + offset) << shift;
|
|
|
|
loads[2] = (avenrun[2] + offset) << shift;
|
|
|
|
}
|
|
|
|
|
2016-07-13 00:33:56 +08:00
|
|
|
long calc_load_fold_active(struct rq *this_rq, long adjust)
|
2013-04-20 03:10:49 +08:00
|
|
|
{
|
|
|
|
long nr_active, delta = 0;
|
|
|
|
|
2016-07-13 00:33:56 +08:00
|
|
|
nr_active = this_rq->nr_running - adjust;
|
2015-04-14 19:19:42 +08:00
|
|
|
nr_active += (long)this_rq->nr_uninterruptible;
|
2013-04-20 03:10:49 +08:00
|
|
|
|
|
|
|
if (nr_active != this_rq->calc_load_active) {
|
|
|
|
delta = nr_active - this_rq->calc_load_active;
|
|
|
|
this_rq->calc_load_active = nr_active;
|
|
|
|
}
|
|
|
|
|
|
|
|
return delta;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* a1 = a0 * e + a * (1 - e)
|
|
|
|
*/
|
|
|
|
static unsigned long
|
|
|
|
calc_load(unsigned long load, unsigned long exp, unsigned long active)
|
|
|
|
{
|
sched/loadavg: Fix loadavg artifacts on fully idle and on fully loaded systems
Systems show a minimal load average of 0.00, 0.01, 0.05 even when they
have no load at all.
Uptime and /proc/loadavg on all systems with kernels released during the
last five years up until kernel version 4.6-rc5, show a 5- and 15-minute
minimum loadavg of 0.01 and 0.05 respectively. This should be 0.00 on
idle systems, but the way the kernel calculates this value prevents it
from getting lower than the mentioned values.
Likewise but not as obviously noticeable, a fully loaded system with no
processes waiting, shows a maximum 1/5/15 loadavg of 1.00, 0.99, 0.95
(multiplied by number of cores).
Once the (old) load becomes 93 or higher, it mathematically can never
get lower than 93, even when the active (load) remains 0 forever.
This results in the strange 0.00, 0.01, 0.05 uptime values on idle
systems. Note: 93/2048 = 0.0454..., which rounds up to 0.05.
It is not correct to add a 0.5 rounding (=1024/2048) here, since the
result from this function is fed back into the next iteration again,
so the result of that +0.5 rounding value then gets multiplied by
(2048-2037), and then rounded again, so there is a virtual "ghost"
load created, next to the old and active load terms.
By changing the way the internally kept value is rounded, that internal
value equivalent now can reach 0.00 on idle, and 1.00 on full load. Upon
increasing load, the internally kept load value is rounded up, when the
load is decreasing, the load value is rounded down.
The modified code was tested on nohz=off and nohz kernels. It was tested
on vanilla kernel 4.6-rc5 and on centos 7.1 kernel 3.10.0-327. It was
tested on single, dual, and octal cores system. It was tested on virtual
hosts and bare hardware. No unwanted effects have been observed, and the
problems that the patch intended to fix were indeed gone.
Tested-by: Damien Wyart <damien.wyart@free.fr>
Signed-off-by: Vik Heyndrickx <vik.heyndrickx@veribox.net>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: <stable@vger.kernel.org>
Cc: Doug Smythies <dsmythies@telus.net>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: 0f004f5a696a ("sched: Cure more NO_HZ load average woes")
Link: http://lkml.kernel.org/r/e8d32bff-d544-7748-72b5-3c86cc71f09f@veribox.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-29 02:46:28 +08:00
|
|
|
unsigned long newload;
|
|
|
|
|
|
|
|
newload = load * exp + active * (FIXED_1 - exp);
|
|
|
|
if (active >= load)
|
|
|
|
newload += FIXED_1-1;
|
|
|
|
|
|
|
|
return newload / FIXED_1;
|
2013-04-20 03:10:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_NO_HZ_COMMON
|
|
|
|
/*
|
|
|
|
* Handle NO_HZ for the global load-average.
|
|
|
|
*
|
|
|
|
* Since the above described distributed algorithm to compute the global
|
|
|
|
* load-average relies on per-cpu sampling from the tick, it is affected by
|
|
|
|
* NO_HZ.
|
|
|
|
*
|
2017-06-19 10:12:00 +08:00
|
|
|
* The basic idea is to fold the nr_active delta into a global NO_HZ-delta upon
|
2013-04-20 03:10:49 +08:00
|
|
|
* entering NO_HZ state such that we can include this as an 'extra' cpu delta
|
|
|
|
* when we read the global state.
|
|
|
|
*
|
|
|
|
* Obviously reality has to ruin such a delightfully simple scheme:
|
|
|
|
*
|
|
|
|
* - When we go NO_HZ idle during the window, we can negate our sample
|
|
|
|
* contribution, causing under-accounting.
|
|
|
|
*
|
2017-06-19 10:12:00 +08:00
|
|
|
* We avoid this by keeping two NO_HZ-delta counters and flipping them
|
2013-04-20 03:10:49 +08:00
|
|
|
* when the window starts, thus separating old and new NO_HZ load.
|
|
|
|
*
|
|
|
|
* The only trick is the slight shift in index flip for read vs write.
|
|
|
|
*
|
|
|
|
* 0s 5s 10s 15s
|
|
|
|
* +10 +10 +10 +10
|
|
|
|
* |-|-----------|-|-----------|-|-----------|-|
|
|
|
|
* r:0 0 1 1 0 0 1 1 0
|
|
|
|
* w:0 1 1 0 0 1 1 0 0
|
|
|
|
*
|
2017-06-19 10:12:00 +08:00
|
|
|
* This ensures we'll fold the old NO_HZ contribution in this window while
|
2013-04-20 03:10:49 +08:00
|
|
|
* accumlating the new one.
|
|
|
|
*
|
2017-06-19 10:12:00 +08:00
|
|
|
* - When we wake up from NO_HZ during the window, we push up our
|
2013-04-20 03:10:49 +08:00
|
|
|
* contribution, since we effectively move our sample point to a known
|
|
|
|
* busy state.
|
|
|
|
*
|
|
|
|
* This is solved by pushing the window forward, and thus skipping the
|
2017-06-19 10:12:00 +08:00
|
|
|
* sample, for this cpu (effectively using the NO_HZ-delta for this cpu which
|
2013-04-20 03:10:49 +08:00
|
|
|
* was in effect at the time the window opened). This also solves the issue
|
2017-06-19 10:12:00 +08:00
|
|
|
* of having to deal with a cpu having been in NO_HZ for multiple LOAD_FREQ
|
|
|
|
* intervals.
|
2013-04-20 03:10:49 +08:00
|
|
|
*
|
|
|
|
* When making the ILB scale, we should try to pull this in as well.
|
|
|
|
*/
|
2017-06-19 10:12:00 +08:00
|
|
|
static atomic_long_t calc_load_nohz[2];
|
2013-04-20 03:10:49 +08:00
|
|
|
static int calc_load_idx;
|
|
|
|
|
|
|
|
static inline int calc_load_write_idx(void)
|
|
|
|
{
|
|
|
|
int idx = calc_load_idx;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* See calc_global_nohz(), if we observe the new index, we also
|
|
|
|
* need to observe the new update time.
|
|
|
|
*/
|
|
|
|
smp_rmb();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the folding window started, make sure we start writing in the
|
2017-06-19 10:12:00 +08:00
|
|
|
* next NO_HZ-delta.
|
2013-04-20 03:10:49 +08:00
|
|
|
*/
|
2017-02-17 20:07:31 +08:00
|
|
|
if (!time_before(jiffies, READ_ONCE(calc_load_update)))
|
2013-04-20 03:10:49 +08:00
|
|
|
idx++;
|
|
|
|
|
|
|
|
return idx & 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int calc_load_read_idx(void)
|
|
|
|
{
|
|
|
|
return calc_load_idx & 1;
|
|
|
|
}
|
|
|
|
|
2017-06-19 10:12:00 +08:00
|
|
|
void calc_load_nohz_start(void)
|
2013-04-20 03:10:49 +08:00
|
|
|
{
|
|
|
|
struct rq *this_rq = this_rq();
|
|
|
|
long delta;
|
|
|
|
|
|
|
|
/*
|
2017-06-19 10:12:00 +08:00
|
|
|
* We're going into NO_HZ mode, if there's any pending delta, fold it
|
|
|
|
* into the pending NO_HZ delta.
|
2013-04-20 03:10:49 +08:00
|
|
|
*/
|
2016-07-13 00:33:56 +08:00
|
|
|
delta = calc_load_fold_active(this_rq, 0);
|
2013-04-20 03:10:49 +08:00
|
|
|
if (delta) {
|
|
|
|
int idx = calc_load_write_idx();
|
2015-04-14 19:19:42 +08:00
|
|
|
|
2017-06-19 10:12:00 +08:00
|
|
|
atomic_long_add(delta, &calc_load_nohz[idx]);
|
2013-04-20 03:10:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-19 10:12:00 +08:00
|
|
|
void calc_load_nohz_stop(void)
|
2013-04-20 03:10:49 +08:00
|
|
|
{
|
|
|
|
struct rq *this_rq = this_rq();
|
|
|
|
|
|
|
|
/*
|
2017-02-17 20:07:30 +08:00
|
|
|
* If we're still before the pending sample window, we're done.
|
2013-04-20 03:10:49 +08:00
|
|
|
*/
|
2017-02-17 20:07:31 +08:00
|
|
|
this_rq->calc_load_update = READ_ONCE(calc_load_update);
|
2013-04-20 03:10:49 +08:00
|
|
|
if (time_before(jiffies, this_rq->calc_load_update))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We woke inside or after the sample window, this means we're already
|
|
|
|
* accounted through the nohz accounting, so skip the entire deal and
|
|
|
|
* sync up for the next window.
|
|
|
|
*/
|
|
|
|
if (time_before(jiffies, this_rq->calc_load_update + 10))
|
|
|
|
this_rq->calc_load_update += LOAD_FREQ;
|
|
|
|
}
|
|
|
|
|
2017-06-19 10:12:00 +08:00
|
|
|
static long calc_load_nohz_fold(void)
|
2013-04-20 03:10:49 +08:00
|
|
|
{
|
|
|
|
int idx = calc_load_read_idx();
|
|
|
|
long delta = 0;
|
|
|
|
|
2017-06-19 10:12:00 +08:00
|
|
|
if (atomic_long_read(&calc_load_nohz[idx]))
|
|
|
|
delta = atomic_long_xchg(&calc_load_nohz[idx], 0);
|
2013-04-20 03:10:49 +08:00
|
|
|
|
|
|
|
return delta;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* fixed_power_int - compute: x^n, in O(log n) time
|
|
|
|
*
|
|
|
|
* @x: base of the power
|
|
|
|
* @frac_bits: fractional bits of @x
|
|
|
|
* @n: power to raise @x to.
|
|
|
|
*
|
|
|
|
* By exploiting the relation between the definition of the natural power
|
|
|
|
* function: x^n := x*x*...*x (x multiplied by itself for n times), and
|
|
|
|
* the binary encoding of numbers used by computers: n := \Sum n_i * 2^i,
|
|
|
|
* (where: n_i \elem {0, 1}, the binary vector representing n),
|
|
|
|
* we find: x^n := x^(\Sum n_i * 2^i) := \Prod x^(n_i * 2^i), which is
|
|
|
|
* of course trivially computable in O(log_2 n), the length of our binary
|
|
|
|
* vector.
|
|
|
|
*/
|
|
|
|
static unsigned long
|
|
|
|
fixed_power_int(unsigned long x, unsigned int frac_bits, unsigned int n)
|
|
|
|
{
|
|
|
|
unsigned long result = 1UL << frac_bits;
|
|
|
|
|
2015-04-14 19:19:42 +08:00
|
|
|
if (n) {
|
|
|
|
for (;;) {
|
|
|
|
if (n & 1) {
|
|
|
|
result *= x;
|
|
|
|
result += 1UL << (frac_bits - 1);
|
|
|
|
result >>= frac_bits;
|
|
|
|
}
|
|
|
|
n >>= 1;
|
|
|
|
if (!n)
|
|
|
|
break;
|
|
|
|
x *= x;
|
|
|
|
x += 1UL << (frac_bits - 1);
|
|
|
|
x >>= frac_bits;
|
2013-04-20 03:10:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* a1 = a0 * e + a * (1 - e)
|
|
|
|
*
|
|
|
|
* a2 = a1 * e + a * (1 - e)
|
|
|
|
* = (a0 * e + a * (1 - e)) * e + a * (1 - e)
|
|
|
|
* = a0 * e^2 + a * (1 - e) * (1 + e)
|
|
|
|
*
|
|
|
|
* a3 = a2 * e + a * (1 - e)
|
|
|
|
* = (a0 * e^2 + a * (1 - e) * (1 + e)) * e + a * (1 - e)
|
|
|
|
* = a0 * e^3 + a * (1 - e) * (1 + e + e^2)
|
|
|
|
*
|
|
|
|
* ...
|
|
|
|
*
|
|
|
|
* an = a0 * e^n + a * (1 - e) * (1 + e + ... + e^n-1) [1]
|
|
|
|
* = a0 * e^n + a * (1 - e) * (1 - e^n)/(1 - e)
|
|
|
|
* = a0 * e^n + a * (1 - e^n)
|
|
|
|
*
|
|
|
|
* [1] application of the geometric series:
|
|
|
|
*
|
|
|
|
* n 1 - x^(n+1)
|
|
|
|
* S_n := \Sum x^i = -------------
|
|
|
|
* i=0 1 - x
|
|
|
|
*/
|
|
|
|
static unsigned long
|
|
|
|
calc_load_n(unsigned long load, unsigned long exp,
|
|
|
|
unsigned long active, unsigned int n)
|
|
|
|
{
|
|
|
|
return calc_load(load, fixed_power_int(exp, FSHIFT, n), active);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NO_HZ can leave us missing all per-cpu ticks calling
|
2017-06-19 10:12:00 +08:00
|
|
|
* calc_load_fold_active(), but since a NO_HZ CPU folds its delta into
|
|
|
|
* calc_load_nohz per calc_load_nohz_start(), all we need to do is fold
|
|
|
|
* in the pending NO_HZ delta if our NO_HZ period crossed a load cycle boundary.
|
2013-04-20 03:10:49 +08:00
|
|
|
*
|
|
|
|
* Once we've updated the global active value, we need to apply the exponential
|
|
|
|
* weights adjusted to the number of cycles missed.
|
|
|
|
*/
|
|
|
|
static void calc_global_nohz(void)
|
|
|
|
{
|
2017-02-17 20:07:31 +08:00
|
|
|
unsigned long sample_window;
|
2013-04-20 03:10:49 +08:00
|
|
|
long delta, active, n;
|
|
|
|
|
2017-02-17 20:07:31 +08:00
|
|
|
sample_window = READ_ONCE(calc_load_update);
|
|
|
|
if (!time_before(jiffies, sample_window + 10)) {
|
2013-04-20 03:10:49 +08:00
|
|
|
/*
|
|
|
|
* Catch-up, fold however many we are behind still
|
|
|
|
*/
|
2017-02-17 20:07:31 +08:00
|
|
|
delta = jiffies - sample_window - 10;
|
2013-04-20 03:10:49 +08:00
|
|
|
n = 1 + (delta / LOAD_FREQ);
|
|
|
|
|
|
|
|
active = atomic_long_read(&calc_load_tasks);
|
|
|
|
active = active > 0 ? active * FIXED_1 : 0;
|
|
|
|
|
|
|
|
avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n);
|
|
|
|
avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
|
|
|
|
avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
|
|
|
|
|
2017-02-17 20:07:31 +08:00
|
|
|
WRITE_ONCE(calc_load_update, sample_window + n * LOAD_FREQ);
|
2013-04-20 03:10:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-06-19 10:12:00 +08:00
|
|
|
* Flip the NO_HZ index...
|
2013-04-20 03:10:49 +08:00
|
|
|
*
|
|
|
|
* Make sure we first write the new time then flip the index, so that
|
|
|
|
* calc_load_write_idx() will see the new time when it reads the new
|
|
|
|
* index, this avoids a double flip messing things up.
|
|
|
|
*/
|
|
|
|
smp_wmb();
|
|
|
|
calc_load_idx++;
|
|
|
|
}
|
|
|
|
#else /* !CONFIG_NO_HZ_COMMON */
|
|
|
|
|
2017-06-19 10:12:00 +08:00
|
|
|
static inline long calc_load_nohz_fold(void) { return 0; }
|
2013-04-20 03:10:49 +08:00
|
|
|
static inline void calc_global_nohz(void) { }
|
|
|
|
|
|
|
|
#endif /* CONFIG_NO_HZ_COMMON */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* calc_load - update the avenrun load estimates 10 ticks after the
|
|
|
|
* CPUs have updated calc_load_tasks.
|
2015-04-14 19:19:42 +08:00
|
|
|
*
|
|
|
|
* Called from the global timer code.
|
2013-04-20 03:10:49 +08:00
|
|
|
*/
|
|
|
|
void calc_global_load(unsigned long ticks)
|
|
|
|
{
|
2017-02-17 20:07:31 +08:00
|
|
|
unsigned long sample_window;
|
2013-04-20 03:10:49 +08:00
|
|
|
long active, delta;
|
|
|
|
|
2017-02-17 20:07:31 +08:00
|
|
|
sample_window = READ_ONCE(calc_load_update);
|
|
|
|
if (time_before(jiffies, sample_window + 10))
|
2013-04-20 03:10:49 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
2017-06-19 10:12:00 +08:00
|
|
|
* Fold the 'old' NO_HZ-delta to include all NO_HZ cpus.
|
2013-04-20 03:10:49 +08:00
|
|
|
*/
|
2017-06-19 10:12:00 +08:00
|
|
|
delta = calc_load_nohz_fold();
|
2013-04-20 03:10:49 +08:00
|
|
|
if (delta)
|
|
|
|
atomic_long_add(delta, &calc_load_tasks);
|
|
|
|
|
|
|
|
active = atomic_long_read(&calc_load_tasks);
|
|
|
|
active = active > 0 ? active * FIXED_1 : 0;
|
|
|
|
|
|
|
|
avenrun[0] = calc_load(avenrun[0], EXP_1, active);
|
|
|
|
avenrun[1] = calc_load(avenrun[1], EXP_5, active);
|
|
|
|
avenrun[2] = calc_load(avenrun[2], EXP_15, active);
|
|
|
|
|
2017-02-17 20:07:31 +08:00
|
|
|
WRITE_ONCE(calc_load_update, sample_window + LOAD_FREQ);
|
2013-04-20 03:10:49 +08:00
|
|
|
|
|
|
|
/*
|
2017-06-19 10:12:00 +08:00
|
|
|
* In case we went to NO_HZ for multiple LOAD_FREQ intervals
|
|
|
|
* catch up in bulk.
|
2013-04-20 03:10:49 +08:00
|
|
|
*/
|
|
|
|
calc_global_nohz();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-04-14 19:19:42 +08:00
|
|
|
* Called from scheduler_tick() to periodically update this CPU's
|
2013-04-20 03:10:49 +08:00
|
|
|
* active count.
|
|
|
|
*/
|
2015-04-14 19:19:42 +08:00
|
|
|
void calc_global_load_tick(struct rq *this_rq)
|
2013-04-20 03:10:49 +08:00
|
|
|
{
|
|
|
|
long delta;
|
|
|
|
|
|
|
|
if (time_before(jiffies, this_rq->calc_load_update))
|
|
|
|
return;
|
|
|
|
|
2016-07-13 00:33:56 +08:00
|
|
|
delta = calc_load_fold_active(this_rq, 0);
|
2013-04-20 03:10:49 +08:00
|
|
|
if (delta)
|
|
|
|
atomic_long_add(delta, &calc_load_tasks);
|
|
|
|
|
|
|
|
this_rq->calc_load_update += LOAD_FREQ;
|
|
|
|
}
|