#include "common.h"
+#ifdef __APPLE__
+#define INHERIT_NONE 0
+#endif /* __APPLE__ */
+#if defined(__FreeBSD__) || defined(__APPLE__)
+# define O_NOATIME 0
+# define MADV_DONTFORK INHERIT_NONE
+#endif /* __FreeBSD__ || __APPLE__*/
+
char *global_host_prefix = "";
int enable_ksm = 1;
// its lifetime), these can be used to override the default system allocation
// routines.
+#ifdef NETDATA_LOG_ALLOCATIONS
+static struct memory_statistics {
+ volatile size_t malloc_calls_made;
+ volatile size_t calloc_calls_made;
+ volatile size_t realloc_calls_made;
+ volatile size_t strdup_calls_made;
+ volatile size_t free_calls_made;
+ volatile size_t memory_calls_made;
+ volatile size_t allocated_memory;
+ volatile size_t mmapped_memory;
+} memory_statistics;
+
+static inline void print_allocations(const char *file, const char *function, const unsigned long line) {
+ static struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ //if(unlikely(!(memory_statistics.memory_calls_made % 5))) {
+ fprintf(stderr, "(%04lu@%-10.10s:%-15.15s): Allocated %zu KB (+%zu B), mmapped %zu KB (+%zu B): malloc %zu (+%zu), calloc %zu (+%zu), realloc %zu (+%zu), strdup %zu (+%zu), free %zu (+%zu)\n",
+ line, file, function,
+ (memory_statistics.allocated_memory + 512) / 1024, memory_statistics.allocated_memory - old.allocated_memory,
+ (memory_statistics.mmapped_memory + 512) / 1024, memory_statistics.mmapped_memory - old.mmapped_memory,
+ memory_statistics.malloc_calls_made, memory_statistics.malloc_calls_made - old.malloc_calls_made,
+ memory_statistics.calloc_calls_made, memory_statistics.calloc_calls_made - old.calloc_calls_made,
+ memory_statistics.realloc_calls_made, memory_statistics.realloc_calls_made - old.realloc_calls_made,
+ memory_statistics.strdup_calls_made, memory_statistics.strdup_calls_made - old.strdup_calls_made,
+ memory_statistics.free_calls_made, memory_statistics.free_calls_made - old.free_calls_made
+ );
+
+ memcpy(&old, &memory_statistics, sizeof(struct memory_statistics));
+ //}
+}
+
+static inline void malloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.malloc_calls_made++;
+ memory_statistics.allocated_memory += size;
+#endif
+ print_allocations(file, function, line);
+}
+
+static inline void mmap_accounting(size_t size) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.mmapped_memory, size, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.mmapped_memory += size;
+#endif
+}
+
+static inline void calloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.calloc_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.calloc_calls_made++;
+ memory_statistics.allocated_memory += size;
+#endif
+ print_allocations(file, function, line);
+}
+
+static inline void realloc_accounting(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
+ (void)ptr;
+
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.realloc_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.realloc_calls_made++;
+ memory_statistics.allocated_memory += size;
+#endif
+ print_allocations(file, function, line);
+}
+
+static inline void strdup_accounting(const char *file, const char *function, const unsigned long line, const char *s) {
+ size_t size = strlen(s) + 1;
+
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.strdup_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.strdup_calls_made++;
+ memory_statistics.allocated_memory += size;
+#endif
+ print_allocations(file, function, line);
+}
+
+static inline void free_accounting(const char *file, const char *function, const unsigned long line, void *ptr) {
+ (void)file;
+ (void)function;
+ (void)line;
+
+ if(likely(ptr)) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.free_calls_made, 1, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.free_calls_made++;
+#endif
+ }
+}
+#endif
+
+#ifdef NETDATA_LOG_ALLOCATIONS
+char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s) {
+ strdup_accounting(file, function, line, s);
+#else
char *strdupz(const char *s) {
+#endif
+
char *t = strdup(s);
if (unlikely(!t)) fatal("Cannot strdup() string '%s'", s);
return t;
}
+#ifdef NETDATA_LOG_ALLOCATIONS
+void *mallocz_int(const char *file, const char *function, const unsigned long line, size_t size) {
+ malloc_accounting(file, function, line, size);
+#else
void *mallocz(size_t size) {
+#endif
+
void *p = malloc(size);
if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", size);
return p;
}
+#ifdef NETDATA_LOG_ALLOCATIONS
+void *callocz_int(const char *file, const char *function, const unsigned long line, size_t nmemb, size_t size) {
+ calloc_accounting(file, function, line, nmemb * size);
+#else
void *callocz(size_t nmemb, size_t size) {
+#endif
+
void *p = calloc(nmemb, size);
if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", nmemb * size);
return p;
}
+#ifdef NETDATA_LOG_ALLOCATIONS
+void *reallocz_int(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
+ realloc_accounting(file, function, line, ptr, size);
+#else
void *reallocz(void *ptr, size_t size) {
+#endif
+
void *p = realloc(ptr, size);
if (unlikely(!p)) fatal("Cannot re-allocate memory to %zu bytes.", size);
return p;
}
+#ifdef NETDATA_LOG_ALLOCATIONS
+void freez_int(const char *file, const char *function, const unsigned long line, void *ptr) {
+ free_accounting(file, function, line, ptr);
+#else
void freez(void *ptr) {
+#endif
+
free(ptr);
}
-// ----------------------------------------------------------------------------
-// time functions
-
-inline unsigned long long timeval_usec(struct timeval *tv) {
- return tv->tv_sec * 1000000ULL + tv->tv_usec;
-}
+void json_escape_string(char *dst, const char *src, size_t size) {
+ const char *t;
+ char *d = dst, *e = &dst[size - 1];
-// time(NULL) in nanoseconds
-inline unsigned long long time_usec(void) {
- struct timeval now;
- gettimeofday(&now, NULL);
- return timeval_usec(&now);
-}
+ for(t = src; *t && d < e ;t++) {
+ if(unlikely(*t == '\\' || *t == '"')) {
+ if(unlikely(d + 1 >= e)) break;
+ *d++ = '\\';
+ }
+ *d++ = *t;
+ }
-inline unsigned long long usec_dt(struct timeval *now, struct timeval *old) {
- unsigned long long tv1 = timeval_usec(now);
- unsigned long long tv2 = timeval_usec(old);
- return (tv1 > tv2) ? (tv1 - tv2) : (tv2 - tv1);
+ *d = '\0';
}
-int sleep_usec(unsigned long long usec) {
+int sleep_usec(usec_t usec) {
#ifndef NETDATA_WITH_USLEEP
// we expect microseconds (1.000.000 per second)
while (nanosleep(&req, &rem) == -1) {
if (likely(errno == EINTR)) {
- info("nanosleep() interrupted (while sleeping for %llu microseconds).", usec);
+ debug(D_SYSTEM, "nanosleep() interrupted (while sleeping for %llu microseconds).", usec);
req.tv_sec = rem.tv_sec;
req.tv_nsec = rem.tv_nsec;
} else {
}
*/
-
+/*
// http://isthe.com/chongo/tech/comp/fnv/#FNV-1a
uint32_t simple_hash(const char *name) {
unsigned char *s = (unsigned char *) name;
}
return hval;
}
+*/
/*
// http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
*/
void strreverse(char *begin, char *end) {
- char aux;
-
while (end > begin) {
// clearer code.
- aux = *end;
+ char aux = *end;
*end-- = *begin;
*begin++ = aux;
}
#ifdef MADV_MERGEABLE
static int log_madvise_2 = 1, log_madvise_3 = 1;
#endif
- int fd;
void *mem = NULL;
errno = 0;
- fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
+ int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
if (fd != -1) {
if (lseek(fd, size, SEEK_SET) == (off_t) size) {
if (write(fd, "", 1) == 1) {
if (flags & MAP_SHARED || !enable_ksm || !ksm) {
#endif
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
- if (mem != MAP_FAILED) {
+ if (mem == MAP_FAILED) {
+ error("Cannot allocate SHARED memory for file '%s'.", filename);
+ mem = NULL;
+ }
+ else {
+#ifdef NETDATA_LOG_ALLOCATIONS
+ mmap_accounting(size);
+#endif
int advise = MADV_SEQUENTIAL | MADV_DONTFORK;
if (flags & MAP_SHARED) advise |= MADV_WILLNEED;
}
}
#ifdef MADV_MERGEABLE
- } else {
+ }
+ else {
/*
// test - load the file into memory
mem = calloc(1, size);
}
*/
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
- if (mem != MAP_FAILED) {
+ if (mem == MAP_FAILED) {
+ error("Cannot allocate PRIVATE ANONYMOUS memory for KSM for file '%s'.", filename);
+ mem = NULL;
+ }
+ else {
+#ifdef NETDATA_LOG_ALLOCATIONS
+ mmap_accounting(size);
+#endif
if (lseek(fd, 0, SEEK_SET) == 0) {
if (read(fd, mem, size) != (ssize_t) size)
error("Cannot read from file '%s'", filename);
filename);
log_madvise_3--;
}
- } else
- error("Cannot allocate PRIVATE ANONYMOUS memory for KSM for file '%s'.", filename);
+ }
}
#endif
- } else
+ }
+ else
error("Cannot write to file '%s' at position %zu.", filename, size);
- } else
+ }
+ else
error("Cannot seek file '%s' to size %zu.", filename, size);
close(fd);
- } else
+ }
+ else
error("Cannot create/open file '%s'.", filename);
return mem;
return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}
-/*
- ***************************************************************************
- * Get number of clock ticks per second.
- ***************************************************************************
- */
-unsigned int hz;
-
-void get_HZ(void) {
- long ticks;
-
- if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
- perror("sysconf");
- }
-
- hz = (unsigned int) ticks;
-}
-
pid_t gettid(void) {
+#ifdef __FreeBSD__
+ return (pid_t)pthread_getthreadid_np();
+#elif defined(__APPLE__)
+ uint64_t curthreadid;
+ pthread_threadid_np(NULL, &curthreadid);
+ return (pid_t)curthreadid;
+#else
return (pid_t)syscall(SYS_gettid);
+#endif /* __FreeBSD__, __APPLE__*/
}
char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
return s;
}
-char *strncpyz(char *dst, const char *src, size_t n) {
- char *p = dst;
-
- while (*src && n--)
- *dst++ = *src++;
-
- *dst = '\0';
-
- return p;
-}
-
int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
int size = vsnprintf(dst, n, fmt, args);
return ret;
}
+
+// ----------------------------------------------------------------------------
+// system functions
+// to retrieve settings of the system
+
+int processors = 1;
+long get_system_cpus(void) {
+ processors = 1;
+
+ #ifdef __APPLE__
+ int32_t tmp_processors;
+
+ if (unlikely(GETSYSCTL("hw.logicalcpu", tmp_processors))) {
+ error("Assuming system has %d processors.", processors);
+ } else {
+ processors = tmp_processors;
+ }
+
+ return processors;
+ #elif __FreeBSD__
+ int32_t tmp_processors;
+
+ if (unlikely(GETSYSCTL("hw.ncpu", tmp_processors))) {
+ error("Assuming system has %d processors.", processors);
+ } else {
+ processors = tmp_processors;
+ }
+
+ return processors;
+ #else
+
+ char filename[FILENAME_MAX + 1];
+ snprintfz(filename, FILENAME_MAX, "%s/proc/stat", global_host_prefix);
+
+ procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
+ if(!ff) {
+ error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
+ return processors;
+ }
+
+ ff = procfile_readall(ff);
+ if(!ff) {
+ error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
+ return processors;
+ }
+
+ 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) processors++;
+ }
+ processors--;
+ if(processors < 1) processors = 1;
+
+ procfile_close(ff);
+
+ debug(D_SYSTEM, "System has %d processors.", processors);
+ return processors;
+
+ #endif /* __APPLE__, __FreeBSD__ */
+}
+
+pid_t pid_max = 32768;
+pid_t get_system_pid_max(void) {
+ #ifdef __APPLE__
+ // 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 __FreeBSD__
+ int32_t tmp_pid_max;
+
+ if (unlikely(GETSYSCTL("kern.pid_max", tmp_pid_max))) {
+ pid_max = 99999;
+ error("Assuming system's maximum pid is %d.", pid_max);
+ } else {
+ pid_max = tmp_pid_max;
+ }
+
+ return pid_max;
+ #else
+
+ 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", global_host_prefix);
+
+ unsigned long long max = 0;
+ if(read_single_number_file(filename, &max) != 0) {
+ error("Cannot open file '%s'. Assuming system supports %d pids.", filename, pid_max);
+ return pid_max;
+ }
+
+ if(!max) {
+ error("Cannot parse file '%s'. Assuming system supports %d pids.", filename, pid_max);
+ return pid_max;
+ }
+
+ pid_max = (pid_t) max;
+ return pid_max;
+
+ #endif /* __APPLE__, __FreeBSD__ */
+}
+
+unsigned int hz;
+void get_system_HZ(void) {
+ long ticks;
+
+ if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
+ error("Cannot get system clock ticks");
+ }
+
+ hz = (unsigned int) ticks;
+}
+
+/*
+// poor man cycle counting
+static unsigned long tsc;
+void begin_tsc(void) {
+ unsigned long a, d;
+ asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
+ tsc = ((unsigned long)d << 32) | (unsigned long)a;
+}
+unsigned long end_tsc(void) {
+ unsigned long a, d;
+ asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
+ return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
+}
+*/