da30fdf96a
The scheduler uses the load tracking logic to compute the load of threads to be enqueued into the run queue. The time delta between the last enqueue and the next enqueue may grow very large for threads that mostly wait on conditions. In such cases the int "n" period count variable would become too small and wrap around, leading to an assertion failure. For this to happen, the thread in question would have to have slept for at least ~25 days and then wake up. Threads often affected would be ones waiting for some other process to end, for example shell threads waiting for a long running process to exit. Fixes #13558.
58 lines
1.1 KiB
C
58 lines
1.1 KiB
C
/*
|
|
* Copyright 2013 Paweł Dziepak, pdziepak@quarnos.org.
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
#ifndef _KERNEL_LOAD_TRACKING_H
|
|
#define _KERNEL_LOAD_TRACKING_H
|
|
|
|
|
|
#include <OS.h>
|
|
|
|
|
|
const int32 kMaxLoad = 1000;
|
|
const bigtime_t kLoadMeasureInterval = 1000;
|
|
const bigtime_t kIntervalInaccuracy = kLoadMeasureInterval / 4;
|
|
|
|
|
|
static inline int32
|
|
compute_load(bigtime_t& measureTime, bigtime_t& measureActiveTime, int32& load,
|
|
bigtime_t now)
|
|
{
|
|
if (measureTime == 0) {
|
|
measureTime = now;
|
|
return -1;
|
|
}
|
|
|
|
bigtime_t deltaTime = now - measureTime;
|
|
|
|
if (deltaTime < kLoadMeasureInterval)
|
|
return -1;
|
|
|
|
int32 oldLoad = load;
|
|
ASSERT(oldLoad >= 0 && oldLoad <= kMaxLoad);
|
|
|
|
int32 newLoad = measureActiveTime * kMaxLoad;
|
|
newLoad /= max_c(deltaTime, 1);
|
|
newLoad = max_c(min_c(newLoad, kMaxLoad), 0);
|
|
|
|
measureActiveTime = 0;
|
|
measureTime = now;
|
|
|
|
deltaTime += kIntervalInaccuracy;
|
|
bigtime_t n = deltaTime / kLoadMeasureInterval;
|
|
ASSERT(n > 0);
|
|
|
|
if (n > 10)
|
|
load = newLoad;
|
|
else {
|
|
newLoad *= (1 << n) - 1;
|
|
load = (load + newLoad) / (1 << n);
|
|
ASSERT(load >= 0 && load <= kMaxLoad);
|
|
}
|
|
|
|
return oldLoad;
|
|
}
|
|
|
|
|
|
#endif // _KERNEL_LOAD_TRACKING_H
|