@cryptotaxi247 / netdata-1 / commits / 1c0dc57c4

handle usleep() on systems that do not accept more than 999999 usec; implement alternative using nanosleep()

Costa Tsaousis (ktsaou) committed Jul 6, 2016 at 02:09 UTC 1c0dc57c4043f8780a92ce99e9871d26d55472a9
6 files changed +53 -7
src/apps_plugin.c
+1 -1
@@ -2320,7 +2320,7 @@ int main(int argc, char **argv)
2320 #ifndef PROFILING_MODE
2321 // delay until it is our time to run
2322 while((sunow = timems()) < sunext)
2323 - usleep((useconds_t)(sunext - sunow));
2323 + usecsleep(sunext - sunow);
2324
2325 // find the next time we need to run
2326 while(timems() > sunext)
src/common.c
+46 -1
@@ -10,7 +10,7 @@
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <sys/mman.h>
13 -
13 +#include <time.h>
14
15 #include "log.h"
16 #include "common.h"
@@ -27,6 +27,51 @@ unsigned long long timems(void) {
27 return now.tv_sec * 1000000ULL + now.tv_usec;
28 }
29
30 +int usecsleep(unsigned long long usec) {
31 +
32 +#ifdef NETDATA_WITH_NANOSLEEP
33 + // we expect microseconds (1.000.000 per second)
34 + // but timespec is nanoseconds (1.000.000.000 per second)
35 + struct timespec req = { .tv_sec = usec / 1000000, .tv_nsec = (usec % 1000000) * 1000 }, rem;
36 +
37 + while(nanosleep(&req, &rem) == -1) {
38 + error("nanosleep() failed for %llu microseconds.", usec);
39 +
40 + if(likely(errno == EINTR)) {
41 + req.tv_sec = rem.tv_sec;
42 + req.tv_nsec = rem.tv_nsec;
43 + }
44 + else {
45 + error("Cannot nanosleep() for %llu microseconds.", usec);
46 + break;
47 + }
48 + }
49 +
50 + return 0;
51 +#else
52 + int ret = usleep(usec);
53 + if(unlikely(ret == -1 && errno == EINVAL)) {
54 + // on certain systems, usec has to be up to 999999
55 + if(usec > 999999) {
56 + int counter = usec / 999999;
57 + while(counter--)
58 + usleep(999999);
59 +
60 + usleep(usec % 999999);
61 + }
62 + else {
63 + error("Cannot usleep() for %llu microseconds.", usec);
64 + return ret;
65 + }
66 + }
67 +
68 + if(ret != 0)
69 + error("usleep() failed for %llu microseconds.", usec);
70 +
71 + return ret;
72 +#endif
73 +}
74 +
75 unsigned char netdata_map_chart_names[256] = {
76 [0] = '\0', //
77 [1] = '_', //
src/common.h
+1
@@ -46,6 +46,7 @@ extern void get_HZ(void);
46 extern pid_t gettid(void);
47
48 extern unsigned long long timems(void);
49 +extern int usecsleep(unsigned long long usec);
50
51 extern char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len);
52
src/plugin_proc.c
+1 -1
@@ -90,7 +90,7 @@ void *proc_main(void *ptr)
90
91 // delay until it is our time to run
92 while((sunow = timems()) < sunext)
93 - usleep((useconds_t)(sunext - sunow));
93 + usecsleep(sunext - sunow);
94
95 // find the next time we need to run
96 while(timems() > sunext)
src/rrd.c
+3 -3
@@ -860,7 +860,7 @@ unsigned long long rrdset_done(RRDSET *st)
860 // calculate the proper last_collected_time, using usec_since_last_update
861 unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec + st->usec_since_last_update;
862 st->last_collected_time.tv_sec = (time_t) (ut / 1000000ULL);
863 - st->last_collected_time.tv_usec = (useconds_t) (ut % 1000000ULL);
863 + st->last_collected_time.tv_usec = (suseconds_t) (ut % 1000000ULL);
864 }
865
866 // if this set has not been updated in the past
@@ -870,7 +870,7 @@ unsigned long long rrdset_done(RRDSET *st)
870 // set a fake last_updated, in the past using usec_since_last_update
871 unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
872 st->last_updated.tv_sec = (time_t) (ut / 1000000ULL);
873 - st->last_updated.tv_usec = (useconds_t) (ut % 1000000ULL);
873 + st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
874
875 // the first entry should not be stored
876 store_this_entry = 0;
@@ -890,7 +890,7 @@ unsigned long long rrdset_done(RRDSET *st)
890
891 unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
892 st->last_updated.tv_sec = (time_t) (ut / 1000000ULL);
893 - st->last_updated.tv_usec = (useconds_t) (ut % 1000000ULL);
893 + st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
894
895 // the first entry should not be stored
896 store_this_entry = 0;
src/sys_fs_cgroup.c
+1 -1
@@ -1275,7 +1275,7 @@ void *cgroups_main(void *ptr)
1275
1276 // delay until it is our time to run
1277 while((sunow = timems()) < sunext)
1278 - usleep((useconds_t)(sunext - sunow));
1278 + usecsleep(sunext - sunow);
1279
1280 // find the next time we need to run
1281 while(timems() > sunext)