]> arthur.barton.de Git - netdata.git/commitdiff
handle usleep() on systems that do not accept more than 999999 usec; implement altern...
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Tue, 5 Jul 2016 23:09:56 +0000 (02:09 +0300)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Tue, 5 Jul 2016 23:09:56 +0000 (02:09 +0300)
src/apps_plugin.c
src/common.c
src/common.h
src/plugin_proc.c
src/rrd.c
src/sys_fs_cgroup.c

index 3d94d40ad89770488dbddff2d00eb277944e3458..ba497b7b9ce17949c5b3dae30cfc006b00b11e8f 100644 (file)
@@ -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)
index 699f58c64d025938456eb35553795dcb6711db32..02d37ab675ccd8a8c7dba1a12e8f0bcfb9efeed2 100644 (file)
@@ -10,7 +10,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/mman.h>
-
+#include <time.h>
 
 #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] = '_', //
index 1502379e77917b191d28561f22c37d8568ebad3e..f6736df68470c2cb178b17c6f653c11d7bb49b00 100644 (file)
@@ -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);
 
index 0e2d9c1227018b513317f009fe64677fd104f905..e7b8d50c87d64c2695c4b63373eb92418f496cdf 100644 (file)
@@ -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)
index de511e7e6c9f813075e4a31e10377f26d40e23fb..dd7698ab8d443cbfd526e11f2512a45e20e15e33 100644 (file)
--- 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;
index 670da064ac38a1fee24e6dc917f7e3b92b008e15..5f139c891ee824b220f96b12bbd6ac96a501b1cc 100644 (file)
@@ -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)