summaryrefslogtreecommitdiffstats
path: root/src/libnetdata/os
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/libnetdata/os/adjtimex.c16
-rw-r--r--src/libnetdata/os/adjtimex.h13
-rw-r--r--src/libnetdata/os/byteorder.h32
-rw-r--r--src/libnetdata/os/get_pid_max.c58
-rw-r--r--src/libnetdata/os/get_pid_max.h11
-rw-r--r--src/libnetdata/os/get_system_cpus.c93
-rw-r--r--src/libnetdata/os/get_system_cpus.h10
-rw-r--r--src/libnetdata/os/getgrouplist.c16
-rw-r--r--src/libnetdata/os/getgrouplist.h9
-rw-r--r--src/libnetdata/os/gettid.c33
-rw-r--r--src/libnetdata/os/gettid.h11
-rw-r--r--src/libnetdata/os/os-freebsd-wrappers.c73
-rw-r--r--src/libnetdata/os/os-freebsd-wrappers.h29
-rw-r--r--src/libnetdata/os/os-macos-wrappers.c21
-rw-r--r--src/libnetdata/os/os-macos-wrappers.h17
-rw-r--r--src/libnetdata/os/os.c92
-rw-r--r--src/libnetdata/os/os.h37
-rw-r--r--src/libnetdata/os/setenv.c30
-rw-r--r--src/libnetdata/os/setenv.h13
-rw-r--r--src/libnetdata/os/setresgid.c16
-rw-r--r--src/libnetdata/os/setresgid.h9
-rw-r--r--src/libnetdata/os/setresuid.c16
-rw-r--r--src/libnetdata/os/setresuid.h10
-rw-r--r--src/libnetdata/os/strndup.c13
-rw-r--r--src/libnetdata/os/strndup.h12
-rw-r--r--src/libnetdata/os/tinysleep.c23
-rw-r--r--src/libnetdata/os/tinysleep.h8
-rw-r--r--src/libnetdata/os/uuid_generate.c45
-rw-r--r--src/libnetdata/os/uuid_generate.h10
-rw-r--r--src/libnetdata/os/waitid.c72
-rw-r--r--src/libnetdata/os/waitid.h48
31 files changed, 896 insertions, 0 deletions
diff --git a/src/libnetdata/os/adjtimex.c b/src/libnetdata/os/adjtimex.c
new file mode 100644
index 000000000..b7a910095
--- /dev/null
+++ b/src/libnetdata/os/adjtimex.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+int os_adjtimex(struct timex *buf __maybe_unused) {
+#if defined(OS_MACOS) || defined(OS_FREEBSD)
+ return ntp_adjtime(buf);
+#endif
+
+#if defined(OS_LINUX)
+ return adjtimex(buf);
+#endif
+
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/src/libnetdata/os/adjtimex.h b/src/libnetdata/os/adjtimex.h
new file mode 100644
index 000000000..d37ebf887
--- /dev/null
+++ b/src/libnetdata/os/adjtimex.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_ADJTIMEX_H
+#define NETDATA_ADJTIMEX_H
+
+#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_MACOS)
+#include <sys/timex.h>
+#endif
+
+struct timex;
+int os_adjtimex(struct timex *buf);
+
+#endif //NETDATA_ADJTIMEX_H
diff --git a/src/libnetdata/os/byteorder.h b/src/libnetdata/os/byteorder.h
new file mode 100644
index 000000000..28fc9e663
--- /dev/null
+++ b/src/libnetdata/os/byteorder.h
@@ -0,0 +1,32 @@
+#ifndef LIBNETDATA_BYTE_ORDER_H
+#define LIBNETDATA_BYTE_ORDER_H
+
+/** compatibility header for endian.h
+ * This is a simple compatibility shim to convert
+ * BSD/Linux endian macros to the Mac OS X equivalents.
+ * It is public domain.
+ * */
+
+#ifndef __APPLE__
+#error "This header file (endian.h) is MacOS X specific.\n"
+#endif /* __APPLE__ */
+
+
+#include <libkern/OSByteOrder.h>
+
+#define htobe16(x) OSSwapHostToBigInt16(x)
+#define htole16(x) OSSwapHostToLittleInt16(x)
+#define be16toh(x) OSSwapBigToHostInt16(x)
+#define le16toh(x) OSSwapLittleToHostInt16(x)
+
+#define htobe32(x) OSSwapHostToBigInt32(x)
+#define htole32(x) OSSwapHostToLittleInt32(x)
+#define be32toh(x) OSSwapBigToHostInt32(x)
+#define le32toh(x) OSSwapLittleToHostInt32(x)
+
+#define htobe64(x) OSSwapHostToBigInt64(x)
+#define htole64(x) OSSwapHostToLittleInt64(x)
+#define be64toh(x) OSSwapBigToHostInt64(x)
+#define le64toh(x) OSSwapLittleToHostInt64(x)
+
+#endif /* LIBNETDATA_BYTE_ORDER_H */
diff --git a/src/libnetdata/os/get_pid_max.c b/src/libnetdata/os/get_pid_max.c
new file mode 100644
index 000000000..45027961a
--- /dev/null
+++ b/src/libnetdata/os/get_pid_max.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+pid_t pid_max = 32768;
+pid_t os_get_system_pid_max(void) {
+#if defined(OS_MACOS)
+
+ // As we currently do not know a solution to query pid_max from the os
+ // we use the number defined in bsd/sys/proc_internal.h in XNU sources
+ pid_max = 99999;
+ return pid_max;
+
+#elif defined(OS_FREEBSD)
+
+ int32_t tmp_pid_max;
+
+ if (unlikely(GETSYSCTL_BY_NAME("kern.pid_max", tmp_pid_max))) {
+ pid_max = 99999;
+ netdata_log_error("Assuming system's maximum pid is %d.", pid_max);
+ } else {
+ pid_max = tmp_pid_max;
+ }
+
+ return pid_max;
+
+#elif defined(OS_LINUX)
+
+ static char read = 0;
+ if(unlikely(read)) return pid_max;
+ read = 1;
+
+ char filename[FILENAME_MAX + 1];
+ snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", netdata_configured_host_prefix?netdata_configured_host_prefix:"");
+
+ unsigned long long max = 0;
+ if(read_single_number_file(filename, &max) != 0) {
+ netdata_log_error("Cannot open file '%s'. Assuming system supports %d pids.", filename, pid_max);
+ return pid_max;
+ }
+
+ if(!max) {
+ netdata_log_error("Cannot parse file '%s'. Assuming system supports %d pids.", filename, pid_max);
+ return pid_max;
+ }
+
+ pid_max = (pid_t) max;
+ return pid_max;
+
+#else
+
+ // just a big default
+
+ pid_max = 4194304;
+ return pid_max;
+
+#endif
+}
diff --git a/src/libnetdata/os/get_pid_max.h b/src/libnetdata/os/get_pid_max.h
new file mode 100644
index 000000000..a6da0a4df
--- /dev/null
+++ b/src/libnetdata/os/get_pid_max.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_GET_PID_MAX_H
+#define NETDATA_GET_PID_MAX_H
+
+#include <unistd.h>
+
+extern pid_t pid_max;
+pid_t os_get_system_pid_max(void);
+
+#endif //NETDATA_GET_PID_MAX_H
diff --git a/src/libnetdata/os/get_system_cpus.c b/src/libnetdata/os/get_system_cpus.c
new file mode 100644
index 000000000..5a76d8aa5
--- /dev/null
+++ b/src/libnetdata/os/get_system_cpus.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+#if defined(OS_WINDOWS)
+#include <windows.h>
+#endif
+
+#define CPUS_FOR_COLLECTORS 0
+#define CPUS_FOR_NETDATA 1
+
+long os_get_system_cpus_cached(bool cache, bool for_netdata) {
+ static long processors[2] = { 0, 0 };
+
+ int index = for_netdata ? CPUS_FOR_NETDATA : CPUS_FOR_COLLECTORS;
+
+ if(likely(cache && processors[index] > 0))
+ return processors[index];
+
+#if defined(OS_FREEBSD) || defined(OS_MACOS)
+#if defined(OS_MACOS)
+#define HW_CPU_NAME "hw.logicalcpu"
+#else
+#define HW_CPU_NAME "hw.ncpu"
+#endif
+
+ int32_t tmp_processors;
+ bool error = false;
+
+ if (unlikely(GETSYSCTL_BY_NAME(HW_CPU_NAME, tmp_processors)))
+ error = true;
+ else
+ processors[index] = tmp_processors;
+
+ if(processors[index] < 1) {
+ processors[index] = 1;
+
+ if(error)
+ netdata_log_error("Assuming system has %ld processors.", processors[index]);
+ }
+
+ return processors[index];
+#elif defined(OS_LINUX)
+
+ char filename[FILENAME_MAX + 1];
+ snprintfz(filename, FILENAME_MAX, "%s/proc/stat",
+ (!for_netdata && netdata_configured_host_prefix) ? netdata_configured_host_prefix : "");
+
+ procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
+ if(!ff) {
+ processors[index] = 1;
+ netdata_log_error("Cannot open file '%s'. Assuming system has %ld processors.", filename, processors[index]);
+ return processors[index];
+ }
+
+ ff = procfile_readall(ff);
+ if(!ff) {
+ processors[index] = 1;
+ netdata_log_error("Cannot open file '%s'. Assuming system has %ld processors.", filename, processors[index]);
+ return processors[index];
+ }
+
+ long tmp_processors = 0;
+ unsigned int i;
+ for(i = 0; i < procfile_lines(ff); i++) {
+ if(!procfile_linewords(ff, i)) continue;
+
+ if(strncmp(procfile_lineword(ff, i, 0), "cpu", 3) == 0)
+ tmp_processors++;
+ }
+ procfile_close(ff);
+
+ processors[index] = --tmp_processors;
+
+ if(processors[index] < 1)
+ processors[index] = 1;
+
+ netdata_log_debug(D_SYSTEM, "System has %ld processors.", processors[index]);
+ return processors[index];
+
+#elif defined(OS_WINDOWS)
+
+ SYSTEM_INFO sysInfo;
+ GetSystemInfo(&sysInfo);
+ return (long) sysInfo.dwNumberOfProcessors;
+
+#else
+
+ processors[index] = 1;
+ return processors[index];
+
+#endif
+}
diff --git a/src/libnetdata/os/get_system_cpus.h b/src/libnetdata/os/get_system_cpus.h
new file mode 100644
index 000000000..3c608df81
--- /dev/null
+++ b/src/libnetdata/os/get_system_cpus.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_GET_SYSTEM_CPUS_H
+#define NETDATA_GET_SYSTEM_CPUS_H
+
+#include "../libnetdata.h"
+
+long os_get_system_cpus_cached(bool cache, bool for_netdata);
+
+#endif //NETDATA_GET_SYSTEM_CPUS_H
diff --git a/src/libnetdata/os/getgrouplist.c b/src/libnetdata/os/getgrouplist.c
new file mode 100644
index 000000000..7f32faf33
--- /dev/null
+++ b/src/libnetdata/os/getgrouplist.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+int os_getgrouplist(const char *username __maybe_unused, gid_t gid __maybe_unused, gid_t *supplementary_groups __maybe_unused, int *ngroups __maybe_unused) {
+#if defined(OS_LINUX) || defined(OS_FREEBSD)
+ return getgrouplist(username, gid, supplementary_groups, ngroups);
+#endif
+
+#if defined(OS_MACOS)
+ return getgrouplist(username, gid, (int *)supplementary_groups, ngroups);
+#endif
+
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/src/libnetdata/os/getgrouplist.h b/src/libnetdata/os/getgrouplist.h
new file mode 100644
index 000000000..336462553
--- /dev/null
+++ b/src/libnetdata/os/getgrouplist.h
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_GETGROUPLIST_H
+#define NETDATA_GETGROUPLIST_H
+
+#include <unistd.h>
+int os_getgrouplist(const char *username, gid_t gid, gid_t *supplementary_groups, int *ngroups);
+
+#endif //NETDATA_GETGROUPLIST_H
diff --git a/src/libnetdata/os/gettid.c b/src/libnetdata/os/gettid.c
new file mode 100644
index 000000000..273c428f8
--- /dev/null
+++ b/src/libnetdata/os/gettid.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+#if defined(OS_WINDOWS)
+#include <windows.h>
+#endif
+
+pid_t os_gettid(void) {
+#if defined(HAVE_GETTID)
+ return gettid();
+#elif defined(HAVE_PTHREAD_GETTHREADID_NP)
+ return (pid_t)pthread_getthreadid_np();
+#elif defined(HAVE_PTHREAD_THREADID_NP)
+ uint64_t curthreadid;
+ pthread_threadid_np(NULL, &curthreadid);
+ return curthreadid;
+#elif defined(OS_WINDOWS)
+ return (pid_t)GetCurrentThreadId();
+#elif defined(OS_LINUX)
+ return (pid_t)syscall(SYS_gettid);
+#else
+ return (pid_t)pthread_self();
+#endif
+}
+
+static __thread pid_t gettid_cached_tid = 0;
+pid_t gettid_cached(void) {
+ if(unlikely(gettid_cached_tid == 0))
+ gettid_cached_tid = os_gettid();
+
+ return gettid_cached_tid;
+} \ No newline at end of file
diff --git a/src/libnetdata/os/gettid.h b/src/libnetdata/os/gettid.h
new file mode 100644
index 000000000..f04d9c365
--- /dev/null
+++ b/src/libnetdata/os/gettid.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_GETTID_H
+#define NETDATA_GETTID_H
+
+#include <unistd.h>
+
+pid_t os_gettid(void);
+pid_t gettid_cached(void);
+
+#endif //NETDATA_GETTID_H
diff --git a/src/libnetdata/os/os-freebsd-wrappers.c b/src/libnetdata/os/os-freebsd-wrappers.c
new file mode 100644
index 000000000..c3d1bda04
--- /dev/null
+++ b/src/libnetdata/os/os-freebsd-wrappers.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+#if defined(OS_FREEBSD)
+
+int getsysctl_by_name(const char *name, void *ptr, size_t len) {
+ size_t nlen = len;
+
+ if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) {
+ netdata_log_error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno));
+ return 1;
+ }
+ if (unlikely(nlen != len)) {
+ netdata_log_error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
+ return 1;
+ }
+ return 0;
+}
+
+int getsysctl_simple(const char *name, int *mib, size_t miblen, void *ptr, size_t len) {
+ size_t nlen = len;
+
+ if (unlikely(!mib[0]))
+ if (unlikely(getsysctl_mib(name, mib, miblen)))
+ return 1;
+
+ if (unlikely(sysctl(mib, miblen, ptr, &nlen, NULL, 0) == -1)) {
+ netdata_log_error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno));
+ return 1;
+ }
+ if (unlikely(nlen != len)) {
+ netdata_log_error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
+ return 1;
+ }
+
+ return 0;
+}
+
+int getsysctl(const char *name, int *mib, size_t miblen, void *ptr, size_t *len) {
+ size_t nlen = *len;
+
+ if (unlikely(!mib[0]))
+ if (unlikely(getsysctl_mib(name, mib, miblen)))
+ return 1;
+
+ if (unlikely(sysctl(mib, miblen, ptr, len, NULL, 0) == -1)) {
+ netdata_log_error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno));
+ return 1;
+ }
+ if (unlikely(ptr != NULL && nlen != *len)) {
+ netdata_log_error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)*len, (unsigned long)nlen);
+ return 1;
+ }
+
+ return 0;
+}
+
+int getsysctl_mib(const char *name, int *mib, size_t len) {
+ size_t nlen = len;
+
+ if (unlikely(sysctlnametomib(name, mib, &nlen) == -1)) {
+ netdata_log_error("FREEBSD: sysctl(%s...) failed: %s", name, strerror(errno));
+ return 1;
+ }
+ if (unlikely(nlen != len)) {
+ netdata_log_error("FREEBSD: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
+ return 1;
+ }
+ return 0;
+}
+
+#endif
diff --git a/src/libnetdata/os/os-freebsd-wrappers.h b/src/libnetdata/os/os-freebsd-wrappers.h
new file mode 100644
index 000000000..6f54a2e9d
--- /dev/null
+++ b/src/libnetdata/os/os-freebsd-wrappers.h
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_OS_FREEBSD_WRAPPERS_H
+#define NETDATA_OS_FREEBSD_WRAPPERS_H
+
+#include "../libnetdata.h"
+
+#if defined(OS_FREEBSD)
+#include <sys/sysctl.h>
+
+#define GETSYSCTL_BY_NAME(name, var) getsysctl_by_name(name, &(var), sizeof(var))
+int getsysctl_by_name(const char *name, void *ptr, size_t len);
+
+#define GETSYSCTL_MIB(name, mib) getsysctl_mib(name, mib, sizeof(mib)/sizeof(int))
+
+int getsysctl_mib(const char *name, int *mib, size_t len);
+
+#define GETSYSCTL_SIMPLE(name, mib, var) getsysctl_simple(name, mib, sizeof(mib)/sizeof(int), &(var), sizeof(var))
+#define GETSYSCTL_WSIZE(name, mib, var, size) getsysctl_simple(name, mib, sizeof(mib)/sizeof(int), var, size)
+
+int getsysctl_simple(const char *name, int *mib, size_t miblen, void *ptr, size_t len);
+
+#define GETSYSCTL_SIZE(name, mib, size) getsysctl(name, mib, sizeof(mib)/sizeof(int), NULL, &(size))
+#define GETSYSCTL(name, mib, var, size) getsysctl(name, mib, sizeof(mib)/sizeof(int), &(var), &(size))
+
+int getsysctl(const char *name, int *mib, size_t miblen, void *ptr, size_t *len);
+#endif
+
+#endif //NETDATA_OS_FREEBSD_WRAPPERS_H
diff --git a/src/libnetdata/os/os-macos-wrappers.c b/src/libnetdata/os/os-macos-wrappers.c
new file mode 100644
index 000000000..b3d3ee4e6
--- /dev/null
+++ b/src/libnetdata/os/os-macos-wrappers.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+#if defined(OS_MACOS)
+
+int getsysctl_by_name(const char *name, void *ptr, size_t len) {
+ size_t nlen = len;
+
+ if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) {
+ netdata_log_error("MACOS: sysctl(%s...) failed: %s", name, strerror(errno));
+ return 1;
+ }
+ if (unlikely(nlen != len)) {
+ netdata_log_error("MACOS: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
+ return 1;
+ }
+ return 0;
+}
+
+#endif
diff --git a/src/libnetdata/os/os-macos-wrappers.h b/src/libnetdata/os/os-macos-wrappers.h
new file mode 100644
index 000000000..ec863c664
--- /dev/null
+++ b/src/libnetdata/os/os-macos-wrappers.h
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_OS_MACOS_WRAPPERS_H
+#define NETDATA_OS_MACOS_WRAPPERS_H
+
+#include "../libnetdata.h"
+
+#if defined(OS_MACOS)
+#include <sys/sysctl.h>
+#include "byteorder.h"
+
+#define GETSYSCTL_BY_NAME(name, var) getsysctl_by_name(name, &(var), sizeof(var))
+int getsysctl_by_name(const char *name, void *ptr, size_t len);
+
+#endif
+
+#endif //NETDATA_OS_MACOS_WRAPPERS_H
diff --git a/src/libnetdata/os/os.c b/src/libnetdata/os/os.c
new file mode 100644
index 000000000..1caa25f85
--- /dev/null
+++ b/src/libnetdata/os/os.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+// ----------------------------------------------------------------------------
+// system functions
+// to retrieve settings of the system
+
+unsigned int system_hz;
+void os_get_system_HZ(void) {
+ long ticks;
+
+ if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
+ netdata_log_error("Cannot get system clock ticks");
+ }
+
+ system_hz = (unsigned int) ticks;
+}
+
+static inline unsigned long cpuset_str2ul(char **s) {
+ unsigned long n = 0;
+ char c;
+ for(c = **s; c >= '0' && c <= '9' ; c = *(++*s)) {
+ n *= 10;
+ n += c - '0';
+ }
+ return n;
+}
+
+unsigned long os_read_cpuset_cpus(const char *filename, long system_cpus) {
+ static char *buf = NULL;
+ static size_t buf_size = 0;
+
+ if(!buf) {
+ buf_size = 100U + 6 * system_cpus + 1; // taken from kernel/cgroup/cpuset.c
+ buf = mallocz(buf_size);
+ }
+
+ int ret = read_txt_file(filename, buf, buf_size);
+
+ if(!ret) {
+ char *s = buf;
+ unsigned long ncpus = 0;
+
+ // parse the cpuset string and calculate the number of cpus the cgroup is allowed to use
+ while (*s) {
+ if (isspace((uint8_t)*s)) {
+ s++;
+ continue;
+ }
+ unsigned long n = cpuset_str2ul(&s);
+ ncpus++;
+ if(*s == ',') {
+ s++;
+ continue;
+ }
+ if(*s == '-') {
+ s++;
+ unsigned long m = cpuset_str2ul(&s);
+ ncpus += m - n; // calculate the number of cpus in the region
+ }
+ s++;
+ }
+
+ if(!ncpus)
+ return 0;
+
+ return ncpus;
+ }
+
+ return 0;
+}
+
+// =====================================================================================================================
+// os_type
+
+#if defined(OS_LINUX)
+const char *os_type = "linux";
+#endif
+
+#if defined(OS_FREEBSD)
+const char *os_type = "freebsd";
+#endif
+
+#if defined(OS_MACOS)
+const char *os_type = "macos";
+#endif
+
+#if defined(OS_WINDOWS)
+const char *os_type = "windows";
+#endif
+
diff --git a/src/libnetdata/os/os.h b/src/libnetdata/os/os.h
new file mode 100644
index 000000000..350096159
--- /dev/null
+++ b/src/libnetdata/os/os.h
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_OS_H
+#define NETDATA_OS_H
+
+#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_MACOS)
+#include <sys/syscall.h>
+#endif
+
+#include "setresuid.h"
+#include "setresgid.h"
+#include "getgrouplist.h"
+#include "adjtimex.h"
+#include "gettid.h"
+#include "waitid.h"
+#include "get_pid_max.h"
+#include "get_system_cpus.h"
+#include "tinysleep.h"
+#include "uuid_generate.h"
+#include "setenv.h"
+#include "os-freebsd-wrappers.h"
+#include "os-macos-wrappers.h"
+
+// =====================================================================================================================
+// common defs for Apple/FreeBSD/Linux
+
+extern const char *os_type;
+
+#define os_get_system_cpus() os_get_system_cpus_cached(true, false)
+#define os_get_system_cpus_uncached() os_get_system_cpus_cached(false, false)
+long os_get_system_cpus_cached(bool cache, bool for_netdata);
+unsigned long os_read_cpuset_cpus(const char *filename, long system_cpus);
+
+extern unsigned int system_hz;
+void os_get_system_HZ(void);
+
+#endif //NETDATA_OS_H
diff --git a/src/libnetdata/os/setenv.c b/src/libnetdata/os/setenv.c
new file mode 100644
index 000000000..5aa4302b8
--- /dev/null
+++ b/src/libnetdata/os/setenv.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "config.h"
+
+#ifndef HAVE_SETENV
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int os_setenv(const char *name, const char *value, int overwrite) {
+ char *env_var;
+ int result;
+
+ if (!overwrite) {
+ env_var = getenv(name);
+ if (env_var) return 0; // Already set
+ }
+
+ size_t len = strlen(name) + strlen(value) + 2; // +2 for '=' and '\0'
+ env_var = malloc(len);
+ if (!env_var) return -1; // Allocation failure
+ snprintf(env_var, len, "%s=%s", name, value);
+
+ result = putenv(env_var);
+ // free(env_var); // _putenv in Windows makes a copy of the string
+ return result;
+}
+
+#endif
diff --git a/src/libnetdata/os/setenv.h b/src/libnetdata/os/setenv.h
new file mode 100644
index 000000000..3ed63714c
--- /dev/null
+++ b/src/libnetdata/os/setenv.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_SETENV_H
+#define NETDATA_SETENV_H
+
+#include "config.h"
+
+#ifndef HAVE_SETENV
+int os_setenv(const char *name, const char *value, int overwrite);
+#define setenv(name, value, overwrite) os_setenv(name, value, overwrite)
+#endif
+
+#endif //NETDATA_SETENV_H
diff --git a/src/libnetdata/os/setresgid.c b/src/libnetdata/os/setresgid.c
new file mode 100644
index 000000000..e9f1b1860
--- /dev/null
+++ b/src/libnetdata/os/setresgid.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+int os_setresgid(gid_t gid __maybe_unused, gid_t egid __maybe_unused, gid_t sgid __maybe_unused) {
+#if defined(OS_LINUX) || defined(OS_FREEBSD)
+ return setresgid(gid, egid, sgid);
+#endif
+
+#if defined(OS_MACOS)
+ return setregid(gid, egid);
+#endif
+
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/src/libnetdata/os/setresgid.h b/src/libnetdata/os/setresgid.h
new file mode 100644
index 000000000..fc6d41f95
--- /dev/null
+++ b/src/libnetdata/os/setresgid.h
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_SETRESGID_H
+#define NETDATA_SETRESGID_H
+
+#include <unistd.h>
+int os_setresgid(gid_t gid, gid_t egid, gid_t sgid);
+
+#endif //NETDATA_SETRESGID_H
diff --git a/src/libnetdata/os/setresuid.c b/src/libnetdata/os/setresuid.c
new file mode 100644
index 000000000..081690291
--- /dev/null
+++ b/src/libnetdata/os/setresuid.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+int os_setresuid(uid_t uid __maybe_unused, uid_t euid __maybe_unused, uid_t suid __maybe_unused) {
+#if defined(OS_LINUX) || defined(OS_FREEBSD)
+ return setresuid(uid, euid, suid);
+#endif
+
+#if defined(OS_MACOS)
+ return setreuid(uid, euid);
+#endif
+
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/src/libnetdata/os/setresuid.h b/src/libnetdata/os/setresuid.h
new file mode 100644
index 000000000..9f95d5d69
--- /dev/null
+++ b/src/libnetdata/os/setresuid.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_SETRESUID_H
+#define NETDATA_SETRESUID_H
+
+#include <unistd.h>
+
+int os_setresuid(uid_t uid, uid_t euid, uid_t suid);
+
+#endif //NETDATA_SETRESUID_H
diff --git a/src/libnetdata/os/strndup.c b/src/libnetdata/os/strndup.c
new file mode 100644
index 000000000..17210f124
--- /dev/null
+++ b/src/libnetdata/os/strndup.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef HAVE_STRNDUP
+#include "../libnetdata.h"
+
+static inline char *os_strndup( const char *s1, size_t n)
+{
+ char *copy= (char*)malloc( n+1 );
+ memcpy( copy, s1, n );
+ copy[n] = 0;
+ return copy;
+};
+#endif
diff --git a/src/libnetdata/os/strndup.h b/src/libnetdata/os/strndup.h
new file mode 100644
index 000000000..9e51c8fd3
--- /dev/null
+++ b/src/libnetdata/os/strndup.h
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef STRNDUP_H
+#define STRNDUP_H
+
+#include "config.h"
+
+#ifndef HAVE_STRNDUP
+#define strndup(s, n) os_strndup(s, n)
+#endif
+
+#endif //STRNDUP_H
diff --git a/src/libnetdata/os/tinysleep.c b/src/libnetdata/os/tinysleep.c
new file mode 100644
index 000000000..f04cbdadc
--- /dev/null
+++ b/src/libnetdata/os/tinysleep.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+#ifdef OS_WINDOWS
+#include <windows.h>
+
+void tinysleep(void) {
+ // Improve the system timer resolution to 1 ms
+ timeBeginPeriod(1);
+
+ // Sleep for the desired duration
+ Sleep(1);
+
+ // Reset the system timer resolution
+ timeEndPeriod(1);
+}
+#else
+void tinysleep(void) {
+ static const struct timespec ns = { .tv_sec = 0, .tv_nsec = 1 };
+ nanosleep(&ns, NULL);
+}
+#endif
diff --git a/src/libnetdata/os/tinysleep.h b/src/libnetdata/os/tinysleep.h
new file mode 100644
index 000000000..480575a3a
--- /dev/null
+++ b/src/libnetdata/os/tinysleep.h
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_TINYSLEEP_H
+#define NETDATA_TINYSLEEP_H
+
+void tinysleep(void);
+
+#endif //NETDATA_TINYSLEEP_H
diff --git a/src/libnetdata/os/uuid_generate.c b/src/libnetdata/os/uuid_generate.c
new file mode 100644
index 000000000..4a7a9b6bc
--- /dev/null
+++ b/src/libnetdata/os/uuid_generate.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+#undef uuid_generate
+#undef uuid_generate_random
+#undef uuid_generate_time
+
+#ifdef OS_WINDOWS
+#include <windows.h>
+
+void os_uuid_generate(void *out) {
+ RPC_STATUS status = UuidCreate(out);
+ while (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
+ tinysleep();
+ status = UuidCreate(out);
+ }
+}
+
+void os_uuid_generate_random(void *out) {
+ os_uuid_generate(out);
+}
+
+void os_uuid_generate_time(void *out) {
+ os_uuid_generate(out);
+}
+
+#else
+
+#if !defined(OS_MACOS)
+#include <uuid.h>
+#endif
+
+void os_uuid_generate(void *out) {
+ uuid_generate(out);
+}
+
+void os_uuid_generate_random(void *out) {
+ uuid_generate_random(out);
+}
+
+void os_uuid_generate_time(void *out) {
+ uuid_generate_time(out);
+}
+
+#endif
diff --git a/src/libnetdata/os/uuid_generate.h b/src/libnetdata/os/uuid_generate.h
new file mode 100644
index 000000000..95f07c796
--- /dev/null
+++ b/src/libnetdata/os/uuid_generate.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_UUID_GENERATE_H
+#define NETDATA_UUID_GENERATE_H
+
+void os_uuid_generate(void *out);
+void os_uuid_generate_random(void *out);
+void os_uuid_generate_time(void *out);
+
+#endif //NETDATA_UUID_GENERATE_H
diff --git a/src/libnetdata/os/waitid.c b/src/libnetdata/os/waitid.c
new file mode 100644
index 000000000..b78d704ed
--- /dev/null
+++ b/src/libnetdata/os/waitid.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+int os_waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) {
+#if defined(HAVE_WAITID)
+ return waitid(idtype, id, infop, options);
+#else
+ // emulate waitid() using waitpid()
+
+ // a cache for WNOWAIT
+ static const struct pid_status empty = { 0, 0 };
+ static __thread struct pid_status last = { 0, 0 }; // the cache
+ struct pid_status current = { 0, 0 };
+
+ // zero the infop structure
+ memset(infop, 0, sizeof(*infop));
+
+ // from the infop structure we use only 3 fields:
+ // - si_pid
+ // - si_code
+ // - si_status
+ // so, we update only these 3
+
+ switch(idtype) {
+ case P_ALL:
+ current.pid = waitpid((pid_t)-1, &current.status, options);
+ if(options & WNOWAIT)
+ last = current;
+ else
+ last = empty;
+ break;
+
+ case P_PID:
+ if(last.pid == (pid_t)id) {
+ current = last;
+ last = empty;
+ }
+ else
+ current.pid = waitpid((pid_t)id, &current.status, options);
+
+ break;
+
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (current.pid > 0) {
+ if (WIFEXITED(current.status)) {
+ infop->si_code = CLD_EXITED;
+ infop->si_status = WEXITSTATUS(current.status);
+ } else if (WIFSIGNALED(current.status)) {
+ infop->si_code = WTERMSIG(current.status) == SIGABRT ? CLD_DUMPED : CLD_KILLED;
+ infop->si_status = WTERMSIG(current.status);
+ } else if (WIFSTOPPED(current.status)) {
+ infop->si_code = CLD_STOPPED;
+ infop->si_status = WSTOPSIG(current.status);
+ } else if (WIFCONTINUED(current.status)) {
+ infop->si_code = CLD_CONTINUED;
+ infop->si_status = SIGCONT;
+ }
+ infop->si_pid = current.pid;
+ return 0;
+ } else if (current.pid == 0) {
+ // No change in state, depends on WNOHANG
+ return 0;
+ }
+
+ return -1;
+#endif
+}
diff --git a/src/libnetdata/os/waitid.h b/src/libnetdata/os/waitid.h
new file mode 100644
index 000000000..9e1fd6be7
--- /dev/null
+++ b/src/libnetdata/os/waitid.h
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_WAITID_H
+#define NETDATA_WAITID_H
+
+#include "config.h"
+#include <sys/types.h>
+#include <signal.h>
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#ifndef WNOWAIT
+#define WNOWAIT 0x01000000
+#endif
+
+#ifndef WEXITED
+#define WEXITED 4
+#endif
+
+#if !defined(HAVE_WAITID)
+typedef enum
+{
+ P_ALL, /* Wait for any child. */
+ P_PID, /* Wait for specified process. */
+ P_PGID, /* Wait for members of process group. */
+ P_PIDFD, /* Wait for the child referred by the PID file descriptor. */
+} idtype_t;
+
+struct pid_status {
+ pid_t pid;
+ int status;
+};
+
+#if defined(OS_WINDOWS) && !defined(__CYGWIN__)
+typedef uint32_t id_t;
+typedef struct {
+ int si_code; /* Signal code. */
+ int si_status; /* Exit value or signal. */
+ pid_t si_pid; /* Sending process ID. */
+} siginfo_t;
+#endif
+#endif
+
+int os_waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
+
+#endif //NETDATA_WAITID_H