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)