mirror of https://github.com/xzeldon/htop.git
Request the realtime and monotonic clock times once per sample
Refactor the sample time code to make one call to gettimeofday (aka the realtime clock in clock_gettime, when available) and one to the monotonic clock. Stores each in more appropriately named ProcessList fields for ready access when needed. Every platform gets the opportunity to provide their own clock code, and the existing Mac OS X specific code is moved below darwin instead of in Compat. A couple of leftover time(2) calls are converted to use these ProcessList fields as well, instead of yet again sampling the system clock. Related to https://github.com/htop-dev/htop/pull/574
This commit is contained in:
parent
421bdeec60
commit
356488aa53
|
@ -23,7 +23,7 @@ static void ClockMeter_updateValues(Meter* this) {
|
||||||
const ProcessList* pl = this->pl;
|
const ProcessList* pl = this->pl;
|
||||||
|
|
||||||
struct tm result;
|
struct tm result;
|
||||||
const struct tm* lt = localtime_r(&pl->timestamp.tv_sec, &result);
|
const struct tm* lt = localtime_r(&pl->realtime.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);
|
||||||
}
|
}
|
||||||
|
|
34
Compat.c
34
Compat.c
|
@ -11,18 +11,12 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h> // IWYU pragma: keep
|
#include <fcntl.h> // IWYU pragma: keep
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h> // IWYU pragma: keep
|
#include <sys/types.h> // IWYU pragma: keep
|
||||||
|
|
||||||
#include "XUtils.h" // IWYU pragma: keep
|
#include "XUtils.h" // IWYU pragma: keep
|
||||||
|
|
||||||
#ifdef HAVE_HOST_GET_CLOCK_SERVICE
|
|
||||||
#include <mach/clock.h>
|
|
||||||
#include <mach/mach.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int Compat_faccessat(int dirfd,
|
int Compat_faccessat(int dirfd,
|
||||||
const char* pathname,
|
const char* pathname,
|
||||||
|
@ -123,31 +117,3 @@ ssize_t Compat_readlinkat(int dirfd,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int Compat_clock_monotonic_gettime(struct timespec *tp) {
|
|
||||||
|
|
||||||
#if defined(HAVE_CLOCK_GETTIME)
|
|
||||||
|
|
||||||
return clock_gettime(CLOCK_MONOTONIC, tp);
|
|
||||||
|
|
||||||
#elif defined(HAVE_HOST_GET_CLOCK_SERVICE)
|
|
||||||
|
|
||||||
clock_serv_t cclock;
|
|
||||||
mach_timespec_t mts;
|
|
||||||
|
|
||||||
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
|
|
||||||
clock_get_time(cclock, &mts);
|
|
||||||
mach_port_deallocate(mach_task_self(), cclock);
|
|
||||||
|
|
||||||
tp->tv_sec = mts.tv_sec;
|
|
||||||
tp->tv_nsec = mts.tv_nsec;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#error No Compat_clock_monotonic_gettime() implementation!
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
2
Compat.h
2
Compat.h
|
@ -56,6 +56,4 @@ ssize_t Compat_readlinkat(int dirfd,
|
||||||
char* buf,
|
char* buf,
|
||||||
size_t bufsize);
|
size_t bufsize);
|
||||||
|
|
||||||
int Compat_clock_monotonic_gettime(struct timespec *tp);
|
|
||||||
|
|
||||||
#endif /* HEADER_Compat */
|
#endif /* HEADER_Compat */
|
||||||
|
|
|
@ -23,7 +23,7 @@ static void DateMeter_updateValues(Meter* this) {
|
||||||
const ProcessList* pl = this->pl;
|
const ProcessList* pl = this->pl;
|
||||||
|
|
||||||
struct tm result;
|
struct tm result;
|
||||||
const struct tm* lt = localtime_r(&pl->timestamp.tv_sec, &result);
|
const struct tm* lt = localtime_r(&pl->realtime.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)) {
|
||||||
|
|
|
@ -20,9 +20,10 @@ static const int DateTimeMeter_attributes[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DateTimeMeter_updateValues(Meter* this) {
|
static void DateTimeMeter_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->realtime.tv_sec, &result);
|
||||||
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)) {
|
||||||
this->total = 366;
|
this->total = 366;
|
||||||
|
|
|
@ -34,7 +34,7 @@ static void DiskIOMeter_updateValues(Meter* this) {
|
||||||
const ProcessList* pl = this->pl;
|
const ProcessList* pl = this->pl;
|
||||||
|
|
||||||
static uint64_t cached_last_update;
|
static uint64_t cached_last_update;
|
||||||
uint64_t passedTimeInMs = pl->timestampMs - cached_last_update;
|
uint64_t passedTimeInMs = pl->realtimeMs - cached_last_update;
|
||||||
|
|
||||||
/* update only every 500ms */
|
/* update only every 500ms */
|
||||||
if (passedTimeInMs > 500) {
|
if (passedTimeInMs > 500) {
|
||||||
|
@ -43,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 = pl->timestampMs;
|
cached_last_update = pl->realtimeMs;
|
||||||
|
|
||||||
DiskIOData data;
|
DiskIOData data;
|
||||||
|
|
||||||
|
|
14
Makefile.am
14
Makefile.am
|
@ -134,6 +134,7 @@ myhtopheaders = \
|
||||||
# -----
|
# -----
|
||||||
|
|
||||||
linux_platform_headers = \
|
linux_platform_headers = \
|
||||||
|
generic/gettime.h \
|
||||||
generic/hostname.h \
|
generic/hostname.h \
|
||||||
generic/uname.h \
|
generic/uname.h \
|
||||||
linux/HugePageMeter.h \
|
linux/HugePageMeter.h \
|
||||||
|
@ -154,6 +155,7 @@ linux_platform_headers = \
|
||||||
zfs/ZfsCompressedArcMeter.h
|
zfs/ZfsCompressedArcMeter.h
|
||||||
|
|
||||||
linux_platform_sources = \
|
linux_platform_sources = \
|
||||||
|
generic/gettime.c \
|
||||||
generic/hostname.c \
|
generic/hostname.c \
|
||||||
generic/uname.c \
|
generic/uname.c \
|
||||||
linux/HugePageMeter.c \
|
linux/HugePageMeter.c \
|
||||||
|
@ -184,6 +186,7 @@ freebsd_platform_headers = \
|
||||||
freebsd/FreeBSDProcess.h \
|
freebsd/FreeBSDProcess.h \
|
||||||
freebsd/Platform.h \
|
freebsd/Platform.h \
|
||||||
freebsd/ProcessField.h \
|
freebsd/ProcessField.h \
|
||||||
|
generic/gettime.h \
|
||||||
generic/hostname.h \
|
generic/hostname.h \
|
||||||
generic/openzfs_sysctl.h \
|
generic/openzfs_sysctl.h \
|
||||||
generic/uname.h \
|
generic/uname.h \
|
||||||
|
@ -195,6 +198,7 @@ freebsd_platform_sources = \
|
||||||
freebsd/Platform.c \
|
freebsd/Platform.c \
|
||||||
freebsd/FreeBSDProcessList.c \
|
freebsd/FreeBSDProcessList.c \
|
||||||
freebsd/FreeBSDProcess.c \
|
freebsd/FreeBSDProcess.c \
|
||||||
|
generic/gettime.c \
|
||||||
generic/hostname.c \
|
generic/hostname.c \
|
||||||
generic/openzfs_sysctl.c \
|
generic/openzfs_sysctl.c \
|
||||||
generic/uname.c \
|
generic/uname.c \
|
||||||
|
@ -215,6 +219,7 @@ dragonflybsd_platform_headers = \
|
||||||
dragonflybsd/DragonFlyBSDProcess.h \
|
dragonflybsd/DragonFlyBSDProcess.h \
|
||||||
dragonflybsd/Platform.h \
|
dragonflybsd/Platform.h \
|
||||||
dragonflybsd/ProcessField.h \
|
dragonflybsd/ProcessField.h \
|
||||||
|
generic/gettime.h \
|
||||||
generic/hostname.h \
|
generic/hostname.h \
|
||||||
generic/uname.h
|
generic/uname.h
|
||||||
|
|
||||||
|
@ -222,6 +227,7 @@ dragonflybsd_platform_sources = \
|
||||||
dragonflybsd/DragonFlyBSDProcessList.c \
|
dragonflybsd/DragonFlyBSDProcessList.c \
|
||||||
dragonflybsd/DragonFlyBSDProcess.c \
|
dragonflybsd/DragonFlyBSDProcess.c \
|
||||||
dragonflybsd/Platform.c \
|
dragonflybsd/Platform.c \
|
||||||
|
generic/gettime.c \
|
||||||
generic/hostname.c \
|
generic/hostname.c \
|
||||||
generic/uname.c
|
generic/uname.c
|
||||||
|
|
||||||
|
@ -235,6 +241,7 @@ endif
|
||||||
# -------
|
# -------
|
||||||
|
|
||||||
openbsd_platform_headers = \
|
openbsd_platform_headers = \
|
||||||
|
generic/gettime.h \
|
||||||
generic/hostname.h \
|
generic/hostname.h \
|
||||||
generic/uname.h \
|
generic/uname.h \
|
||||||
openbsd/OpenBSDProcessList.h \
|
openbsd/OpenBSDProcessList.h \
|
||||||
|
@ -243,6 +250,7 @@ openbsd_platform_headers = \
|
||||||
openbsd/ProcessField.h
|
openbsd/ProcessField.h
|
||||||
|
|
||||||
openbsd_platform_sources = \
|
openbsd_platform_sources = \
|
||||||
|
generic/gettime.c \
|
||||||
generic/hostname.c \
|
generic/hostname.c \
|
||||||
generic/uname.c \
|
generic/uname.c \
|
||||||
openbsd/OpenBSDProcessList.c \
|
openbsd/OpenBSDProcessList.c \
|
||||||
|
@ -263,6 +271,7 @@ darwin_platform_headers = \
|
||||||
darwin/DarwinProcessList.h \
|
darwin/DarwinProcessList.h \
|
||||||
darwin/Platform.h \
|
darwin/Platform.h \
|
||||||
darwin/ProcessField.h \
|
darwin/ProcessField.h \
|
||||||
|
generic/gettime.h \
|
||||||
generic/hostname.h \
|
generic/hostname.h \
|
||||||
generic/openzfs_sysctl.h \
|
generic/openzfs_sysctl.h \
|
||||||
generic/uname.h \
|
generic/uname.h \
|
||||||
|
@ -274,6 +283,7 @@ darwin_platform_sources = \
|
||||||
darwin/Platform.c \
|
darwin/Platform.c \
|
||||||
darwin/DarwinProcess.c \
|
darwin/DarwinProcess.c \
|
||||||
darwin/DarwinProcessList.c \
|
darwin/DarwinProcessList.c \
|
||||||
|
generic/gettime.c \
|
||||||
generic/hostname.c \
|
generic/hostname.c \
|
||||||
generic/openzfs_sysctl.c \
|
generic/openzfs_sysctl.c \
|
||||||
generic/uname.c \
|
generic/uname.c \
|
||||||
|
@ -291,6 +301,7 @@ endif
|
||||||
# -------
|
# -------
|
||||||
|
|
||||||
solaris_platform_headers = \
|
solaris_platform_headers = \
|
||||||
|
generic/gettime.h \
|
||||||
generic/hostname.h \
|
generic/hostname.h \
|
||||||
generic/uname.h \
|
generic/uname.h \
|
||||||
solaris/ProcessField.h \
|
solaris/ProcessField.h \
|
||||||
|
@ -302,6 +313,7 @@ solaris_platform_headers = \
|
||||||
zfs/ZfsCompressedArcMeter.h
|
zfs/ZfsCompressedArcMeter.h
|
||||||
|
|
||||||
solaris_platform_sources = \
|
solaris_platform_sources = \
|
||||||
|
generic/gettime.c \
|
||||||
generic/hostname.c \
|
generic/hostname.c \
|
||||||
generic/uname.c \
|
generic/uname.c \
|
||||||
solaris/Platform.c \
|
solaris/Platform.c \
|
||||||
|
@ -320,12 +332,14 @@ endif
|
||||||
# -----------
|
# -----------
|
||||||
|
|
||||||
unsupported_platform_headers = \
|
unsupported_platform_headers = \
|
||||||
|
generic/gettime.h \
|
||||||
unsupported/Platform.h \
|
unsupported/Platform.h \
|
||||||
unsupported/ProcessField.h \
|
unsupported/ProcessField.h \
|
||||||
unsupported/UnsupportedProcess.h \
|
unsupported/UnsupportedProcess.h \
|
||||||
unsupported/UnsupportedProcessList.h
|
unsupported/UnsupportedProcessList.h
|
||||||
|
|
||||||
unsupported_platform_sources = \
|
unsupported_platform_sources = \
|
||||||
|
generic/gettime.c \
|
||||||
unsupported/Platform.c \
|
unsupported/Platform.c \
|
||||||
unsupported/UnsupportedProcess.c \
|
unsupported/UnsupportedProcess.c \
|
||||||
unsupported/UnsupportedProcessList.c
|
unsupported/UnsupportedProcessList.c
|
||||||
|
|
4
Meter.c
4
Meter.c
|
@ -314,10 +314,10 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||||
x += captionLen;
|
x += captionLen;
|
||||||
w -= captionLen;
|
w -= captionLen;
|
||||||
|
|
||||||
if (!timercmp(&pl->timestamp, &(data->time), <)) {
|
if (!timercmp(&pl->realtime, &(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(&pl->timestamp, &delay, &(data->time));
|
timeradd(&pl->realtime, &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];
|
||||||
|
|
|
@ -28,7 +28,7 @@ static void NetworkIOMeter_updateValues(Meter* this) {
|
||||||
const ProcessList* pl = this->pl;
|
const ProcessList* pl = this->pl;
|
||||||
static uint64_t cached_last_update = 0;
|
static uint64_t cached_last_update = 0;
|
||||||
|
|
||||||
uint64_t passedTimeInMs = pl->timestampMs - cached_last_update;
|
uint64_t passedTimeInMs = pl->realtimeMs - cached_last_update;
|
||||||
|
|
||||||
/* update only every 500ms */
|
/* update only every 500ms */
|
||||||
if (passedTimeInMs > 500) {
|
if (passedTimeInMs > 500) {
|
||||||
|
@ -38,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 = pl->timestampMs;
|
cached_last_update = pl->realtimeMs;
|
||||||
|
|
||||||
NetworkIOData data;
|
NetworkIOData data;
|
||||||
hasData = Platform_getNetworkIO(&data);
|
hasData = Platform_getNetworkIO(&data);
|
||||||
|
|
|
@ -467,14 +467,14 @@ void Process_toggleTag(Process* this) {
|
||||||
|
|
||||||
bool Process_isNew(const Process* this) {
|
bool Process_isNew(const Process* this) {
|
||||||
assert(this->processList);
|
assert(this->processList);
|
||||||
if (this->processList->scanTs >= this->seenTs) {
|
if (this->processList->monotonicMs >= this->seenStampMs) {
|
||||||
return this->processList->scanTs - this->seenTs <= 1000 * this->processList->settings->highlightDelaySecs;
|
return this->processList->monotonicMs - this->seenStampMs <= 1000 * (uint64_t)this->processList->settings->highlightDelaySecs;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Process_isTomb(const Process* this) {
|
bool Process_isTomb(const Process* this) {
|
||||||
return this->tombTs > 0;
|
return this->tombStampMs > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Process_setPriority(Process* this, int priority) {
|
bool Process_setPriority(Process* this, int priority) {
|
||||||
|
|
|
@ -174,8 +174,8 @@ typedef struct Process_ {
|
||||||
/*
|
/*
|
||||||
* Internal time counts for showing new and exited processes.
|
* Internal time counts for showing new and exited processes.
|
||||||
*/
|
*/
|
||||||
time_t seenTs;
|
uint64_t seenStampMs;
|
||||||
time_t tombTs;
|
uint64_t tombStampMs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal state for tree-mode.
|
* Internal state for tree-mode.
|
||||||
|
|
|
@ -10,11 +10,12 @@ in the source distribution for its full text.
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "Compat.h"
|
|
||||||
#include "CRT.h"
|
#include "CRT.h"
|
||||||
#include "Hashtable.h"
|
#include "Hashtable.h"
|
||||||
#include "Macros.h"
|
#include "Macros.h"
|
||||||
|
#include "Platform.h"
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "XUtils.h"
|
#include "XUtils.h"
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, Users
|
||||||
// set later by platform-specific code
|
// set later by platform-specific code
|
||||||
this->cpuCount = 0;
|
this->cpuCount = 0;
|
||||||
|
|
||||||
this->scanTs = 0;
|
this->monotonicMs = 0;
|
||||||
|
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
this->topologyOk = false;
|
this->topologyOk = false;
|
||||||
|
@ -131,7 +132,7 @@ void ProcessList_add(ProcessList* this, Process* p) {
|
||||||
p->processList = this;
|
p->processList = this;
|
||||||
|
|
||||||
// highlighting processes found in first scan by first scan marked "far in the past"
|
// highlighting processes found in first scan by first scan marked "far in the past"
|
||||||
p->seenTs = this->scanTs;
|
p->seenStampMs = this->monotonicMs;
|
||||||
|
|
||||||
Vector_add(this->processes, p);
|
Vector_add(this->processes, p);
|
||||||
Hashtable_put(this->processTable, p->pid, p);
|
Hashtable_put(this->processTable, p->pid, p);
|
||||||
|
@ -582,8 +583,6 @@ Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) {
|
void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) {
|
||||||
struct timespec now;
|
|
||||||
|
|
||||||
// in pause mode only gather global data for meters (CPU/memory/...)
|
// in pause mode only gather global data for meters (CPU/memory/...)
|
||||||
if (pauseProcessUpdate) {
|
if (pauseProcessUpdate) {
|
||||||
ProcessList_goThroughEntries(this, true);
|
ProcessList_goThroughEntries(this, true);
|
||||||
|
@ -604,31 +603,29 @@ void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) {
|
||||||
this->runningTasks = 0;
|
this->runningTasks = 0;
|
||||||
|
|
||||||
|
|
||||||
// set scanTs
|
// set scan timestamp
|
||||||
static bool firstScanDone = false;
|
static bool firstScanDone = false;
|
||||||
if (!firstScanDone) {
|
if (firstScanDone) {
|
||||||
this->scanTs = 0;
|
Platform_gettime_monotonic(&this->monotonicMs);
|
||||||
|
} else {
|
||||||
|
this->monotonicMs = 0;
|
||||||
firstScanDone = true;
|
firstScanDone = true;
|
||||||
} else if (Compat_clock_monotonic_gettime(&now) == 0) {
|
|
||||||
// save time in millisecond, so with a delay in deciseconds
|
|
||||||
// there are no irregularities
|
|
||||||
this->scanTs = 1000 * now.tv_sec + now.tv_nsec / 1000000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessList_goThroughEntries(this, false);
|
ProcessList_goThroughEntries(this, false);
|
||||||
|
|
||||||
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
|
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
|
||||||
Process* p = (Process*) Vector_get(this->processes, i);
|
Process* p = (Process*) Vector_get(this->processes, i);
|
||||||
if (p->tombTs > 0) {
|
if (p->tombStampMs > 0) {
|
||||||
// remove tombed process
|
// remove tombed process
|
||||||
if (this->scanTs >= p->tombTs) {
|
if (this->monotonicMs >= p->tombStampMs) {
|
||||||
ProcessList_remove(this, p);
|
ProcessList_remove(this, p);
|
||||||
}
|
}
|
||||||
} else if (p->updated == false) {
|
} else if (p->updated == false) {
|
||||||
// process no longer exists
|
// process no longer exists
|
||||||
if (this->settings->highlightChanges && p->wasShown) {
|
if (this->settings->highlightChanges && p->wasShown) {
|
||||||
// mark tombed
|
// mark tombed
|
||||||
p->tombTs = this->scanTs + 1000 * this->settings->highlightDelaySecs;
|
p->tombStampMs = this->monotonicMs + 1000 * this->settings->highlightDelaySecs;
|
||||||
} else {
|
} else {
|
||||||
// immediately remove
|
// immediately remove
|
||||||
ProcessList_remove(this, p);
|
ProcessList_remove(this, p);
|
||||||
|
|
|
@ -48,8 +48,9 @@ typedef struct ProcessList_ {
|
||||||
Hashtable* displayTreeSet;
|
Hashtable* displayTreeSet;
|
||||||
Hashtable* draftingTreeSet;
|
Hashtable* draftingTreeSet;
|
||||||
|
|
||||||
struct timeval timestamp; /* time of the current sample */
|
struct timeval realtime; /* time of the current sample */
|
||||||
uint64_t timestampMs; /* current time in milliseconds */
|
uint64_t realtimeMs; /* current time in milliseconds */
|
||||||
|
uint64_t monotonicMs; /* same, but from monotonic clock */
|
||||||
|
|
||||||
Panel* panel;
|
Panel* panel;
|
||||||
int following;
|
int following;
|
||||||
|
@ -79,8 +80,6 @@ typedef struct ProcessList_ {
|
||||||
memory_t cachedSwap;
|
memory_t cachedSwap;
|
||||||
|
|
||||||
unsigned int cpuCount;
|
unsigned int cpuCount;
|
||||||
|
|
||||||
time_t scanTs;
|
|
||||||
} ProcessList;
|
} ProcessList;
|
||||||
|
|
||||||
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId);
|
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId);
|
||||||
|
|
|
@ -15,6 +15,7 @@ in the source distribution for its full text.
|
||||||
#include "CRT.h"
|
#include "CRT.h"
|
||||||
#include "FunctionBar.h"
|
#include "FunctionBar.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
#include "Platform.h"
|
||||||
#include "ProcessList.h"
|
#include "ProcessList.h"
|
||||||
#include "ProvideCurses.h"
|
#include "ProvideCurses.h"
|
||||||
#include "XUtils.h"
|
#include "XUtils.h"
|
||||||
|
@ -92,9 +93,8 @@ void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) {
|
||||||
static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTimeout, bool* redraw, bool* rescan, bool* timedOut) {
|
static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTimeout, bool* redraw, bool* rescan, bool* timedOut) {
|
||||||
ProcessList* pl = this->header->pl;
|
ProcessList* pl = this->header->pl;
|
||||||
|
|
||||||
struct timeval tv;
|
Platform_gettime_realtime(&pl->realtime, &pl->realtimeMs);
|
||||||
gettimeofday(&tv, NULL);
|
double newTime = ((double)pl->realtime.tv_sec * 10) + ((double)pl->realtime.tv_usec / 100000);
|
||||||
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
|
|
||||||
|
|
||||||
*timedOut = (newTime - *oldTime > this->settings->delay);
|
*timedOut = (newTime - *oldTime > this->settings->delay);
|
||||||
*rescan |= *timedOut;
|
*rescan |= *timedOut;
|
||||||
|
|
|
@ -37,6 +37,10 @@ in the source distribution for its full text.
|
||||||
#include "zfs/ZfsArcMeter.h"
|
#include "zfs/ZfsArcMeter.h"
|
||||||
#include "zfs/ZfsCompressedArcMeter.h"
|
#include "zfs/ZfsCompressedArcMeter.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_HOST_GET_CLOCK_SERVICE
|
||||||
|
#include <mach/clock.h>
|
||||||
|
#include <mach/mach.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_MACH_MACH_TIME_H
|
#ifdef HAVE_MACH_MACH_TIME_H
|
||||||
#include <mach/mach_time.h>
|
#include <mach/mach_time.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -405,3 +409,23 @@ void Platform_getBattery(double* percent, ACPresence* isOnAC) {
|
||||||
CFRelease(list);
|
CFRelease(list);
|
||||||
CFRelease(power_sources);
|
CFRelease(power_sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Platform_gettime_monotonic(uint64_t* msec) {
|
||||||
|
|
||||||
|
#ifdef HAVE_HOST_GET_CLOCK_SERVICE
|
||||||
|
|
||||||
|
clock_serv_t cclock;
|
||||||
|
mach_timespec_t mts;
|
||||||
|
|
||||||
|
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
|
||||||
|
clock_get_time(cclock, &mts);
|
||||||
|
mach_port_deallocate(mach_task_self(), cclock);
|
||||||
|
|
||||||
|
*msec = ((uint64_t)mts.tv_sec * 1000) + ((uint64_t)mts.tv_nsec / 1000000);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
Generic_gettime_monotomic(msec);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ in the source distribution for its full text.
|
||||||
#include "NetworkIOMeter.h"
|
#include "NetworkIOMeter.h"
|
||||||
#include "ProcessLocksScreen.h"
|
#include "ProcessLocksScreen.h"
|
||||||
#include "SignalsPanel.h"
|
#include "SignalsPanel.h"
|
||||||
|
#include "generic/gettime.h"
|
||||||
#include "generic/hostname.h"
|
#include "generic/hostname.h"
|
||||||
#include "generic/uname.h"
|
#include "generic/uname.h"
|
||||||
|
|
||||||
|
@ -85,4 +86,10 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) {
|
||||||
|
Generic_gettime_realtime(tv, msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_gettime_monotonic(uint64_t* msec);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,6 +17,7 @@ in the source distribution for its full text.
|
||||||
#include "NetworkIOMeter.h"
|
#include "NetworkIOMeter.h"
|
||||||
#include "ProcessLocksScreen.h"
|
#include "ProcessLocksScreen.h"
|
||||||
#include "SignalsPanel.h"
|
#include "SignalsPanel.h"
|
||||||
|
#include "generic/gettime.h"
|
||||||
#include "generic/hostname.h"
|
#include "generic/hostname.h"
|
||||||
#include "generic/uname.h"
|
#include "generic/uname.h"
|
||||||
|
|
||||||
|
@ -75,4 +76,12 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) {
|
||||||
|
Generic_gettime_realtime(tv, msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
||||||
|
Generic_gettime_monotonic(msec);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,6 +18,7 @@ in the source distribution for its full text.
|
||||||
#include "Process.h"
|
#include "Process.h"
|
||||||
#include "ProcessLocksScreen.h"
|
#include "ProcessLocksScreen.h"
|
||||||
#include "SignalsPanel.h"
|
#include "SignalsPanel.h"
|
||||||
|
#include "generic/gettime.h"
|
||||||
#include "generic/hostname.h"
|
#include "generic/hostname.h"
|
||||||
#include "generic/uname.h"
|
#include "generic/uname.h"
|
||||||
|
|
||||||
|
@ -80,4 +81,12 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) {
|
||||||
|
Generic_gettime_realtime(tv, msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
||||||
|
Generic_gettime_monotonic(msec);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
htop - generic/gettime.c
|
||||||
|
(C) 2021 htop dev team
|
||||||
|
Released under the GNU GPLv2, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
*/
|
||||||
|
#include "config.h" // IWYU pragma: keep
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "generic/gettime.h"
|
||||||
|
|
||||||
|
|
||||||
|
void Generic_gettime_realtime(struct timeval* tvp, uint64_t* msec) {
|
||||||
|
|
||||||
|
#if defined(HAVE_CLOCK_GETTIME)
|
||||||
|
|
||||||
|
struct timespec ts;
|
||||||
|
if (clock_gettime(CLOCK_REALTIME, &ts) == 0) {
|
||||||
|
tvp->tv_sec = ts.tv_sec;
|
||||||
|
tvp->tv_usec = ts.tv_nsec / 1000;
|
||||||
|
*msec = ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000);
|
||||||
|
} else {
|
||||||
|
memset(tvp, 0, sizeof(struct timeval));
|
||||||
|
*msec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* lower resolution gettimeofday(2) is always available */
|
||||||
|
|
||||||
|
struct timeval tv;
|
||||||
|
if (gettimeofday(&tv, NULL) == 0) {
|
||||||
|
*tsp = tv; /* struct copy */
|
||||||
|
*msec = ((uint64_t)tv.tv_sec * 1000) + ((uint64_t)tv.tv_usec / 1000);
|
||||||
|
} else {
|
||||||
|
memset(tvp, 0, sizeof(struct timeval));
|
||||||
|
*msec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Generic_gettime_monotonic(uint64_t* msec) {
|
||||||
|
#if defined(HAVE_CLOCK_GETTIME)
|
||||||
|
|
||||||
|
struct timespec ts;
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||||
|
*msec = ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000);
|
||||||
|
else
|
||||||
|
*msec = 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# error "No monotonic clock available"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef HEADER_gettime
|
||||||
|
#define HEADER_gettime
|
||||||
|
/*
|
||||||
|
htop - generic/gettime.h
|
||||||
|
(C) 2021 htop dev team
|
||||||
|
Released under the GNU GPLv2, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
void Generic_gettime_realtime(struct timeval* ts, uint64_t* msec);
|
||||||
|
|
||||||
|
void Generic_gettime_monotonic(uint64_t* msec);
|
||||||
|
|
||||||
|
#endif
|
|
@ -189,13 +189,6 @@ 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);
|
||||||
|
@ -1975,7 +1968,6 @@ 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);
|
||||||
|
@ -2005,5 +1997,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, super->timestampMs);
|
LinuxProcessList_recurseProcTree(this, rootFd, PROCDIR, NULL, period, super->realtimeMs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ in the source distribution for its full text.
|
||||||
#include "Process.h"
|
#include "Process.h"
|
||||||
#include "ProcessLocksScreen.h"
|
#include "ProcessLocksScreen.h"
|
||||||
#include "SignalsPanel.h"
|
#include "SignalsPanel.h"
|
||||||
|
#include "generic/gettime.h"
|
||||||
#include "generic/hostname.h"
|
#include "generic/hostname.h"
|
||||||
#include "generic/uname.h"
|
#include "generic/uname.h"
|
||||||
|
|
||||||
|
@ -93,4 +94,12 @@ void Platform_longOptionsUsage(const char* name);
|
||||||
|
|
||||||
bool Platform_getLongOption(int opt, int argc, char** argv);
|
bool Platform_getLongOption(int opt, int argc, char** argv);
|
||||||
|
|
||||||
|
static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) {
|
||||||
|
Generic_gettime_realtime(tv, msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
||||||
|
Generic_gettime_monotonic(msec);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,6 +19,7 @@ in the source distribution for its full text.
|
||||||
#include "Process.h"
|
#include "Process.h"
|
||||||
#include "ProcessLocksScreen.h"
|
#include "ProcessLocksScreen.h"
|
||||||
#include "SignalsPanel.h"
|
#include "SignalsPanel.h"
|
||||||
|
#include "generic/gettime.h"
|
||||||
#include "generic/hostname.h"
|
#include "generic/hostname.h"
|
||||||
#include "generic/uname.h"
|
#include "generic/uname.h"
|
||||||
|
|
||||||
|
@ -78,4 +79,12 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) {
|
||||||
|
Generic_gettime_realtime(tv, msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
||||||
|
Generic_gettime_monotonic(msec);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,6 +26,7 @@ in the source distribution for its full text.
|
||||||
#include "ProcessLocksScreen.h"
|
#include "ProcessLocksScreen.h"
|
||||||
#include "SignalsPanel.h"
|
#include "SignalsPanel.h"
|
||||||
|
|
||||||
|
#include "generic/gettime.h"
|
||||||
#include "generic/hostname.h"
|
#include "generic/hostname.h"
|
||||||
#include "generic/uname.h"
|
#include "generic/uname.h"
|
||||||
|
|
||||||
|
@ -101,4 +102,12 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) {
|
||||||
|
Generic_gettime_realtime(tv, msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
||||||
|
Generic_gettime_monotonic(msec);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,6 +15,7 @@ in the source distribution for its full text.
|
||||||
#include "ProcessLocksScreen.h"
|
#include "ProcessLocksScreen.h"
|
||||||
#include "SignalsPanel.h"
|
#include "SignalsPanel.h"
|
||||||
#include "UnsupportedProcess.h"
|
#include "UnsupportedProcess.h"
|
||||||
|
#include "generic/gettime.h"
|
||||||
|
|
||||||
|
|
||||||
extern const SignalItem Platform_signals[];
|
extern const SignalItem Platform_signals[];
|
||||||
|
@ -69,4 +70,12 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) {
|
||||||
|
Generic_gettime_realtime(tv, msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
||||||
|
Generic_gettime_monotonic(msec);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue