1fd0c672fSmrg/* 2fd0c672fSmrg 3fd0c672fSmrgCopyright (c) 1989 X Consortium 4fd0c672fSmrg 5fd0c672fSmrgPermission is hereby granted, free of charge, to any person obtaining 6fd0c672fSmrga copy of this software and associated documentation files (the 7fd0c672fSmrg"Software"), to deal in the Software without restriction, including 8fd0c672fSmrgwithout limitation the rights to use, copy, modify, merge, publish, 9fd0c672fSmrgdistribute, sublicense, and/or sell copies of the Software, and to 10fd0c672fSmrgpermit persons to whom the Software is furnished to do so, subject to 11fd0c672fSmrgthe following conditions: 12fd0c672fSmrg 13fd0c672fSmrgThe above copyright notice and this permission notice shall be included 14fd0c672fSmrgin all copies or substantial portions of the Software. 15fd0c672fSmrg 16fd0c672fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17fd0c672fSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18fd0c672fSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19fd0c672fSmrgIN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 20fd0c672fSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21fd0c672fSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22fd0c672fSmrgOTHER DEALINGS IN THE SOFTWARE. 23fd0c672fSmrg 24fd0c672fSmrgExcept as contained in this notice, the name of the X Consortium shall 25fd0c672fSmrgnot be used in advertising or otherwise to promote the sale, use or 26fd0c672fSmrgother dealings in this Software without prior written authorization 27fd0c672fSmrgfrom the X Consortium. 28fd0c672fSmrg 29fd0c672fSmrg*/ 30fd0c672fSmrg 31fd0c672fSmrg/* 32fd0c672fSmrg * get_load - get system load 33fd0c672fSmrg * 34fd0c672fSmrg * Authors: Many and varied... 35fd0c672fSmrg * 36fd0c672fSmrg * Call InitLoadPoint() to initialize. 37fd0c672fSmrg * GetLoadPoint() is a callback for the StripChart widget. 38fd0c672fSmrg */ 39fd0c672fSmrg 40fd0c672fSmrg#ifdef HAVE_CONFIG_H 41fd0c672fSmrg# include "config.h" 42fd0c672fSmrg#endif 43fd0c672fSmrg 44fd0c672fSmrg#include <X11/Xos.h> 45fd0c672fSmrg#include <X11/Intrinsic.h> 46fd0c672fSmrg#include <X11/Xlocale.h> 47fd0c672fSmrg#include <stdio.h> 48fd0c672fSmrg#include <stdlib.h> 49fd0c672fSmrg#include "xload.h" 50fd0c672fSmrg 518846b520Smrg#if defined(__CYGWIN__) || defined(_WIN32) 52953c684bSmrg# define WIN32_LEAN_AND_MEAN 538846b520Smrg# include <X11/Xwindows.h> 54fd0c672fSmrgtypedef struct { 55fd0c672fSmrg DWORD stat; 56fd0c672fSmrg union { 57fd0c672fSmrg LONG vLong; 58fd0c672fSmrg double vDouble; 59fd0c672fSmrg LONGLONG vLongLong; 60fd0c672fSmrg void *string; 61fd0c672fSmrg } u; 62fd0c672fSmrg} COUNTER; 63fd0c672fSmrgstatic HANDLE query; 64fd0c672fSmrgstatic HANDLE counter; 65fd0c672fSmrgstatic HINSTANCE hdll; 66fd0c672fSmrgstatic long (__stdcall *pdhopen)(LPCSTR, DWORD, HANDLE); 67fd0c672fSmrgstatic long (__stdcall *pdhaddcounter)(HANDLE, LPCSTR, DWORD, HANDLE*); 68fd0c672fSmrgstatic long (__stdcall *pdhcollectquerydata)(HANDLE); 69fd0c672fSmrgstatic long (__stdcall *pdhgetformattedcountervalue)(HANDLE, DWORD, LPDWORD, COUNTER*); 70953c684bSmrg# define CYGWIN_PERF 71a8bb11d0Smrgvoid InitLoadPoint(void) 72fd0c672fSmrg{ 73fd0c672fSmrg long ret; 74fd0c672fSmrg hdll=LoadLibrary("pdh.dll"); 75fd0c672fSmrg if (!hdll) exit(-1); 76fd0c672fSmrg pdhopen=(void*)GetProcAddress(hdll, "PdhOpenQueryA"); 77fd0c672fSmrg if (!pdhopen) exit(-1); 78fd0c672fSmrg pdhaddcounter=(void*)GetProcAddress(hdll, "PdhAddCounterA"); 79fd0c672fSmrg if (!pdhaddcounter) exit(-1); 80fd0c672fSmrg pdhcollectquerydata=(void*)GetProcAddress(hdll, "PdhCollectQueryData"); 81fd0c672fSmrg if (!pdhcollectquerydata) exit(-1); 82fd0c672fSmrg pdhgetformattedcountervalue=(void*)GetProcAddress(hdll, "PdhGetFormattedCounterValue"); 83fd0c672fSmrg if (!pdhgetformattedcountervalue) exit(-1); 84fd0c672fSmrg ret = pdhopen( NULL , 0, &query ); 85fd0c672fSmrg if (ret!=0) exit(-1); 86fd0c672fSmrg ret = pdhaddcounter(query, "\\Processor(_Total)\\% Processor Time", 0, &counter); 87953c684bSmrg if (ret!=0) exit(-1); 88fd0c672fSmrg} 89a8bb11d0Smrgvoid GetLoadPoint( 90a8bb11d0Smrg Widget w, /* unused */ 91a8bb11d0Smrg XtPointer closure, /* unused */ 92a8bb11d0Smrg XtPointer call_data) /* pointer to (double) return value */ 93fd0c672fSmrg{ 94fd0c672fSmrg double *loadavg = (double *)call_data; 95fd0c672fSmrg COUNTER fmtvalue; 96fd0c672fSmrg long ret; 97fd0c672fSmrg *loadavg = 0.0; 98fd0c672fSmrg ret = pdhcollectquerydata(query); 99fd0c672fSmrg if (ret!=0) return; 100fd0c672fSmrg ret = pdhgetformattedcountervalue(counter, 0x200, NULL, &fmtvalue); 101fd0c672fSmrg if (ret!=0) return; 102fd0c672fSmrg *loadavg = (fmtvalue.u.vDouble-0.01)/100.0; 103fd0c672fSmrg} 104953c684bSmrg#else /* not CYGWIN */ 105fd0c672fSmrg 106953c684bSmrgstatic void xload_error(const char *, const char *) _X_NORETURN; 107fd0c672fSmrg 108953c684bSmrg# ifdef HAVE_GETLOADAVG 109953c684bSmrg# include <stdlib.h> 110953c684bSmrg# ifdef HAVE_SYS_LOADAVG_H 111953c684bSmrg# include <sys/loadavg.h> /* Solaris definition of getloadavg */ 112953c684bSmrg# endif 113fd0c672fSmrg 114953c684bSmrgvoid InitLoadPoint(void) 115953c684bSmrg{ 116953c684bSmrg} 117fd0c672fSmrg 118953c684bSmrgvoid GetLoadPoint( 119953c684bSmrg Widget w, /* unused */ 120953c684bSmrg XtPointer closure, /* unused */ 121953c684bSmrg XtPointer call_data) /* ptr to (double) return value */ 122953c684bSmrg{ 123953c684bSmrg double *loadavg = (double *)call_data; 124fd0c672fSmrg 125953c684bSmrg if (getloadavg(loadavg, 1) < 0) 126953c684bSmrg xload_error("couldn't obtain load average", ""); 127953c684bSmrg} 128fd0c672fSmrg 129953c684bSmrg# else /* not HAVE_GETLOADAVG */ 130fd0c672fSmrg 131fd0c672fSmrg 13283f4f7f0Smrg# if !defined(linux) && !defined(__GLIBC__) 13383f4f7f0Smrg# include <nlist.h> 13483f4f7f0Smrg# endif /* !linux && ... */ 135fd0c672fSmrg 136953c684bSmrg# ifdef CSRG_BASED 137953c684bSmrg# include <sys/param.h> 138953c684bSmrg# endif 139fd0c672fSmrg 14083f4f7f0Smrg# if defined(linux) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) 141fd0c672fSmrg 14248e69166Smrgvoid InitLoadPoint(void) 143fd0c672fSmrg{ 144fd0c672fSmrg return; 145fd0c672fSmrg} 146fd0c672fSmrg 14748e69166Smrgvoid GetLoadPoint( 14848e69166Smrg Widget w, /* unused */ 14948e69166Smrg XtPointer closure, /* unused */ 15048e69166Smrg XtPointer call_data) /* pointer to (double) return value */ 151fd0c672fSmrg{ 152fd0c672fSmrg static int fd = -1; 153fd0c672fSmrg int n; 154fd0c672fSmrg char buf[10] = {0, }; 15583f4f7f0Smrg# ifndef X_LOCALE 156fd0c672fSmrg char *dp; 157fd0c672fSmrg static char ldp = 0; 15883f4f7f0Smrg# endif 159fd0c672fSmrg 160fd0c672fSmrg 161fd0c672fSmrg if (fd < 0) 162fd0c672fSmrg { 163fd0c672fSmrg if (fd == -2 || 164fd0c672fSmrg (fd = open("/proc/loadavg", O_RDONLY)) < 0) 165fd0c672fSmrg { 166fd0c672fSmrg fd = -2; 167fd0c672fSmrg *(double *)call_data = 0.0; 168fd0c672fSmrg return; 169fd0c672fSmrg } 17083f4f7f0Smrg# ifndef X_LOCALE 171fd0c672fSmrg ldp = *localeconv()->decimal_point; 17283f4f7f0Smrg# endif 173fd0c672fSmrg } 174fd0c672fSmrg else 175fd0c672fSmrg lseek(fd, 0, 0); 176fd0c672fSmrg 177fd0c672fSmrg if ((n = read(fd, buf, sizeof(buf)-1)) > 0) { 17883f4f7f0Smrg# ifndef X_LOCALE 179fd0c672fSmrg if (ldp != '.') 180fd0c672fSmrg while ((dp = memchr(buf,'.',sizeof(buf)-1)) != NULL) { 181fd0c672fSmrg *(char *)dp = ldp; 182fd0c672fSmrg } 183953c684bSmrg 18483f4f7f0Smrg# endif 185fd0c672fSmrg if (sscanf(buf, "%lf", (double *)call_data) == 1) 186fd0c672fSmrg return; 187fd0c672fSmrg } 188953c684bSmrg 189fd0c672fSmrg 190fd0c672fSmrg *(double *)call_data = 0.0; /* temporary hiccup */ 191fd0c672fSmrg 192fd0c672fSmrg return; 193fd0c672fSmrg} 194fd0c672fSmrg 19583f4f7f0Smrg# else /* linux */ 196fd0c672fSmrg 19783f4f7f0Smrg# ifdef __GNU__ 198fd0c672fSmrg 19983f4f7f0Smrg# include <mach.h> 200fd0c672fSmrg 201fd0c672fSmrgstatic processor_set_t default_set; 202fd0c672fSmrg 20348e69166Smrgvoid InitLoadPoint(void) 204fd0c672fSmrg{ 205fd0c672fSmrg if (processor_set_default (mach_host_self (), &default_set) != KERN_SUCCESS) 206fd0c672fSmrg xload_error("cannot get processor_set_default", ""); 207fd0c672fSmrg} 208fd0c672fSmrg 209fd0c672fSmrg/* ARGSUSED */ 21048e69166Smrgvoid GetLoadPoint( 21148e69166Smrg Widget w, /* unused */ 21248e69166Smrg XtPointer closure, /* unused */ 21348e69166Smrg XtPointer call_data) /* pointer to (double) return value */ 214fd0c672fSmrg{ 215fd0c672fSmrg host_t host; 216fd0c672fSmrg struct processor_set_basic_info info; 217fd0c672fSmrg unsigned info_count; 218fd0c672fSmrg 219fd0c672fSmrg info_count = PROCESSOR_SET_BASIC_INFO_COUNT; 220fd0c672fSmrg if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host, 221fd0c672fSmrg (processor_set_info_t) &info, &info_count) 222fd0c672fSmrg != KERN_SUCCESS) 223fd0c672fSmrg { 224fd0c672fSmrg InitLoadPoint(); 225fd0c672fSmrg info.load_average = 0; 226fd0c672fSmrg } 227fd0c672fSmrg 228fd0c672fSmrg *(double *)call_data = info.load_average * 1000 / LOAD_SCALE; 229fd0c672fSmrg 230fd0c672fSmrg return; 231fd0c672fSmrg} 232fd0c672fSmrg 23383f4f7f0Smrg# else /* __GNU__ */ 234fd0c672fSmrg 23583f4f7f0Smrg# ifdef __APPLE__ 236fd0c672fSmrg 23783f4f7f0Smrg# include <mach/mach.h> 238fd0c672fSmrg 239fd0c672fSmrgstatic mach_port_t host_priv_port; 240fd0c672fSmrg 24148e69166Smrgvoid InitLoadPoint(void) 242fd0c672fSmrg{ 243fd0c672fSmrg host_priv_port = mach_host_self(); 244fd0c672fSmrg} 245fd0c672fSmrg 246fd0c672fSmrg/* ARGSUSED */ 24748e69166Smrgvoid GetLoadPoint( 24848e69166Smrg Widget w, /* unused */ 24948e69166Smrg XtPointer closure, /* unused */ 25048e69166Smrg XtPointer call_data) /* pointer to (double) return value */ 251fd0c672fSmrg{ 252fd0c672fSmrg double *loadavg = (double *)call_data; 253fd0c672fSmrg 254fd0c672fSmrg struct host_load_info load_data; 255fd0c672fSmrg int host_count; 256fd0c672fSmrg kern_return_t kr; 257fd0c672fSmrg 258fd0c672fSmrg host_count = sizeof(load_data)/sizeof(integer_t); 259fd0c672fSmrg kr = host_statistics(host_priv_port, HOST_LOAD_INFO, 260fd0c672fSmrg (host_info_t)&load_data, &host_count); 261fd0c672fSmrg if (kr != KERN_SUCCESS) 262fd0c672fSmrg xload_error("cannot get host statistics", ""); 263fd0c672fSmrg *loadavg = (double)load_data.avenrun[0]/LOAD_SCALE; 264fd0c672fSmrg return; 265fd0c672fSmrg} 266fd0c672fSmrg 26783f4f7f0Smrg# else /* __APPLE__ */ 268fd0c672fSmrg 269fd0c672fSmrg 270fd0c672fSmrg 27183f4f7f0Smrg# ifdef __QNXNTO__ 27283f4f7f0Smrg# include <time.h> 27383f4f7f0Smrg# include <sys/neutrino.h> 274fd0c672fSmrgstatic _Uint64t nto_idle = 0, nto_idle_last = 0; 275fd0c672fSmrgstatic int nto_idle_id; 276fd0c672fSmrgstatic struct timespec nto_now, nto_last; 277fd0c672fSmrg 278fd0c672fSmrgvoid 27948e69166SmrgInitLoadPoint(void) 280fd0c672fSmrg{ 281fd0c672fSmrg nto_idle_id = ClockId(1, 1); /* Idle thread */ 282fd0c672fSmrg ClockTime(nto_idle_id, NULL, &nto_idle_last); 283fd0c672fSmrg clock_gettime( CLOCK_REALTIME, &nto_last); 284fd0c672fSmrg} 285fd0c672fSmrg 286fd0c672fSmrg/* ARGSUSED */ 287fd0c672fSmrgvoid 28848e69166SmrgGetLoadPoint( /* QNX NTO version */ 28948e69166Smrg Widget w, /* unused */ 29048e69166Smrg XtPointer closure, /* unused */ 29148e69166Smrg XtPointer call_data) /* pointer to (double) return value */ 292fd0c672fSmrg{ 293fd0c672fSmrg double *loadavg = (double *)call_data; 294fd0c672fSmrg double timediff; 295fd0c672fSmrg double temp = 0.0; 296fd0c672fSmrg 297fd0c672fSmrg ClockTime(nto_idle_id, NULL, &nto_idle); 298fd0c672fSmrg clock_gettime( CLOCK_REALTIME, &nto_now); 299fd0c672fSmrg timediff = 1000000000.0 * (nto_now.tv_sec - nto_last.tv_sec) 300fd0c672fSmrg + (nto_now.tv_nsec - nto_last.tv_nsec); 301fd0c672fSmrg temp = 1.0 - (nto_idle-nto_idle_last)/timediff; 302fd0c672fSmrg *loadavg = temp >= 0 ? temp : 0; 303fd0c672fSmrg nto_idle_last = nto_idle; 304fd0c672fSmrg nto_last = nto_now; 305fd0c672fSmrg} 30683f4f7f0Smrg# else /* not __QNXNTO__ */ 307fd0c672fSmrg 30883f4f7f0Smrg# ifndef KMEM_FILE 30983f4f7f0Smrg# define KMEM_FILE "/dev/kmem" 31083f4f7f0Smrg# endif 311fd0c672fSmrg 31283f4f7f0Smrg# ifndef KERNEL_FILE 313fd0c672fSmrg/* 314fd0c672fSmrg * provide default for everyone else 315fd0c672fSmrg */ 31683f4f7f0Smrg/* If <paths.h> exists, check in it */ 31783f4f7f0Smrg# ifdef HAVE_PATHS_H 31883f4f7f0Smrg# include <paths.h> 31983f4f7f0Smrg# ifdef _PATH_UNIX 32083f4f7f0Smrg# define KERNEL_FILE _PATH_UNIX 32183f4f7f0Smrg# else 32283f4f7f0Smrg# ifdef _PATH_KERNEL 32383f4f7f0Smrg# define KERNEL_FILE _PATH_KERNEL 32483f4f7f0Smrg# else 32583f4f7f0Smrg# define KERNEL_FILE "/vmunix" 32683f4f7f0Smrg# endif 32783f4f7f0Smrg# endif 32883f4f7f0Smrg# else /* HAVE_PATHS_H */ 32983f4f7f0Smrg# define KERNEL_FILE "/vmunix" 33083f4f7f0Smrg# endif /* HAVE_PATHS_H */ 33183f4f7f0Smrg# endif /* KERNEL_FILE */ 33283f4f7f0Smrg 33383f4f7f0Smrg 33483f4f7f0Smrg# ifndef KERNEL_LOAD_VARIABLE 33583f4f7f0Smrg# if defined(BSD) && (BSD >= 199103) 33683f4f7f0Smrg# define KERNEL_LOAD_VARIABLE "_averunnable" 33783f4f7f0Smrg# else /* BSD >= 199103 */ 33883f4f7f0Smrg# define KERNEL_LOAD_VARIABLE "_avenrun" 33983f4f7f0Smrg# endif /* BSD >= 199103 */ 34083f4f7f0Smrg# endif /* KERNEL_LOAD_VARIABLE */ 341fd0c672fSmrg 342fd0c672fSmrgstatic struct nlist namelist[] = { /* namelist for vmunix grubbing */ 34383f4f7f0Smrg# define LOADAV 0 344fd0c672fSmrg {KERNEL_LOAD_VARIABLE}, 345fd0c672fSmrg {0} 346fd0c672fSmrg}; 347fd0c672fSmrg 348fd0c672fSmrgstatic int kmem; 349fd0c672fSmrgstatic long loadavg_seek; 350fd0c672fSmrg 351fd0c672fSmrgvoid InitLoadPoint() 352fd0c672fSmrg{ 35383f4f7f0Smrg# if !defined(AIXV5) && !(BSD >= 199103) && !defined(__APPLE__) 354fd0c672fSmrg extern void nlist(); 35583f4f7f0Smrg# endif 356fd0c672fSmrg 357fd0c672fSmrg nlist( KERNEL_FILE, namelist); 358fd0c672fSmrg /* 359fd0c672fSmrg * Some systems appear to set only one of these to Zero if the entry could 360fd0c672fSmrg * not be found, I hope no_one returns Zero as a good value, or bad things 361fd0c672fSmrg * will happen to you. (I have a hard time believing the value will 362fd0c672fSmrg * ever really be zero anyway). CDP 5/17/89. 363fd0c672fSmrg */ 364fd0c672fSmrg if (namelist[LOADAV].n_type == 0 || 365fd0c672fSmrg namelist[LOADAV].n_value == 0) { 366fd0c672fSmrg xload_error("cannot get name list from", KERNEL_FILE); 367fd0c672fSmrg exit(-1); 368fd0c672fSmrg } 369fd0c672fSmrg loadavg_seek = namelist[LOADAV].n_value; 370fd0c672fSmrg kmem = open(KMEM_FILE, O_RDONLY); 371fd0c672fSmrg if (kmem < 0) xload_error("cannot open", KMEM_FILE); 372fd0c672fSmrg} 373fd0c672fSmrg 374fd0c672fSmrg/* ARGSUSED */ 375fd0c672fSmrgvoid GetLoadPoint( w, closure, call_data ) 376fd0c672fSmrg Widget w; /* unused */ 377fd0c672fSmrg XtPointer closure; /* unused */ 378fd0c672fSmrg XtPointer call_data; /* pointer to (double) return value */ 379fd0c672fSmrg{ 380fd0c672fSmrg double *loadavg = (double *)call_data; 381fd0c672fSmrg 382fd0c672fSmrg (void) lseek(kmem, loadavg_seek, 0); 383fd0c672fSmrg 38483f4f7f0Smrg# if (BSD >= 199103) 385fd0c672fSmrg { 386fd0c672fSmrg long temp; 387fd0c672fSmrg (void) read(kmem, (char *)&temp, sizeof(long)); 388fd0c672fSmrg *loadavg = (double)temp/FSCALE; 389fd0c672fSmrg } 39083f4f7f0Smrg# else /* else not BSD */ 391fd0c672fSmrg (void) read(kmem, (char *)loadavg, sizeof(double)); 39283f4f7f0Smrg# endif /* or ... else */ 393fd0c672fSmrg return; 394fd0c672fSmrg} 39583f4f7f0Smrg# endif /* __QNXNTO__ else */ 39683f4f7f0Smrg# endif /* __APPLE__ else */ 39783f4f7f0Smrg# endif /* __GNU__ else */ 39883f4f7f0Smrg# endif /* linux else */ 399953c684bSmrg# endif /* HAVE_GETLOADAVG else */ 400fd0c672fSmrg 401a8bb11d0Smrgstatic void xload_error(const char *str1, const char *str2) 402fd0c672fSmrg{ 403fd0c672fSmrg (void) fprintf(stderr,"xload: %s %s\n", str1, str2); 404fd0c672fSmrg exit(-1); 405fd0c672fSmrg} 406fd0c672fSmrg 407fd0c672fSmrg#endif /* END of __CYGWIN__ */ 408