From d9e87383613d4d24efe3d1eb144ad6c9cc30b2b0 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 7 Jan 2015 16:57:36 +0100 Subject: [PATCH] pipelimit: take in consideration number of cpus for load - on multi core systems, the sums of stats can go over 100%, resulting in out of range for expected load_value to be 0.0 to 1.0 - safety checks to avoid overflows - reported by Luca M. --- modules/pipelimit/pipelimit.c | 43 ++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/modules/pipelimit/pipelimit.c b/modules/pipelimit/pipelimit.c index a060df78f0a..b966fc59944 100644 --- a/modules/pipelimit/pipelimit.c +++ b/modules/pipelimit/pipelimit.c @@ -182,6 +182,36 @@ struct module_exports exports= { }; +#if defined (__OS_darwin) || defined (__OS_freebsd) +#include +#include +#else +#include +#endif + +int get_num_cpus() { + int count = 0; + +#if defined (__OS_darwin) || defined (__OS_freebsd) + int nm[2]; + size_t len; + + len = sizeof(count); + + nm[0] = CTL_HW; nm[1] = HW_AVAILCPU; + sysctl(nm, 2, &count, &len, NULL, 0); + + if(count < 1) { + nm[1] = HW_NCPU; + sysctl(nm, 2, &count, &len, NULL, 0); + } +#else + count = sysconf(_SC_NPROCESSORS_ONLN); +#endif + if(count < 1) return 1; + return count; +} + /* not using /proc/loadavg because it only works when our_timer_interval == theirs */ static int get_cpuload(double * load) { @@ -190,6 +220,8 @@ static int get_cpuload(double * load) long long n_user, n_nice, n_sys, n_idle, n_iow, n_irq, n_sirq, n_stl; static int first_time = 1; FILE * f = fopen("/proc/stat", "r"); + double vload; + int ncpu; if (! f) { LM_ERR("could not open /proc/stat\n"); @@ -216,7 +248,16 @@ static int get_cpuload(double * load) (n_stl - o_stl); long long d_idle = (n_idle - o_idle); - *load = 1.0 - ((double)d_idle) / (double)d_total; + vload = ((double)d_idle) / (double)d_total; + + /* divide by numbers of cpu */ + ncpu = get_num_cpus(); + vload = vload/ncpu; + vload = 1.0 - vload; + if(vload<0.0) vload = 0.0; + else if (vload>1.0) vload = 1.0; + + *load = vload; } o_user = n_user;