diff options
Diffstat (limited to '')
-rw-r--r-- | libnetdata/libnetdata.c | 215 |
1 files changed, 175 insertions, 40 deletions
diff --git a/libnetdata/libnetdata.c b/libnetdata/libnetdata.c index cc04a97e..f6b6b026 100644 --- a/libnetdata/libnetdata.c +++ b/libnetdata/libnetdata.c @@ -21,6 +21,81 @@ int enable_ksm = 0; volatile sig_atomic_t netdata_exit = 0; const char *program_version = VERSION; +#define MAX_JUDY_SIZE_TO_ARAL 24 +static bool judy_sizes_config[MAX_JUDY_SIZE_TO_ARAL + 1] = { + [3] = true, + [4] = true, + [5] = true, + [6] = true, + [7] = true, + [8] = true, + [10] = true, + [11] = true, + [15] = true, + [23] = true, +}; +static ARAL *judy_sizes_aral[MAX_JUDY_SIZE_TO_ARAL + 1] = {}; + +struct aral_statistics judy_sizes_aral_statistics = {}; + +void aral_judy_init(void) { + for(size_t Words = 0; Words <= MAX_JUDY_SIZE_TO_ARAL; Words++) + if(judy_sizes_config[Words]) { + char buf[30+1]; + snprintfz(buf, 30, "judy-%zu", Words * sizeof(Word_t)); + judy_sizes_aral[Words] = aral_create( + buf, + Words * sizeof(Word_t), + 0, + 65536, + &judy_sizes_aral_statistics, + NULL, NULL, false, false); + } +} + +size_t judy_aral_overhead(void) { + return aral_overhead_from_stats(&judy_sizes_aral_statistics); +} + +size_t judy_aral_structures(void) { + return aral_structures_from_stats(&judy_sizes_aral_statistics); +} + +static ARAL *judy_size_aral(Word_t Words) { + if(Words <= MAX_JUDY_SIZE_TO_ARAL && judy_sizes_aral[Words]) + return judy_sizes_aral[Words]; + + return NULL; +} + +inline Word_t JudyMalloc(Word_t Words) { + Word_t Addr; + + ARAL *ar = judy_size_aral(Words); + if(ar) + Addr = (Word_t) aral_mallocz(ar); + else + Addr = (Word_t) mallocz(Words * sizeof(Word_t)); + + return(Addr); +} + +inline void JudyFree(void * PWord, Word_t Words) { + ARAL *ar = judy_size_aral(Words); + if(ar) + aral_freez(ar, PWord); + else + freez(PWord); +} + +Word_t JudyMallocVirtual(Word_t Words) { + return JudyMalloc(Words); +} + +void JudyFreeVirtual(void * PWord, Word_t Words) { + JudyFree(PWord, Words); +} + // ---------------------------------------------------------------------------- // memory allocation functions that handle failures @@ -150,27 +225,6 @@ void posix_memfree(void *ptr) { libc_free(ptr); } -Word_t JudyMalloc(Word_t Words) { - Word_t Addr; - - Addr = (Word_t) mallocz(Words * sizeof(Word_t)); - return(Addr); -} -void JudyFree(void * PWord, Word_t Words) { - (void)Words; - freez(PWord); -} -Word_t JudyMallocVirtual(Word_t Words) { - Word_t Addr; - - Addr = (Word_t) mallocz(Words * sizeof(Word_t)); - return(Addr); -} -void JudyFreeVirtual(void * PWord, Word_t Words) { - (void)Words; - freez(PWord); -} - #define MALLOC_ALIGNMENT (sizeof(uintptr_t) * 2) #define size_t_atomic_count(op, var, size) __atomic_## op ##_fetch(&(var), size, __ATOMIC_RELAXED) #define size_t_atomic_bytes(op, var, size) __atomic_## op ##_fetch(&(var), ((size) % MALLOC_ALIGNMENT)?((size) + MALLOC_ALIGNMENT - ((size) % MALLOC_ALIGNMENT)):(size), __ATOMIC_RELAXED) @@ -1176,7 +1230,7 @@ static int memory_file_open(const char *filename, size_t size) { return fd; } -static inline int madvise_sequential(void *mem, size_t len) { +inline int madvise_sequential(void *mem, size_t len) { static int logger = 1; int ret = madvise(mem, len, MADV_SEQUENTIAL); @@ -1184,7 +1238,15 @@ static inline int madvise_sequential(void *mem, size_t len) { return ret; } -static inline int madvise_dontfork(void *mem, size_t len) { +inline int madvise_random(void *mem, size_t len) { + static int logger = 1; + int ret = madvise(mem, len, MADV_RANDOM); + + if (ret != 0 && logger-- > 0) error("madvise(MADV_RANDOM) failed."); + return ret; +} + +inline int madvise_dontfork(void *mem, size_t len) { static int logger = 1; int ret = madvise(mem, len, MADV_DONTFORK); @@ -1192,7 +1254,7 @@ static inline int madvise_dontfork(void *mem, size_t len) { return ret; } -static inline int madvise_willneed(void *mem, size_t len) { +inline int madvise_willneed(void *mem, size_t len) { static int logger = 1; int ret = madvise(mem, len, MADV_WILLNEED); @@ -1200,24 +1262,27 @@ static inline int madvise_willneed(void *mem, size_t len) { return ret; } +inline int madvise_dontneed(void *mem, size_t len) { + static int logger = 1; + int ret = madvise(mem, len, MADV_DONTNEED); + + if (ret != 0 && logger-- > 0) error("madvise(MADV_DONTNEED) failed."); + return ret; +} + +inline int madvise_dontdump(void *mem __maybe_unused, size_t len __maybe_unused) { #if __linux__ -static inline int madvise_dontdump(void *mem, size_t len) { static int logger = 1; int ret = madvise(mem, len, MADV_DONTDUMP); if (ret != 0 && logger-- > 0) error("madvise(MADV_DONTDUMP) failed."); return ret; -} #else -static inline int madvise_dontdump(void *mem, size_t len) { - UNUSED(mem); - UNUSED(len); - return 0; -} #endif +} -static inline int madvise_mergeable(void *mem, size_t len) { +inline int madvise_mergeable(void *mem __maybe_unused, size_t len __maybe_unused) { #ifdef MADV_MERGEABLE static int logger = 1; int ret = madvise(mem, len, MADV_MERGEABLE); @@ -1225,14 +1290,12 @@ static inline int madvise_mergeable(void *mem, size_t len) { if (ret != 0 && logger-- > 0) error("madvise(MADV_MERGEABLE) failed."); return ret; #else - UNUSED(mem); - UNUSED(len); - return 0; #endif } -void *netdata_mmap(const char *filename, size_t size, int flags, int ksm) { +void *netdata_mmap(const char *filename, size_t size, int flags, int ksm, bool read_only, int *open_fd) +{ // info("netdata_mmap('%s', %zu", filename, size); // MAP_SHARED is used in memory mode map @@ -1271,7 +1334,7 @@ void *netdata_mmap(const char *filename, size_t size, int flags, int ksm) { fd_for_mmap = -1; } - mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd_for_mmap, 0); + mem = mmap(NULL, size, read_only ? PROT_READ : PROT_READ | PROT_WRITE, flags, fd_for_mmap, 0); if (mem != MAP_FAILED) { #ifdef NETDATA_TRACE_ALLOCATIONS @@ -1288,15 +1351,20 @@ void *netdata_mmap(const char *filename, size_t size, int flags, int ksm) { else info("Cannot seek to beginning of file '%s'.", filename); } - madvise_sequential(mem, size); + // madvise_sequential(mem, size); madvise_dontfork(mem, size); madvise_dontdump(mem, size); - if(flags & MAP_SHARED) madvise_willneed(mem, size); + // if(flags & MAP_SHARED) madvise_willneed(mem, size); if(ksm) madvise_mergeable(mem, size); } cleanup: - if(fd != -1) close(fd); + if(fd != -1) { + if (open_fd) + *open_fd = fd; + else + close(fd); + } if(mem == MAP_FAILED) return NULL; errno = 0; return mem; @@ -1934,3 +2002,70 @@ bool run_command_and_copy_output_to_stdout(const char *command, int max_line_len netdata_pclose(NULL, fp, pid); return true; } + +void for_each_open_fd(OPEN_FD_ACTION action, OPEN_FD_EXCLUDE excluded_fds){ + int fd; + + switch(action){ + case OPEN_FD_ACTION_CLOSE: + if(!(excluded_fds & OPEN_FD_EXCLUDE_STDIN)) (void)close(STDIN_FILENO); + if(!(excluded_fds & OPEN_FD_EXCLUDE_STDOUT)) (void)close(STDOUT_FILENO); + if(!(excluded_fds & OPEN_FD_EXCLUDE_STDERR)) (void)close(STDERR_FILENO); + break; + case OPEN_FD_ACTION_FD_CLOEXEC: + if(!(excluded_fds & OPEN_FD_EXCLUDE_STDIN)) (void)fcntl(STDIN_FILENO, F_SETFD, FD_CLOEXEC); + if(!(excluded_fds & OPEN_FD_EXCLUDE_STDOUT)) (void)fcntl(STDOUT_FILENO, F_SETFD, FD_CLOEXEC); + if(!(excluded_fds & OPEN_FD_EXCLUDE_STDERR)) (void)fcntl(STDERR_FILENO, F_SETFD, FD_CLOEXEC); + break; + default: + break; // do nothing + } + +#if defined(HAVE_CLOSE_RANGE) + if(close_range(STDERR_FILENO + 1, ~0U, (action == OPEN_FD_ACTION_FD_CLOEXEC ? CLOSE_RANGE_CLOEXEC : 0)) == 0) return; + error("close_range() failed, will try to close fds manually"); +#endif + + DIR *dir = opendir("/proc/self/fd"); + if (dir == NULL) { + struct rlimit rl; + int open_max = -1; + + if(getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) open_max = rl.rlim_max; +#ifdef _SC_OPEN_MAX + else open_max = sysconf(_SC_OPEN_MAX); +#endif + + if (open_max == -1) open_max = 65535; // 65535 arbitrary default if everything else fails + + for (fd = STDERR_FILENO + 1; fd < open_max; fd++) { + switch(action){ + case OPEN_FD_ACTION_CLOSE: + if(fd_is_valid(fd)) (void)close(fd); + break; + case OPEN_FD_ACTION_FD_CLOEXEC: + (void)fcntl(fd, F_SETFD, FD_CLOEXEC); + break; + default: + break; // do nothing + } + } + } else { + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + fd = str2i(entry->d_name); + if(unlikely((fd == STDIN_FILENO ) || (fd == STDOUT_FILENO) || (fd == STDERR_FILENO) )) continue; + switch(action){ + case OPEN_FD_ACTION_CLOSE: + if(fd_is_valid(fd)) (void)close(fd); + break; + case OPEN_FD_ACTION_FD_CLOEXEC: + (void)fcntl(fd, F_SETFD, FD_CLOEXEC); + break; + default: + break; // do nothing + } + } + closedir(dir); + } +} |