mirror of https://github.com/xzeldon/htop.git
Merging all the points related to calculating time in one place
The end goal is to consolidate all the points in htop that can only work in live-only mode today, so that will be able to inject PCP archive mode and have a chance at it working. The biggest problem we've got at this moment is all the places that are independently asking the kernel to 'give me the time right now'. Each of those needs to be audited and ultimately changed to allow platforms to manage their own idea of time. So, all the calls to gettimeofday(2) and time(2) are potential problems. Ultimately I want to get these down to just one or two. Related to https://github.com/htop-dev/htop/pull/574
This commit is contained in:
parent
f16aa483dd
commit
421bdeec60
|
@ -20,9 +20,10 @@ static const int ClockMeter_attributes[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ClockMeter_updateValues(Meter* this) {
|
static void ClockMeter_updateValues(Meter* this) {
|
||||||
time_t t = time(NULL);
|
const ProcessList* pl = this->pl;
|
||||||
|
|
||||||
struct tm result;
|
struct tm result;
|
||||||
const struct tm* lt = localtime_r(&t, &result);
|
const struct tm* lt = localtime_r(&pl->timestamp.tv_sec, &result);
|
||||||
this->values[0] = lt->tm_hour * 60 + lt->tm_min;
|
this->values[0] = lt->tm_hour * 60 + lt->tm_min;
|
||||||
strftime(this->txtBuffer, sizeof(this->txtBuffer), "%H:%M:%S", lt);
|
strftime(this->txtBuffer, sizeof(this->txtBuffer), "%H:%M:%S", lt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,10 @@ static const int DateMeter_attributes[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DateMeter_updateValues(Meter* this) {
|
static void DateMeter_updateValues(Meter* this) {
|
||||||
time_t t = time(NULL);
|
const ProcessList* pl = this->pl;
|
||||||
|
|
||||||
struct tm result;
|
struct tm result;
|
||||||
const struct tm* lt = localtime_r(&t, &result);
|
const struct tm* lt = localtime_r(&pl->timestamp.tv_sec, &result);
|
||||||
this->values[0] = lt->tm_yday;
|
this->values[0] = lt->tm_yday;
|
||||||
int year = lt->tm_year + 1900;
|
int year = lt->tm_year + 1900;
|
||||||
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
|
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
|
||||||
|
|
|
@ -31,12 +31,10 @@ static uint32_t cached_write_diff;
|
||||||
static double cached_utilisation_diff;
|
static double cached_utilisation_diff;
|
||||||
|
|
||||||
static void DiskIOMeter_updateValues(Meter* this) {
|
static void DiskIOMeter_updateValues(Meter* this) {
|
||||||
static uint64_t cached_last_update;
|
const ProcessList* pl = this->pl;
|
||||||
|
|
||||||
struct timeval tv;
|
static uint64_t cached_last_update;
|
||||||
gettimeofday(&tv, NULL);
|
uint64_t passedTimeInMs = pl->timestampMs - cached_last_update;
|
||||||
uint64_t timeInMilliSeconds = (uint64_t)tv.tv_sec * 1000 + (uint64_t)tv.tv_usec / 1000;
|
|
||||||
uint64_t passedTimeInMs = timeInMilliSeconds - cached_last_update;
|
|
||||||
|
|
||||||
/* update only every 500ms */
|
/* update only every 500ms */
|
||||||
if (passedTimeInMs > 500) {
|
if (passedTimeInMs > 500) {
|
||||||
|
@ -45,7 +43,7 @@ static void DiskIOMeter_updateValues(Meter* this) {
|
||||||
static uint64_t cached_msTimeSpend_total;
|
static uint64_t cached_msTimeSpend_total;
|
||||||
uint64_t diff;
|
uint64_t diff;
|
||||||
|
|
||||||
cached_last_update = timeInMilliSeconds;
|
cached_last_update = pl->timestampMs;
|
||||||
|
|
||||||
DiskIOData data;
|
DiskIOData data;
|
||||||
|
|
||||||
|
|
8
Meter.c
8
Meter.c
|
@ -18,6 +18,7 @@ in the source distribution for its full text.
|
||||||
#include "CRT.h"
|
#include "CRT.h"
|
||||||
#include "Macros.h"
|
#include "Macros.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
#include "Platform.h"
|
||||||
#include "ProvideCurses.h"
|
#include "ProvideCurses.h"
|
||||||
#include "RichString.h"
|
#include "RichString.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
@ -286,6 +287,7 @@ static const char* const GraphMeterMode_dotsAscii[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||||
|
const ProcessList* pl = this->pl;
|
||||||
|
|
||||||
if (!this->drawData) {
|
if (!this->drawData) {
|
||||||
this->drawData = xCalloc(1, sizeof(GraphData));
|
this->drawData = xCalloc(1, sizeof(GraphData));
|
||||||
|
@ -312,12 +314,10 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||||
x += captionLen;
|
x += captionLen;
|
||||||
w -= captionLen;
|
w -= captionLen;
|
||||||
|
|
||||||
struct timeval now;
|
if (!timercmp(&pl->timestamp, &(data->time), <)) {
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
if (!timercmp(&now, &(data->time), <)) {
|
|
||||||
int globalDelay = this->pl->settings->delay;
|
int globalDelay = this->pl->settings->delay;
|
||||||
struct timeval delay = { .tv_sec = globalDelay / 10, .tv_usec = (globalDelay - ((globalDelay / 10) * 10)) * 100000 };
|
struct timeval delay = { .tv_sec = globalDelay / 10, .tv_usec = (globalDelay - ((globalDelay / 10) * 10)) * 100000 };
|
||||||
timeradd(&now, &delay, &(data->time));
|
timeradd(&pl->timestamp, &delay, &(data->time));
|
||||||
|
|
||||||
for (int i = 0; i < nValues - 1; i++)
|
for (int i = 0; i < nValues - 1; i++)
|
||||||
data->values[i] = data->values[i + 1];
|
data->values[i] = data->values[i + 1];
|
||||||
|
|
|
@ -25,12 +25,10 @@ static uint32_t cached_txb_diff;
|
||||||
static uint32_t cached_txp_diff;
|
static uint32_t cached_txp_diff;
|
||||||
|
|
||||||
static void NetworkIOMeter_updateValues(Meter* this) {
|
static void NetworkIOMeter_updateValues(Meter* this) {
|
||||||
|
const ProcessList* pl = this->pl;
|
||||||
static uint64_t cached_last_update = 0;
|
static uint64_t cached_last_update = 0;
|
||||||
|
|
||||||
struct timeval tv;
|
uint64_t passedTimeInMs = pl->timestampMs - cached_last_update;
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
uint64_t timeInMilliSeconds = (uint64_t)tv.tv_sec * 1000 + (uint64_t)tv.tv_usec / 1000;
|
|
||||||
uint64_t passedTimeInMs = timeInMilliSeconds - cached_last_update;
|
|
||||||
|
|
||||||
/* update only every 500ms */
|
/* update only every 500ms */
|
||||||
if (passedTimeInMs > 500) {
|
if (passedTimeInMs > 500) {
|
||||||
|
@ -40,7 +38,7 @@ static void NetworkIOMeter_updateValues(Meter* this) {
|
||||||
static uint64_t cached_txp_total;
|
static uint64_t cached_txp_total;
|
||||||
uint64_t diff;
|
uint64_t diff;
|
||||||
|
|
||||||
cached_last_update = timeInMilliSeconds;
|
cached_last_update = pl->timestampMs;
|
||||||
|
|
||||||
NetworkIOData data;
|
NetworkIOData data;
|
||||||
hasData = Platform_getNetworkIO(&data);
|
hasData = Platform_getNetworkIO(&data);
|
||||||
|
|
|
@ -48,6 +48,9 @@ typedef struct ProcessList_ {
|
||||||
Hashtable* displayTreeSet;
|
Hashtable* displayTreeSet;
|
||||||
Hashtable* draftingTreeSet;
|
Hashtable* draftingTreeSet;
|
||||||
|
|
||||||
|
struct timeval timestamp; /* time of the current sample */
|
||||||
|
uint64_t timestampMs; /* current time in milliseconds */
|
||||||
|
|
||||||
Panel* panel;
|
Panel* panel;
|
||||||
int following;
|
int following;
|
||||||
uid_t userId;
|
uid_t userId;
|
||||||
|
|
|
@ -189,6 +189,13 @@ static void LinuxProcessList_updateCPUcount(ProcessList* super, FILE* stream) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void LinuxProcessList_updateTime(LinuxProcessList* this) {
|
||||||
|
ProcessList* pl = &(this->super);
|
||||||
|
|
||||||
|
gettimeofday(&pl->timestamp, NULL);
|
||||||
|
pl->timestampMs = (uint64_t)&pl->timestamp.tv_sec * 1000 + (uint64_t)pl->timestamp.tv_usec / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) {
|
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) {
|
||||||
LinuxProcessList* this = xCalloc(1, sizeof(LinuxProcessList));
|
LinuxProcessList* this = xCalloc(1, sizeof(LinuxProcessList));
|
||||||
ProcessList* pl = &(this->super);
|
ProcessList* pl = &(this->super);
|
||||||
|
@ -1968,6 +1975,7 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
LinuxProcessList* this = (LinuxProcessList*) super;
|
LinuxProcessList* this = (LinuxProcessList*) super;
|
||||||
const Settings* settings = super->settings;
|
const Settings* settings = super->settings;
|
||||||
|
|
||||||
|
LinuxProcessList_updateTime(this);
|
||||||
LinuxProcessList_scanMemoryInfo(super);
|
LinuxProcessList_scanMemoryInfo(super);
|
||||||
LinuxProcessList_scanHugePages(this);
|
LinuxProcessList_scanHugePages(this);
|
||||||
LinuxProcessList_scanZfsArcstats(this);
|
LinuxProcessList_scanZfsArcstats(this);
|
||||||
|
@ -1989,10 +1997,6 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
unsigned long long now = tv.tv_sec * 1000ULL + tv.tv_usec / 1000ULL;
|
|
||||||
|
|
||||||
/* PROCDIR is an absolute path */
|
/* PROCDIR is an absolute path */
|
||||||
assert(PROCDIR[0] == '/');
|
assert(PROCDIR[0] == '/');
|
||||||
#ifdef HAVE_OPENAT
|
#ifdef HAVE_OPENAT
|
||||||
|
@ -2001,5 +2005,5 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
openat_arg_t rootFd = "";
|
openat_arg_t rootFd = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LinuxProcessList_recurseProcTree(this, rootFd, PROCDIR, NULL, period, now);
|
LinuxProcessList_recurseProcTree(this, rootFd, PROCDIR, NULL, period, super->timestampMs);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue