From: Costa Tsaousis (ktsaou) Date: Tue, 5 Jul 2016 23:09:56 +0000 (+0300) Subject: handle usleep() on systems that do not accept more than 999999 usec; implement altern... X-Git-Tag: v1.3.0~87^2 X-Git-Url: https://arthur.barton.de/gitweb/?p=netdata.git;a=commitdiff_plain;h=1c0dc57c4043f8780a92ce99e9871d26d55472a9 handle usleep() on systems that do not accept more than 999999 usec; implement alternative using nanosleep() --- diff --git a/src/apps_plugin.c b/src/apps_plugin.c index 3d94d40a..ba497b7b 100644 --- a/src/apps_plugin.c +++ b/src/apps_plugin.c @@ -2320,7 +2320,7 @@ int main(int argc, char **argv) #ifndef PROFILING_MODE // delay until it is our time to run while((sunow = timems()) < sunext) - usleep((useconds_t)(sunext - sunow)); + usecsleep(sunext - sunow); // find the next time we need to run while(timems() > sunext) diff --git a/src/common.c b/src/common.c index 699f58c6..02d37ab6 100644 --- a/src/common.c +++ b/src/common.c @@ -10,7 +10,7 @@ #include #include #include - +#include #include "log.h" #include "common.h" @@ -27,6 +27,51 @@ unsigned long long timems(void) { return now.tv_sec * 1000000ULL + now.tv_usec; } +int usecsleep(unsigned long long usec) { + +#ifdef NETDATA_WITH_NANOSLEEP + // we expect microseconds (1.000.000 per second) + // but timespec is nanoseconds (1.000.000.000 per second) + struct timespec req = { .tv_sec = usec / 1000000, .tv_nsec = (usec % 1000000) * 1000 }, rem; + + while(nanosleep(&req, &rem) == -1) { + error("nanosleep() failed for %llu microseconds.", usec); + + if(likely(errno == EINTR)) { + req.tv_sec = rem.tv_sec; + req.tv_nsec = rem.tv_nsec; + } + else { + error("Cannot nanosleep() for %llu microseconds.", usec); + break; + } + } + + return 0; +#else + int ret = usleep(usec); + if(unlikely(ret == -1 && errno == EINVAL)) { + // on certain systems, usec has to be up to 999999 + if(usec > 999999) { + int counter = usec / 999999; + while(counter--) + usleep(999999); + + usleep(usec % 999999); + } + else { + error("Cannot usleep() for %llu microseconds.", usec); + return ret; + } + } + + if(ret != 0) + error("usleep() failed for %llu microseconds.", usec); + + return ret; +#endif +} + unsigned char netdata_map_chart_names[256] = { [0] = '\0', // [1] = '_', // diff --git a/src/common.h b/src/common.h index 1502379e..f6736df6 100644 --- a/src/common.h +++ b/src/common.h @@ -46,6 +46,7 @@ extern void get_HZ(void); extern pid_t gettid(void); extern unsigned long long timems(void); +extern int usecsleep(unsigned long long usec); extern char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len); diff --git a/src/plugin_proc.c b/src/plugin_proc.c index 0e2d9c12..e7b8d50c 100644 --- a/src/plugin_proc.c +++ b/src/plugin_proc.c @@ -90,7 +90,7 @@ void *proc_main(void *ptr) // delay until it is our time to run while((sunow = timems()) < sunext) - usleep((useconds_t)(sunext - sunow)); + usecsleep(sunext - sunow); // find the next time we need to run while(timems() > sunext) diff --git a/src/rrd.c b/src/rrd.c index de511e7e..dd7698ab 100644 --- a/src/rrd.c +++ b/src/rrd.c @@ -860,7 +860,7 @@ unsigned long long rrdset_done(RRDSET *st) // calculate the proper last_collected_time, using usec_since_last_update unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec + st->usec_since_last_update; st->last_collected_time.tv_sec = (time_t) (ut / 1000000ULL); - st->last_collected_time.tv_usec = (useconds_t) (ut % 1000000ULL); + st->last_collected_time.tv_usec = (suseconds_t) (ut % 1000000ULL); } // if this set has not been updated in the past @@ -870,7 +870,7 @@ unsigned long long rrdset_done(RRDSET *st) // set a fake last_updated, in the past using usec_since_last_update unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update; st->last_updated.tv_sec = (time_t) (ut / 1000000ULL); - st->last_updated.tv_usec = (useconds_t) (ut % 1000000ULL); + st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL); // the first entry should not be stored store_this_entry = 0; @@ -890,7 +890,7 @@ unsigned long long rrdset_done(RRDSET *st) unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update; st->last_updated.tv_sec = (time_t) (ut / 1000000ULL); - st->last_updated.tv_usec = (useconds_t) (ut % 1000000ULL); + st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL); // the first entry should not be stored store_this_entry = 0; diff --git a/src/sys_fs_cgroup.c b/src/sys_fs_cgroup.c index 670da064..5f139c89 100644 --- a/src/sys_fs_cgroup.c +++ b/src/sys_fs_cgroup.c @@ -1275,7 +1275,7 @@ void *cgroups_main(void *ptr) // delay until it is our time to run while((sunow = timems()) < sunext) - usleep((useconds_t)(sunext - sunow)); + usecsleep(sunext - sunow); // find the next time we need to run while(timems() > sunext)