diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/fdstat_sysctl.c | 80 | ||||
-rw-r--r-- | generic/fdstat_sysctl.h | 13 | ||||
-rw-r--r-- | generic/gettime.c | 62 | ||||
-rw-r--r-- | generic/gettime.h | 18 | ||||
-rw-r--r-- | generic/hostname.c | 18 | ||||
-rw-r--r-- | generic/hostname.h | 15 | ||||
-rw-r--r-- | generic/openzfs_sysctl.c | 104 | ||||
-rw-r--r-- | generic/openzfs_sysctl.h | 17 | ||||
-rw-r--r-- | generic/uname.c | 99 | ||||
-rw-r--r-- | generic/uname.h | 12 |
10 files changed, 438 insertions, 0 deletions
diff --git a/generic/fdstat_sysctl.c b/generic/fdstat_sysctl.c new file mode 100644 index 0000000..ea374fb --- /dev/null +++ b/generic/fdstat_sysctl.c @@ -0,0 +1,80 @@ +/* +htop - generic/fdstat_sysctl.c +(C) 2022-2023 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 "generic/fdstat_sysctl.h" + +#include <math.h> +#include <stddef.h> +#include <stdint.h> + +#include <sys/types.h> // Shitty FreeBSD upstream headers +#include <sys/sysctl.h> + + +static void Generic_getFileDescriptors_sysctl_internal( + const char* sysctlname_maxfiles, + const char* sysctlname_numfiles, + size_t size_header, + size_t size_entry, + double* used, + double* max +) { + *used = NAN; + *max = 65536; + + int max_fd, open_fd; + size_t len; + + len = sizeof(max_fd); + if (sysctlname_maxfiles && sysctlbyname(sysctlname_maxfiles, &max_fd, &len, NULL, 0) == 0) { + if (max_fd) { + *max = max_fd; + } else { + *max = NAN; + } + } + + len = sizeof(open_fd); + if (sysctlname_numfiles && sysctlbyname(sysctlname_numfiles, &open_fd, &len, NULL, 0) == 0) { + *used = open_fd; + return; + } + + // If no sysctl arc available, try to guess from the file table size at kern.file + // The size per entry differs per OS, thus skip if we don't know: + if (!size_entry) + return; + + len = 0; + if (sysctlbyname("kern.file", NULL, &len, NULL, 0) < 0) + return; + + if (len < size_header) + return; + + *used = (len - size_header) / size_entry; +} + +void Generic_getFileDescriptors_sysctl(double* used, double* max) { +#if defined(HTOP_DARWIN) + Generic_getFileDescriptors_sysctl_internal( + "kern.maxfiles", "kern.num_files", 0, 0, used, max); +#elif defined(HTOP_DRAGONFLY) + Generic_getFileDescriptors_sysctl_internal( + "kern.maxfiles", NULL, 0, sizeof(struct kinfo_file), used, max); +#elif defined(HTOP_FREEBSD) + Generic_getFileDescriptors_sysctl_internal( + "kern.maxfiles", "kern.openfiles", 0, 0, used, max); +#elif defined(HTOP_NETBSD) + Generic_getFileDescriptors_sysctl_internal( + "kern.maxfiles", NULL, 0, sizeof(struct kinfo_file), used, max); +#else +#error Unknown platform: Please implement proper way to query open/max file information +#endif +} diff --git a/generic/fdstat_sysctl.h b/generic/fdstat_sysctl.h new file mode 100644 index 0000000..107fcab --- /dev/null +++ b/generic/fdstat_sysctl.h @@ -0,0 +1,13 @@ +#ifndef HEADER_fdstat_sysctl +#define HEADER_fdstat_sysctl +/* +htop - generic/fdstat_sysctl.h +(C) 2022-2023 htop dev team +Released under the GNU GPLv2+, see the COPYING file +in the source distribution for its full text. +*/ + + +void Generic_getFileDescriptors_sysctl(double* used, double* max); + +#endif diff --git a/generic/gettime.c b/generic/gettime.c new file mode 100644 index 0000000..209f523 --- /dev/null +++ b/generic/gettime.c @@ -0,0 +1,62 @@ +/* +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 "generic/gettime.h" + +#include <string.h> +#include <time.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) { + *tvp = 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 /* lower resolution gettimeofday() should be always available */ + + struct timeval tv; + if (gettimeofday(&tv, NULL) == 0) + *msec = ((uint64_t)tv.tv_sec * 1000) + ((uint64_t)tv.tv_usec / 1000); + else + *msec = 0; + +#endif +} diff --git a/generic/gettime.h b/generic/gettime.h new file mode 100644 index 0000000..91fe43d --- /dev/null +++ b/generic/gettime.h @@ -0,0 +1,18 @@ +#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> + + +void Generic_gettime_realtime(struct timeval* tvp, uint64_t* msec); + +void Generic_gettime_monotonic(uint64_t* msec); + +#endif diff --git a/generic/hostname.c b/generic/hostname.c new file mode 100644 index 0000000..e327582 --- /dev/null +++ b/generic/hostname.c @@ -0,0 +1,18 @@ +/* +htop - generic/hostname.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 "generic/hostname.h" + +#include <unistd.h> + + +void Generic_hostname(char* buffer, size_t size) { + gethostname(buffer, size - 1); + buffer[size - 1] = '\0'; +} diff --git a/generic/hostname.h b/generic/hostname.h new file mode 100644 index 0000000..1e6c52d --- /dev/null +++ b/generic/hostname.h @@ -0,0 +1,15 @@ +#ifndef HEADER_hostname +#define HEADER_hostname +/* +htop - generic/hostname.h +(C) 2021 htop dev team +Released under the GNU GPLv2+, see the COPYING file +in the source distribution for its full text. +*/ + +#include <stddef.h> + + +void Generic_hostname(char* buffer, size_t size); + +#endif diff --git a/generic/openzfs_sysctl.c b/generic/openzfs_sysctl.c new file mode 100644 index 0000000..bcd37dc --- /dev/null +++ b/generic/openzfs_sysctl.c @@ -0,0 +1,104 @@ +/* +htop - generic/openzfs_sysctl.c +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2+, see the COPYING file +in the source distribution for its full text. +*/ + +#include "generic/openzfs_sysctl.h" + +#include <stdlib.h> +#include <sys/types.h> // IWYU pragma: keep +#include <sys/sysctl.h> // needs <sys/types.h> for u_int with gcc + +#include "zfs/ZfsArcStats.h" + + +static int MIB_kstat_zfs_misc_arcstats_size[5]; +static int MIB_kstat_zfs_misc_arcstats_c_min[5]; +static int MIB_kstat_zfs_misc_arcstats_c_max[5]; +static int MIB_kstat_zfs_misc_arcstats_mfu_size[5]; +static int MIB_kstat_zfs_misc_arcstats_mru_size[5]; +static int MIB_kstat_zfs_misc_arcstats_anon_size[5]; +static int MIB_kstat_zfs_misc_arcstats_hdr_size[5]; +static int MIB_kstat_zfs_misc_arcstats_other_size[5]; +static int MIB_kstat_zfs_misc_arcstats_compressed_size[5]; +static int MIB_kstat_zfs_misc_arcstats_uncompressed_size[5]; + +void openzfs_sysctl_init(ZfsArcStats* stats) { + size_t len; + unsigned long long int arcSize; + + len = sizeof(arcSize); + if (sysctlbyname("kstat.zfs.misc.arcstats.size", &arcSize, &len, NULL, 0) == 0 && arcSize != 0) { + stats->enabled = 1; + + len = 5; + sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); + + sysctlnametomib("kstat.zfs.misc.arcstats.c_min", MIB_kstat_zfs_misc_arcstats_c_min, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.c_max", MIB_kstat_zfs_misc_arcstats_c_max, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.mfu_size", MIB_kstat_zfs_misc_arcstats_mfu_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.mru_size", MIB_kstat_zfs_misc_arcstats_mru_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.anon_size", MIB_kstat_zfs_misc_arcstats_anon_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.hdr_size", MIB_kstat_zfs_misc_arcstats_hdr_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.other_size", MIB_kstat_zfs_misc_arcstats_other_size, &len); + + if (sysctlnametomib("kstat.zfs.misc.arcstats.compressed_size", MIB_kstat_zfs_misc_arcstats_compressed_size, &len) == 0) { + stats->isCompressed = 1; + sysctlnametomib("kstat.zfs.misc.arcstats.uncompressed_size", MIB_kstat_zfs_misc_arcstats_uncompressed_size, &len); + } else { + stats->isCompressed = 0; + } + } else { + stats->enabled = 0; + } +} + +void openzfs_sysctl_updateArcStats(ZfsArcStats* stats) { + size_t len; + + if (stats->enabled) { + len = sizeof(stats->size); + sysctl(MIB_kstat_zfs_misc_arcstats_size, 5, &(stats->size), &len, NULL, 0); + stats->size /= 1024; + + len = sizeof(stats->min); + sysctl(MIB_kstat_zfs_misc_arcstats_c_min, 5, &(stats->min), &len, NULL, 0); + stats->min /= 1024; + + len = sizeof(stats->max); + sysctl(MIB_kstat_zfs_misc_arcstats_c_max, 5, &(stats->max), &len, NULL, 0); + stats->max /= 1024; + + len = sizeof(stats->MFU); + sysctl(MIB_kstat_zfs_misc_arcstats_mfu_size, 5, &(stats->MFU), &len, NULL, 0); + stats->MFU /= 1024; + + len = sizeof(stats->MRU); + sysctl(MIB_kstat_zfs_misc_arcstats_mru_size, 5, &(stats->MRU), &len, NULL, 0); + stats->MRU /= 1024; + + len = sizeof(stats->anon); + sysctl(MIB_kstat_zfs_misc_arcstats_anon_size, 5, &(stats->anon), &len, NULL, 0); + stats->anon /= 1024; + + len = sizeof(stats->header); + sysctl(MIB_kstat_zfs_misc_arcstats_hdr_size, 5, &(stats->header), &len, NULL, 0); + stats->header /= 1024; + + len = sizeof(stats->other); + sysctl(MIB_kstat_zfs_misc_arcstats_other_size, 5, &(stats->other), &len, NULL, 0); + stats->other /= 1024; + + if (stats->isCompressed) { + len = sizeof(stats->compressed); + sysctl(MIB_kstat_zfs_misc_arcstats_compressed_size, 5, &(stats->compressed), &len, NULL, 0); + stats->compressed /= 1024; + + len = sizeof(stats->uncompressed); + sysctl(MIB_kstat_zfs_misc_arcstats_uncompressed_size, 5, &(stats->uncompressed), &len, NULL, 0); + stats->uncompressed /= 1024; + } + } +} diff --git a/generic/openzfs_sysctl.h b/generic/openzfs_sysctl.h new file mode 100644 index 0000000..27fa720 --- /dev/null +++ b/generic/openzfs_sysctl.h @@ -0,0 +1,17 @@ +#ifndef HEADER_openzfs_sysctl +#define HEADER_openzfs_sysctl +/* +htop - generic/openzfs_sysctl.h +(C) 2014 Hisham H. Muhammad +Released under the GNU GPLv2+, see the COPYING file +in the source distribution for its full text. +*/ + +#include "zfs/ZfsArcStats.h" + + +void openzfs_sysctl_init(ZfsArcStats* stats); + +void openzfs_sysctl_updateArcStats(ZfsArcStats* stats); + +#endif diff --git a/generic/uname.c b/generic/uname.c new file mode 100644 index 0000000..b5bb583 --- /dev/null +++ b/generic/uname.c @@ -0,0 +1,99 @@ +/* +htop - generic/uname.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 "generic/uname.h" + +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include "Macros.h" +#include "XUtils.h" + +#ifdef HAVE_SYS_UTSNAME_H +#include <sys/utsname.h> +#endif + + +#ifndef OSRELEASEFILE +#define OSRELEASEFILE "/etc/os-release" +#endif + +static void parseOSRelease(char* buffer, size_t bufferLen) { + FILE* stream = fopen(OSRELEASEFILE, "r"); + if (!stream) { + xSnprintf(buffer, bufferLen, "No OS Release"); + return; + } + + char name[64] = {'\0'}; + char version[64] = {'\0'}; + char lineBuffer[256]; + while (fgets(lineBuffer, sizeof(lineBuffer), stream)) { + if (String_startsWith(lineBuffer, "PRETTY_NAME=\"")) { + const char* start = lineBuffer + strlen("PRETTY_NAME=\""); + const char* stop = strrchr(lineBuffer, '"'); + if (!stop || stop <= start) + continue; + String_safeStrncpy(buffer, start, MINIMUM(bufferLen, (size_t)(stop - start + 1))); + fclose(stream); + return; + } + if (String_startsWith(lineBuffer, "NAME=\"")) { + const char* start = lineBuffer + strlen("NAME=\""); + const char* stop = strrchr(lineBuffer, '"'); + if (!stop || stop <= start) + continue; + String_safeStrncpy(name, start, MINIMUM(sizeof(name), (size_t)(stop - start + 1))); + continue; + } + if (String_startsWith(lineBuffer, "VERSION=\"")) { + const char* start = lineBuffer + strlen("VERSION=\""); + const char* stop = strrchr(lineBuffer, '"'); + if (!stop || stop <= start) + continue; + String_safeStrncpy(version, start, MINIMUM(sizeof(version), (size_t)(stop - start + 1))); + continue; + } + } + fclose(stream); + + snprintf(buffer, bufferLen, "%s%s%s", name[0] ? name : "", name[0] && version[0] ? " " : "", version); +} + +char* Generic_uname(void) { + static char savedString[ + /* uname structure fields - manpages recommend sizeof */ + sizeof(((struct utsname*)0)->sysname) + + sizeof(((struct utsname*)0)->release) + + sizeof(((struct utsname*)0)->machine) + + 16/*markup*/ + + 128/*distro*/] = {'\0'}; + static bool loaded_data = false; + + if (!loaded_data) { + struct utsname uname_info; + int uname_result = uname(&uname_info); + + char distro[128]; + parseOSRelease(distro, sizeof(distro)); + + if (uname_result == 0) { + size_t written = xSnprintf(savedString, sizeof(savedString), "%s %s [%s]", uname_info.sysname, uname_info.release, uname_info.machine); + if (!String_contains_i(savedString, distro, false) && sizeof(savedString) > written) + snprintf(savedString + written, sizeof(savedString) - written, " @ %s", distro); + } else { + snprintf(savedString, sizeof(savedString), "%s", distro); + } + + loaded_data = true; + } + + return savedString; +} diff --git a/generic/uname.h b/generic/uname.h new file mode 100644 index 0000000..940d64c --- /dev/null +++ b/generic/uname.h @@ -0,0 +1,12 @@ +#ifndef HEADER_uname +#define HEADER_uname +/* +htop - generic/uname.h +(C) 2021 htop dev team +Released under the GNU GPLv2+, see the COPYING file +in the source distribution for its full text. +*/ + +char* Generic_uname(void); + +#endif |