Merge branch 'smalinux-CtrTime'

This commit is contained in:
Nathan Scott 2021-04-07 15:19:18 +10:00
commit f3a37f9ef3
25 changed files with 220 additions and 87 deletions

View File

@ -20,9 +20,10 @@ static const int ClockMeter_attributes[] = {
};
static void ClockMeter_updateValues(Meter* this) {
time_t t = time(NULL);
const ProcessList* pl = this->pl;
struct tm result;
const struct tm* lt = localtime_r(&t, &result);
const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result);
this->values[0] = lt->tm_hour * 60 + lt->tm_min;
strftime(this->txtBuffer, sizeof(this->txtBuffer), "%H:%M:%S", lt);
}

View File

@ -11,18 +11,12 @@ in the source distribution for its full text.
#include <errno.h>
#include <fcntl.h> // IWYU pragma: keep
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.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,
const char* pathname,
@ -123,31 +117,3 @@ ssize_t Compat_readlinkat(int dirfd,
#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
}

View File

@ -56,6 +56,4 @@ ssize_t Compat_readlinkat(int dirfd,
char* buf,
size_t bufsize);
int Compat_clock_monotonic_gettime(struct timespec *tp);
#endif /* HEADER_Compat */

View File

@ -20,9 +20,10 @@ static const int DateMeter_attributes[] = {
};
static void DateMeter_updateValues(Meter* this) {
time_t t = time(NULL);
const ProcessList* pl = this->pl;
struct tm result;
const struct tm* lt = localtime_r(&t, &result);
const struct tm* lt = localtime_r(&pl->realtime.tv_sec, &result);
this->values[0] = lt->tm_yday;
int year = lt->tm_year + 1900;
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {

View File

@ -20,9 +20,10 @@ static const int DateTimeMeter_attributes[] = {
};
static void DateTimeMeter_updateValues(Meter* this) {
time_t t = time(NULL);
const ProcessList* pl = this->pl;
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;
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
this->total = 366;

View File

@ -31,12 +31,10 @@ static uint32_t cached_write_diff;
static double cached_utilisation_diff;
static void DiskIOMeter_updateValues(Meter* this) {
static uint64_t cached_last_update;
const ProcessList* pl = this->pl;
struct timeval tv;
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;
static uint64_t cached_last_update;
uint64_t passedTimeInMs = pl->realtimeMs - cached_last_update;
/* update only every 500ms */
if (passedTimeInMs > 500) {
@ -45,7 +43,7 @@ static void DiskIOMeter_updateValues(Meter* this) {
static uint64_t cached_msTimeSpend_total;
uint64_t diff;
cached_last_update = timeInMilliSeconds;
cached_last_update = pl->realtimeMs;
DiskIOData data;

View File

@ -134,6 +134,7 @@ myhtopheaders = \
# -----
linux_platform_headers = \
generic/gettime.h \
generic/hostname.h \
generic/uname.h \
linux/HugePageMeter.h \
@ -154,6 +155,7 @@ linux_platform_headers = \
zfs/ZfsCompressedArcMeter.h
linux_platform_sources = \
generic/gettime.c \
generic/hostname.c \
generic/uname.c \
linux/HugePageMeter.c \
@ -184,6 +186,7 @@ freebsd_platform_headers = \
freebsd/FreeBSDProcess.h \
freebsd/Platform.h \
freebsd/ProcessField.h \
generic/gettime.h \
generic/hostname.h \
generic/openzfs_sysctl.h \
generic/uname.h \
@ -195,6 +198,7 @@ freebsd_platform_sources = \
freebsd/Platform.c \
freebsd/FreeBSDProcessList.c \
freebsd/FreeBSDProcess.c \
generic/gettime.c \
generic/hostname.c \
generic/openzfs_sysctl.c \
generic/uname.c \
@ -215,6 +219,7 @@ dragonflybsd_platform_headers = \
dragonflybsd/DragonFlyBSDProcess.h \
dragonflybsd/Platform.h \
dragonflybsd/ProcessField.h \
generic/gettime.h \
generic/hostname.h \
generic/uname.h
@ -222,6 +227,7 @@ dragonflybsd_platform_sources = \
dragonflybsd/DragonFlyBSDProcessList.c \
dragonflybsd/DragonFlyBSDProcess.c \
dragonflybsd/Platform.c \
generic/gettime.c \
generic/hostname.c \
generic/uname.c
@ -235,6 +241,7 @@ endif
# -------
openbsd_platform_headers = \
generic/gettime.h \
generic/hostname.h \
generic/uname.h \
openbsd/OpenBSDProcessList.h \
@ -243,6 +250,7 @@ openbsd_platform_headers = \
openbsd/ProcessField.h
openbsd_platform_sources = \
generic/gettime.c \
generic/hostname.c \
generic/uname.c \
openbsd/OpenBSDProcessList.c \
@ -263,6 +271,7 @@ darwin_platform_headers = \
darwin/DarwinProcessList.h \
darwin/Platform.h \
darwin/ProcessField.h \
generic/gettime.h \
generic/hostname.h \
generic/openzfs_sysctl.h \
generic/uname.h \
@ -274,6 +283,7 @@ darwin_platform_sources = \
darwin/Platform.c \
darwin/DarwinProcess.c \
darwin/DarwinProcessList.c \
generic/gettime.c \
generic/hostname.c \
generic/openzfs_sysctl.c \
generic/uname.c \
@ -291,6 +301,7 @@ endif
# -------
solaris_platform_headers = \
generic/gettime.h \
generic/hostname.h \
generic/uname.h \
solaris/ProcessField.h \
@ -302,6 +313,7 @@ solaris_platform_headers = \
zfs/ZfsCompressedArcMeter.h
solaris_platform_sources = \
generic/gettime.c \
generic/hostname.c \
generic/uname.c \
solaris/Platform.c \
@ -320,12 +332,14 @@ endif
# -----------
unsupported_platform_headers = \
generic/gettime.h \
unsupported/Platform.h \
unsupported/ProcessField.h \
unsupported/UnsupportedProcess.h \
unsupported/UnsupportedProcessList.h
unsupported_platform_sources = \
generic/gettime.c \
unsupported/Platform.c \
unsupported/UnsupportedProcess.c \
unsupported/UnsupportedProcessList.c

View File

@ -18,6 +18,7 @@ in the source distribution for its full text.
#include "CRT.h"
#include "Macros.h"
#include "Object.h"
#include "Platform.h"
#include "ProvideCurses.h"
#include "RichString.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) {
const ProcessList* pl = this->pl;
if (!this->drawData) {
this->drawData = xCalloc(1, sizeof(GraphData));
@ -312,12 +314,10 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
x += captionLen;
w -= captionLen;
struct timeval now;
gettimeofday(&now, NULL);
if (!timercmp(&now, &(data->time), <)) {
if (!timercmp(&pl->realtime, &(data->time), <)) {
int globalDelay = this->pl->settings->delay;
struct timeval delay = { .tv_sec = globalDelay / 10, .tv_usec = (globalDelay - ((globalDelay / 10) * 10)) * 100000 };
timeradd(&now, &delay, &(data->time));
timeradd(&pl->realtime, &delay, &(data->time));
for (int i = 0; i < nValues - 1; i++)
data->values[i] = data->values[i + 1];

View File

@ -25,12 +25,10 @@ static uint32_t cached_txb_diff;
static uint32_t cached_txp_diff;
static void NetworkIOMeter_updateValues(Meter* this) {
const ProcessList* pl = this->pl;
static uint64_t cached_last_update = 0;
struct timeval tv;
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;
uint64_t passedTimeInMs = pl->realtimeMs - cached_last_update;
/* update only every 500ms */
if (passedTimeInMs > 500) {
@ -40,7 +38,7 @@ static void NetworkIOMeter_updateValues(Meter* this) {
static uint64_t cached_txp_total;
uint64_t diff;
cached_last_update = timeInMilliSeconds;
cached_last_update = pl->realtimeMs;
NetworkIOData data;
hasData = Platform_getNetworkIO(&data);

View File

@ -467,14 +467,14 @@ void Process_toggleTag(Process* this) {
bool Process_isNew(const Process* this) {
assert(this->processList);
if (this->processList->scanTs >= this->seenTs) {
return this->processList->scanTs - this->seenTs <= 1000 * this->processList->settings->highlightDelaySecs;
if (this->processList->monotonicMs >= this->seenStampMs) {
return this->processList->monotonicMs - this->seenStampMs <= 1000 * (uint64_t)this->processList->settings->highlightDelaySecs;
}
return false;
}
bool Process_isTomb(const Process* this) {
return this->tombTs > 0;
return this->tombStampMs > 0;
}
bool Process_setPriority(Process* this, int priority) {

View File

@ -174,8 +174,8 @@ typedef struct Process_ {
/*
* Internal time counts for showing new and exited processes.
*/
time_t seenTs;
time_t tombTs;
uint64_t seenStampMs;
uint64_t tombStampMs;
/*
* Internal state for tree-mode.

View File

@ -10,11 +10,12 @@ in the source distribution for its full text.
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include "Compat.h"
#include "CRT.h"
#include "Hashtable.h"
#include "Macros.h"
#include "Platform.h"
#include "Vector.h"
#include "XUtils.h"
@ -35,7 +36,7 @@ ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, Users
// set later by platform-specific code
this->cpuCount = 0;
this->scanTs = 0;
this->monotonicMs = 0;
#ifdef HAVE_LIBHWLOC
this->topologyOk = false;
@ -131,7 +132,7 @@ void ProcessList_add(ProcessList* this, Process* p) {
p->processList = this;
// 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);
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) {
struct timespec now;
// in pause mode only gather global data for meters (CPU/memory/...)
if (pauseProcessUpdate) {
ProcessList_goThroughEntries(this, true);
@ -604,31 +603,29 @@ void ProcessList_scan(ProcessList* this, bool pauseProcessUpdate) {
this->runningTasks = 0;
// set scanTs
// set scan timestamp
static bool firstScanDone = false;
if (!firstScanDone) {
this->scanTs = 0;
if (firstScanDone) {
Platform_gettime_monotonic(&this->monotonicMs);
} else {
this->monotonicMs = 0;
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);
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
Process* p = (Process*) Vector_get(this->processes, i);
if (p->tombTs > 0) {
if (p->tombStampMs > 0) {
// remove tombed process
if (this->scanTs >= p->tombTs) {
if (this->monotonicMs >= p->tombStampMs) {
ProcessList_remove(this, p);
}
} else if (p->updated == false) {
// process no longer exists
if (this->settings->highlightChanges && p->wasShown) {
// mark tombed
p->tombTs = this->scanTs + 1000 * this->settings->highlightDelaySecs;
p->tombStampMs = this->monotonicMs + 1000 * this->settings->highlightDelaySecs;
} else {
// immediately remove
ProcessList_remove(this, p);

View File

@ -48,6 +48,10 @@ typedef struct ProcessList_ {
Hashtable* displayTreeSet;
Hashtable* draftingTreeSet;
struct timeval realtime; /* time of the current sample */
uint64_t realtimeMs; /* current time in milliseconds */
uint64_t monotonicMs; /* same, but from monotonic clock */
Panel* panel;
int following;
uid_t userId;
@ -76,8 +80,6 @@ typedef struct ProcessList_ {
memory_t cachedSwap;
unsigned int cpuCount;
time_t scanTs;
} ProcessList;
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId);

View File

@ -15,6 +15,7 @@ in the source distribution for its full text.
#include "CRT.h"
#include "FunctionBar.h"
#include "Object.h"
#include "Platform.h"
#include "ProcessList.h"
#include "ProvideCurses.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) {
ProcessList* pl = this->header->pl;
struct timeval tv;
gettimeofday(&tv, NULL);
double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
Platform_gettime_realtime(&pl->realtime, &pl->realtimeMs);
double newTime = ((double)pl->realtime.tv_sec * 10) + ((double)pl->realtime.tv_usec / 100000);
*timedOut = (newTime - *oldTime > this->settings->delay);
*rescan |= *timedOut;

View File

@ -37,6 +37,10 @@ in the source distribution for its full text.
#include "zfs/ZfsArcMeter.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
#include <mach/mach_time.h>
#endif
@ -405,3 +409,23 @@ void Platform_getBattery(double* percent, ACPresence* isOnAC) {
CFRelease(list);
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
}

View File

@ -19,6 +19,7 @@ in the source distribution for its full text.
#include "NetworkIOMeter.h"
#include "ProcessLocksScreen.h"
#include "SignalsPanel.h"
#include "generic/gettime.h"
#include "generic/hostname.h"
#include "generic/uname.h"
@ -85,4 +86,10 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
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

View File

@ -17,6 +17,7 @@ in the source distribution for its full text.
#include "NetworkIOMeter.h"
#include "ProcessLocksScreen.h"
#include "SignalsPanel.h"
#include "generic/gettime.h"
#include "generic/hostname.h"
#include "generic/uname.h"
@ -75,4 +76,12 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
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

View File

@ -18,6 +18,7 @@ in the source distribution for its full text.
#include "Process.h"
#include "ProcessLocksScreen.h"
#include "SignalsPanel.h"
#include "generic/gettime.h"
#include "generic/hostname.h"
#include "generic/uname.h"
@ -80,4 +81,12 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
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

57
generic/gettime.c Normal file
View File

@ -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
}

19
generic/gettime.h Normal file
View File

@ -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

View File

@ -1989,10 +1989,6 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
return;
}
struct timeval tv;
gettimeofday(&tv, NULL);
unsigned long long now = tv.tv_sec * 1000ULL + tv.tv_usec / 1000ULL;
/* PROCDIR is an absolute path */
assert(PROCDIR[0] == '/');
#ifdef HAVE_OPENAT
@ -2001,5 +1997,5 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
openat_arg_t rootFd = "";
#endif
LinuxProcessList_recurseProcTree(this, rootFd, PROCDIR, NULL, period, now);
LinuxProcessList_recurseProcTree(this, rootFd, PROCDIR, NULL, period, super->realtimeMs);
}

View File

@ -19,6 +19,7 @@ in the source distribution for its full text.
#include "Process.h"
#include "ProcessLocksScreen.h"
#include "SignalsPanel.h"
#include "generic/gettime.h"
#include "generic/hostname.h"
#include "generic/uname.h"
@ -93,4 +94,12 @@ void Platform_longOptionsUsage(const char* name);
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

View File

@ -19,6 +19,7 @@ in the source distribution for its full text.
#include "Process.h"
#include "ProcessLocksScreen.h"
#include "SignalsPanel.h"
#include "generic/gettime.h"
#include "generic/hostname.h"
#include "generic/uname.h"
@ -78,4 +79,12 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
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

View File

@ -26,6 +26,7 @@ in the source distribution for its full text.
#include "ProcessLocksScreen.h"
#include "SignalsPanel.h"
#include "generic/gettime.h"
#include "generic/hostname.h"
#include "generic/uname.h"
@ -101,4 +102,12 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
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

View File

@ -15,6 +15,7 @@ in the source distribution for its full text.
#include "ProcessLocksScreen.h"
#include "SignalsPanel.h"
#include "UnsupportedProcess.h"
#include "generic/gettime.h"
extern const SignalItem Platform_signals[];
@ -69,4 +70,12 @@ static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int a
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