get_load.c revision a8bb11d0
1/* 2 3Copyright (c) 1989 X Consortium 4 5Permission is hereby granted, free of charge, to any person obtaining 6a copy of this software and associated documentation files (the 7"Software"), to deal in the Software without restriction, including 8without limitation the rights to use, copy, modify, merge, publish, 9distribute, sublicense, and/or sell copies of the Software, and to 10permit persons to whom the Software is furnished to do so, subject to 11the following conditions: 12 13The above copyright notice and this permission notice shall be included 14in all copies or substantial portions of the Software. 15 16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 20OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22OTHER DEALINGS IN THE SOFTWARE. 23 24Except as contained in this notice, the name of the X Consortium shall 25not be used in advertising or otherwise to promote the sale, use or 26other dealings in this Software without prior written authorization 27from the X Consortium. 28 29*/ 30 31/* 32 * get_load - get system load 33 * 34 * Authors: Many and varied... 35 * 36 * Call InitLoadPoint() to initialize. 37 * GetLoadPoint() is a callback for the StripChart widget. 38 */ 39 40#ifdef HAVE_CONFIG_H 41# include "config.h" 42#endif 43 44#include <X11/Xos.h> 45#include <X11/Intrinsic.h> 46#include <X11/Xlocale.h> 47#include <stdio.h> 48#include <stdlib.h> 49#include "xload.h" 50 51#if defined(__CYGWIN__) 52#define WIN32_LEAN_AND_MEAN 53#include <windows.h> 54typedef struct { 55 DWORD stat; 56 union { 57 LONG vLong; 58 double vDouble; 59 LONGLONG vLongLong; 60 void *string; 61 } u; 62} COUNTER; 63static HANDLE query; 64static HANDLE counter; 65static HINSTANCE hdll; 66static long (__stdcall *pdhopen)(LPCSTR, DWORD, HANDLE); 67static long (__stdcall *pdhaddcounter)(HANDLE, LPCSTR, DWORD, HANDLE*); 68static long (__stdcall *pdhcollectquerydata)(HANDLE); 69static long (__stdcall *pdhgetformattedcountervalue)(HANDLE, DWORD, LPDWORD, COUNTER*); 70#define CYGWIN_PERF 71void InitLoadPoint(void) 72{ 73 long ret; 74 hdll=LoadLibrary("pdh.dll"); 75 if (!hdll) exit(-1); 76 pdhopen=(void*)GetProcAddress(hdll, "PdhOpenQueryA"); 77 if (!pdhopen) exit(-1); 78 pdhaddcounter=(void*)GetProcAddress(hdll, "PdhAddCounterA"); 79 if (!pdhaddcounter) exit(-1); 80 pdhcollectquerydata=(void*)GetProcAddress(hdll, "PdhCollectQueryData"); 81 if (!pdhcollectquerydata) exit(-1); 82 pdhgetformattedcountervalue=(void*)GetProcAddress(hdll, "PdhGetFormattedCounterValue"); 83 if (!pdhgetformattedcountervalue) exit(-1); 84 ret = pdhopen( NULL , 0, &query ); 85 if (ret!=0) exit(-1); 86 ret = pdhaddcounter(query, "\\Processor(_Total)\\% Processor Time", 0, &counter); 87 if (ret!=0) exit(-1); 88} 89void GetLoadPoint( 90 Widget w, /* unused */ 91 XtPointer closure, /* unused */ 92 XtPointer call_data) /* pointer to (double) return value */ 93{ 94 double *loadavg = (double *)call_data; 95 COUNTER fmtvalue; 96 long ret; 97 *loadavg = 0.0; 98 ret = pdhcollectquerydata(query); 99 if (ret!=0) return; 100 ret = pdhgetformattedcountervalue(counter, 0x200, NULL, &fmtvalue); 101 if (ret!=0) return; 102 *loadavg = (fmtvalue.u.vDouble-0.01)/100.0; 103} 104#else 105 106 107#if defined(att) || defined(QNX4) 108#define LOADSTUB 109#endif 110 111#ifndef LOADSTUB 112#if !defined(linux) && !defined(__UNIXOS2__) && !defined(__GLIBC__) 113#include <nlist.h> 114#endif /* !linux && ... */ 115#endif /* LOADSTUB */ 116 117#if defined(MOTOROLA) && defined(SYSV) 118#include <sys/sysinfo.h> 119#endif 120 121#ifdef CSRG_BASED 122#include <sys/param.h> 123#endif 124 125#if defined(umips) || (defined(ultrix) && defined(mips)) 126#include <sys/fixpoint.h> 127#endif 128 129#if defined(CRAY) || defined(AIXV3) 130#include <sys/param.h> 131#define word word_t 132#include <sys/sysinfo.h> 133#undef word 134#undef n_type 135#define n_type n_value 136#endif /* CRAY */ 137 138#ifdef sequent 139#include <sys/vm.h> 140#endif /* sequent */ 141 142 143#ifdef hcx 144#include <sys/param.h> 145#endif /* hcx */ 146 147#if defined(UTEK) || defined(alliant) || (defined(MOTOROLA) && defined(SVR4)) 148#define FSCALE 100.0 149#endif 150 151#ifdef sequent 152#define FSCALE 1000.0 153#endif 154 155#ifdef sgi 156#define FSCALE 1024.0 157#endif 158 159#if defined(sony) && OSMAJORVERSION == 4 160#ifdef mips 161#include <sys/fixpoint.h> 162#else 163#include <sys/param.h> 164#endif 165#endif 166 167#ifdef __osf__ 168/* 169 * Use the table(2) interface; it doesn't require setuid root. 170 * 171 * Select 0, 1, or 2 for 5, 30, or 60 second load averages. 172 */ 173#ifndef WHICH_AVG 174#define WHICH_AVG 1 175#endif 176#include <sys/table.h> 177#endif 178 179#ifdef SVR4 180#ifndef FSCALE 181#define FSCALE (1 << 8) 182#endif 183#endif 184 185#ifdef X_NOT_POSIX 186extern long lseek(); 187#endif 188 189static void xload_error(const char *, const char *) _X_NORETURN; 190 191 192#if defined(SYSV) && defined(i386) 193/* 194 * inspired by 'avgload' by John F. Haugh II 195 */ 196#include <sys/param.h> 197#include <sys/buf.h> 198#include <sys/immu.h> 199#include <sys/region.h> 200#include <sys/var.h> 201#include <sys/proc.h> 202#define KERNEL_FILE "/unix" 203#define KMEM_FILE "/dev/kmem" 204#define VAR_NAME "v" 205#define PROC_NAME "proc" 206#define BUF_NAME "buf" 207#define DECAY 0.8 208struct nlist namelist[] = { 209 {VAR_NAME}, 210 {PROC_NAME}, 211 {BUF_NAME}, 212 {0}, 213}; 214 215static int kmem; 216static struct var v; 217static struct proc *p; 218static XtPointer first_buf, last_buf; 219 220void InitLoadPoint() /* SYSV386 version */ 221{ 222 int i; 223 224 nlist( KERNEL_FILE, namelist); 225 226 for (i=0; namelist[i].n_name; i++) 227 if (namelist[i].n_value == 0) 228 xload_error("cannot get name list from", KERNEL_FILE); 229 230 if ((kmem = open(KMEM_FILE, O_RDONLY)) < 0) 231 xload_error("cannot open", KMEM_FILE); 232 233 if (lseek(kmem, namelist[0].n_value, 0) == -1) 234 xload_error("cannot seek", VAR_NAME); 235 236 if (read(kmem, &v, sizeof(v)) != sizeof(v)) 237 xload_error("cannot read", VAR_NAME); 238 239 if ((p=(struct proc *)malloc(v.v_proc*sizeof(*p))) == NULL) 240 xload_error("cannot allocat space for", PROC_NAME); 241 242 first_buf = (XtPointer) namelist[2].n_value; 243 last_buf = (char *)first_buf + v.v_buf * sizeof(struct buf); 244} 245 246/* ARGSUSED */ 247void GetLoadPoint( w, closure, call_data ) /* SYSV386 version */ 248Widget w; /* unused */ 249XtPointer closure; /* unused */ 250XtPointer call_data; /* pointer to (double) return value */ 251{ 252 double *loadavg = (double *)call_data; 253 static double avenrun = 0.0; 254 int i, nproc, size; 255 256 (void) lseek(kmem, namelist[0].n_value, 0); 257 (void) read(kmem, &v, sizeof(v)); 258 259 size = (struct proc *)v.ve_proc - (struct proc *)namelist[1].n_value; 260 261 (void) lseek(kmem, namelist[1].n_value, 0); 262 (void) read(kmem, p, size * sizeof(struct proc)); 263 264 for (nproc = 0, i=0; i<size; i++) 265 if ((p[i].p_stat == SRUN) || 266 (p[i].p_stat == SIDL) || 267 (p[i].p_stat == SXBRK) || 268 (p[i].p_stat == SSLEEP && (p[i].p_pri < PZERO) && 269 (p[i].p_wchan >= (char *)first_buf) && (p[i].p_wchan < (char *)last_buf))) 270 nproc++; 271 272 /* update the load average using a decay filter */ 273 avenrun = DECAY * avenrun + nproc * (1.0 - DECAY); 274 *loadavg = avenrun; 275 276 return; 277} 278#else /* not (SYSV && i386) */ 279 280#if defined(linux) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) 281 282void InitLoadPoint(void) 283{ 284 return; 285} 286 287void GetLoadPoint( 288 Widget w, /* unused */ 289 XtPointer closure, /* unused */ 290 XtPointer call_data) /* pointer to (double) return value */ 291{ 292 static int fd = -1; 293 int n; 294 char buf[10] = {0, }; 295#ifndef X_LOCALE 296 char *dp; 297 static char ldp = 0; 298#endif 299 300 301 if (fd < 0) 302 { 303 if (fd == -2 || 304 (fd = open("/proc/loadavg", O_RDONLY)) < 0) 305 { 306 fd = -2; 307 *(double *)call_data = 0.0; 308 return; 309 } 310#ifndef X_LOCALE 311 ldp = *localeconv()->decimal_point; 312#endif 313 } 314 else 315 lseek(fd, 0, 0); 316 317 if ((n = read(fd, buf, sizeof(buf)-1)) > 0) { 318#ifndef X_LOCALE 319 if (ldp != '.') 320 while ((dp = memchr(buf,'.',sizeof(buf)-1)) != NULL) { 321 *(char *)dp = ldp; 322 } 323 324#endif 325 if (sscanf(buf, "%lf", (double *)call_data) == 1) 326 return; 327 } 328 329 330 *(double *)call_data = 0.0; /* temporary hiccup */ 331 332 return; 333} 334 335#else /* linux */ 336 337#ifdef __GNU__ 338 339#include <mach.h> 340 341static processor_set_t default_set; 342 343void InitLoadPoint(void) 344{ 345 if (processor_set_default (mach_host_self (), &default_set) != KERN_SUCCESS) 346 xload_error("cannot get processor_set_default", ""); 347} 348 349/* ARGSUSED */ 350void GetLoadPoint( 351 Widget w, /* unused */ 352 XtPointer closure, /* unused */ 353 XtPointer call_data) /* pointer to (double) return value */ 354{ 355 host_t host; 356 struct processor_set_basic_info info; 357 unsigned info_count; 358 359 info_count = PROCESSOR_SET_BASIC_INFO_COUNT; 360 if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host, 361 (processor_set_info_t) &info, &info_count) 362 != KERN_SUCCESS) 363 { 364 InitLoadPoint(); 365 info.load_average = 0; 366 } 367 368 *(double *)call_data = info.load_average * 1000 / LOAD_SCALE; 369 370 return; 371} 372 373#else /* __GNU__ */ 374 375#ifdef __APPLE__ 376 377#include <mach/mach.h> 378 379static mach_port_t host_priv_port; 380 381void InitLoadPoint(void) 382{ 383 host_priv_port = mach_host_self(); 384} 385 386/* ARGSUSED */ 387void GetLoadPoint( 388 Widget w, /* unused */ 389 XtPointer closure, /* unused */ 390 XtPointer call_data) /* pointer to (double) return value */ 391{ 392 double *loadavg = (double *)call_data; 393 394 struct host_load_info load_data; 395 int host_count; 396 kern_return_t kr; 397 398 host_count = sizeof(load_data)/sizeof(integer_t); 399 kr = host_statistics(host_priv_port, HOST_LOAD_INFO, 400 (host_info_t)&load_data, &host_count); 401 if (kr != KERN_SUCCESS) 402 xload_error("cannot get host statistics", ""); 403 *loadavg = (double)load_data.avenrun[0]/LOAD_SCALE; 404 return; 405} 406 407#else /* __APPLE__ */ 408 409#ifdef LOADSTUB 410 411void InitLoadPoint() 412{ 413} 414 415/* ARGSUSED */ 416void GetLoadPoint( w, closure, call_data ) 417 Widget w; /* unused */ 418 XtPointer closure; /* unused */ 419 XtPointer call_data; /* pointer to (double) return value */ 420{ 421 *(double *)call_data = 1.0; 422} 423 424#else /* not LOADSTUB */ 425 426#ifdef __osf__ 427 428void InitLoadPoint() 429{ 430} 431 432/*ARGSUSED*/ 433void GetLoadPoint( w, closure, call_data ) 434 Widget w; /* unused */ 435 XtPointer closure; /* unused */ 436 XtPointer call_data; /* pointer to (double) return value */ 437{ 438 double *loadavg = (double *)call_data; 439 struct tbl_loadavg load_data; 440 441 if (table(TBL_LOADAVG, 0, (char *)&load_data, 1, sizeof(load_data)) < 0) 442 xload_error("error reading load average", ""); 443 *loadavg = (load_data.tl_lscale == 0) ? 444 load_data.tl_avenrun.d[WHICH_AVG] : 445 load_data.tl_avenrun.l[WHICH_AVG] / (double)load_data.tl_lscale; 446} 447 448#else /* not __osf__ */ 449 450#ifdef __QNXNTO__ 451#include <time.h> 452#include <sys/neutrino.h> 453static _Uint64t nto_idle = 0, nto_idle_last = 0; 454static int nto_idle_id; 455static struct timespec nto_now, nto_last; 456 457void 458InitLoadPoint(void) 459{ 460 nto_idle_id = ClockId(1, 1); /* Idle thread */ 461 ClockTime(nto_idle_id, NULL, &nto_idle_last); 462 clock_gettime( CLOCK_REALTIME, &nto_last); 463} 464 465/* ARGSUSED */ 466void 467GetLoadPoint( /* QNX NTO version */ 468 Widget w, /* unused */ 469 XtPointer closure, /* unused */ 470 XtPointer call_data) /* pointer to (double) return value */ 471{ 472 double *loadavg = (double *)call_data; 473 double timediff; 474 double temp = 0.0; 475 476 ClockTime(nto_idle_id, NULL, &nto_idle); 477 clock_gettime( CLOCK_REALTIME, &nto_now); 478 timediff = 1000000000.0 * (nto_now.tv_sec - nto_last.tv_sec) 479 + (nto_now.tv_nsec - nto_last.tv_nsec); 480 temp = 1.0 - (nto_idle-nto_idle_last)/timediff; 481 *loadavg = temp >= 0 ? temp : 0; 482 nto_idle_last = nto_idle; 483 nto_last = nto_now; 484} 485#else /* not __QNXNTO__ */ 486 487#ifdef __bsdi__ 488#include <kvm.h> 489 490static struct nlist nl[] = { 491 { "_averunnable" }, 492#define X_AVERUNNABLE 0 493 { "_fscale" }, 494#define X_FSCALE 1 495 { "" }, 496}; 497static kvm_t *kd; 498static int fscale; 499 500void InitLoadPoint(void) 501{ 502 fixpt_t averunnable[3]; /* unused really */ 503 504 if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL) 505 xload_error("can't open kvm files", ""); 506 507 if (kvm_nlist(kd, nl) != 0) 508 xload_error("can't read name list", ""); 509 510 if (kvm_read(kd, (off_t)nl[X_AVERUNNABLE].n_value, (char *)averunnable, 511 sizeof(averunnable)) != sizeof(averunnable)) 512 xload_error("couldn't obtain _averunnable variable", ""); 513 514 if (kvm_read(kd, (off_t)nl[X_FSCALE].n_value, (char *)&fscale, 515 sizeof(fscale)) != sizeof(fscale)) 516 xload_error("couldn't obtain _fscale variable", ""); 517 518 return; 519} 520 521void GetLoadPoint( 522 Widget w, /* unused */ 523 XtPointer closure, /* unused */ 524 XtPointer call_data) /* ptr to (double) return value */ 525{ 526 double *loadavg = (double *)call_data; 527 fixpt_t t; 528 529 if (kvm_read(kd, (off_t)nl[X_AVERUNNABLE].n_value, (char *)&t, 530 sizeof(t)) != sizeof(t)) 531 xload_error("couldn't obtain load average", ""); 532 533 *loadavg = (double)t/fscale; 534 535 return; 536} 537 538#else /* not __bsdi__ */ 539#if defined(HAVE_GETLOADAVG) 540#include <stdlib.h> 541#ifdef HAVE_SYS_LOADAVG_H 542#include <sys/loadavg.h> /* Solaris definition of getloadavg */ 543#endif 544 545void InitLoadPoint() 546{ 547} 548 549void GetLoadPoint(w, closure, call_data) 550 Widget w; /* unused */ 551 XtPointer closure; /* unused */ 552 XtPointer call_data; /* ptr to (double) return value */ 553{ 554 double *loadavg = (double *)call_data; 555 556 if (getloadavg(loadavg, 1) < 0) 557 xload_error("couldn't obtain load average", ""); 558} 559 560#else /* not HAVE_GETLOADAVG */ 561 562#ifndef KMEM_FILE 563#define KMEM_FILE "/dev/kmem" 564#endif 565 566#ifndef KERNEL_FILE 567 568#ifdef alliant 569#define KERNEL_FILE "/vmunix" 570#endif /* alliant */ 571 572#ifdef CRAY 573#define KERNEL_FILE "/unicos" 574#endif /* CRAY */ 575 576#ifdef hpux 577#define KERNEL_FILE "/hp-ux" 578#endif /* hpux */ 579 580 581#ifdef umips 582# ifdef SYSTYPE_SYSV 583# define KERNEL_FILE "/unix" 584# else 585# define KERNEL_FILE "/vmunix" 586# endif /* SYSTYPE_SYSV */ 587#endif /* umips */ 588 589#ifdef sequent 590#define KERNEL_FILE "/dynix" 591#endif /* sequent */ 592 593#ifdef hcx 594#define KERNEL_FILE "/unix" 595#endif /* hcx */ 596 597#ifdef MOTOROLA 598#if defined(SYSV) && defined(m68k) 599#define KERNEL_FILE "/sysV68" 600#endif 601#if defined(SYSV) && defined(m88k) 602#define KERNEL_FILE "/unix" 603#endif 604#ifdef SVR4 605#define KERNEL_FILE "/unix" 606#endif 607#endif /* MOTOROLA */ 608 609#ifdef sgi 610#if (OSMAJORVERSION > 4) 611#define KERNEL_FILE "/unix" 612#endif 613#endif 614 615/* 616 * provide default for everyone else 617 */ 618#ifndef KERNEL_FILE 619#ifdef SVR4 620#define KERNEL_FILE "/stand/unix" 621#else 622#ifdef SYSV 623#define KERNEL_FILE "/unix" 624#else 625/* If a BSD system, check in <paths.h> */ 626# ifdef BSD 627# include <paths.h> 628# ifdef _PATH_UNIX 629# define KERNEL_FILE _PATH_UNIX 630# else 631# ifdef _PATH_KERNEL 632# define KERNEL_FILE _PATH_KERNEL 633# else 634# define KERNEL_FILE "/vmunix" 635# endif 636# endif 637# else /* BSD */ 638# define KERNEL_FILE "/vmunix" 639# endif /* BSD */ 640#endif /* SYSV */ 641#endif /* SVR4 */ 642#endif /* KERNEL_FILE */ 643#endif /* KERNEL_FILE */ 644 645 646#ifndef KERNEL_LOAD_VARIABLE 647# if defined(BSD) && (BSD >= 199103) 648# define KERNEL_LOAD_VARIABLE "_averunnable" 649# endif /* BSD >= 199103 */ 650 651# ifdef alliant 652# define KERNEL_LOAD_VARIABLE "_Loadavg" 653# endif /* alliant */ 654 655# ifdef CRAY 656# if defined(CRAY2) && OSMAJORVERSION == 4 657# define KERNEL_LOAD_VARIABLE "avenrun" 658# else 659# define KERNEL_LOAD_VARIABLE "sysinfo" 660# define SYSINFO 661# endif /* defined(CRAY2) && OSMAJORVERSION == 4 */ 662# endif /* CRAY */ 663 664# ifdef hpux 665# ifdef __hp9000s800 666# define KERNEL_LOAD_VARIABLE "avenrun" 667# endif /* hp9000s800 */ 668# endif /* hpux */ 669 670# ifdef umips 671# ifdef SYSTYPE_SYSV 672# define KERNEL_LOAD_VARIABLE "avenrun" 673# else 674# define KERNEL_LOAD_VARIABLE "_avenrun" 675# endif /* SYSTYPE_SYSV */ 676# endif /* umips */ 677 678# ifdef sgi 679# define KERNEL_LOAD_VARIABLE "avenrun" 680# endif /* sgi */ 681 682# ifdef AIXV3 683# define KERNEL_LOAD_VARIABLE "sysinfo" 684# endif /* AIXV3 */ 685 686# ifdef MOTOROLA 687# if defined(SYSV) && defined(m68k) 688# define KERNEL_LOAD_VARIABLE "sysinfo" 689# endif 690# if defined(SYSV) && defined(m88k) 691# define KERNEL_LOAD_VARIABLE "_sysinfo" 692# endif 693# ifdef SVR4 694# define KERNEL_LOAD_VARIABLE "avenrun" 695# endif 696# endif /* MOTOROLA */ 697 698#endif /* KERNEL_LOAD_VARIABLE */ 699 700/* 701 * provide default for everyone else 702 */ 703 704#ifndef KERNEL_LOAD_VARIABLE 705# ifdef USG 706# define KERNEL_LOAD_VARIABLE "sysinfo" 707# define SYSINFO 708# else 709# ifdef SVR4 710# define KERNEL_LOAD_VARIABLE "avenrun" 711# else 712# define KERNEL_LOAD_VARIABLE "_avenrun" 713# endif 714# endif 715#endif /* KERNEL_LOAD_VARIABLE */ 716 717static struct nlist namelist[] = { /* namelist for vmunix grubbing */ 718#define LOADAV 0 719 {KERNEL_LOAD_VARIABLE}, 720 {0} 721}; 722 723static int kmem; 724static long loadavg_seek; 725 726void InitLoadPoint() 727{ 728#if !defined(SVR4) && !defined(sgi) && !defined(MOTOROLA) && !defined(AIXV5) && !(BSD >= 199103) && !defined(__APPLE__) 729 extern void nlist(); 730#endif 731 732#ifdef AIXV3 733 knlist( namelist, 1, sizeof(struct nlist)); 734#else 735 nlist( KERNEL_FILE, namelist); 736#endif 737 /* 738 * Some systems appear to set only one of these to Zero if the entry could 739 * not be found, I hope no_one returns Zero as a good value, or bad things 740 * will happen to you. (I have a hard time believing the value will 741 * ever really be zero anyway). CDP 5/17/89. 742 */ 743#ifdef hcx 744 if (namelist[LOADAV].n_type == 0 && 745#else 746 if (namelist[LOADAV].n_type == 0 || 747#endif /* hcx */ 748 namelist[LOADAV].n_value == 0) { 749 xload_error("cannot get name list from", KERNEL_FILE); 750 exit(-1); 751 } 752 loadavg_seek = namelist[LOADAV].n_value; 753#if defined(umips) && defined(SYSTYPE_SYSV) 754 loadavg_seek &= 0x7fffffff; 755#endif /* umips && SYSTYPE_SYSV */ 756#if (defined(CRAY) && defined(SYSINFO)) 757 loadavg_seek += ((char *) (((struct sysinfo *)NULL)->avenrun)) - 758 ((char *) NULL); 759#endif /* CRAY && SYSINFO */ 760 kmem = open(KMEM_FILE, O_RDONLY); 761 if (kmem < 0) xload_error("cannot open", KMEM_FILE); 762} 763 764/* ARGSUSED */ 765void GetLoadPoint( w, closure, call_data ) 766 Widget w; /* unused */ 767 XtPointer closure; /* unused */ 768 XtPointer call_data; /* pointer to (double) return value */ 769{ 770 double *loadavg = (double *)call_data; 771 772 (void) lseek(kmem, loadavg_seek, 0); 773 774#if defined (UTEK) || defined(sequent) || defined(alliant) || defined(SVR4) || defined(sgi) || defined(hcx) || (BSD >= 199103) 775 { 776 long temp; 777 (void) read(kmem, (char *)&temp, sizeof(long)); 778 *loadavg = (double)temp/FSCALE; 779 } 780#else /* else not UTEK or sequent or alliant or SVR4 or sgi or hcx */ 781# if defined(umips) || (defined(ultrix) && defined(mips)) 782 { 783 fix temp; 784 (void) read(kmem, (char *)&temp, sizeof(fix)); 785 *loadavg = FIX_TO_DBL(temp); 786 } 787# else /* not umips or ultrix risc */ 788# ifdef AIXV3 789 { 790 struct sysinfo sysinfo_now; 791 struct sysinfo sysinfo_last; 792 static firsttime = TRUE; 793 static double runavg = 0.0, swpavg = 0.0; 794 795 (void) lseek(kmem, loadavg_seek, 0); 796 (void) read(kmem, (char *)&sysinfo_last, sizeof(struct sysinfo)); 797 if (firsttime) 798 { 799 *loadavg = 0.0; 800 firsttime = FALSE; 801 } 802 else 803 { 804 sleep(1); 805 (void) lseek(kmem, loadavg_seek, 0); 806 (void) read(kmem, (char *)&sysinfo_now, sizeof(struct sysinfo)); 807 runavg *= 0.8; swpavg *= 0.8; 808 if (sysinfo_now.runocc != sysinfo_last.runocc) 809 runavg += 0.2*((sysinfo_now.runque - sysinfo_last.runque - 1) 810 /(double)(sysinfo_now.runocc - sysinfo_last.runocc)); 811 if (sysinfo_now.swpocc != sysinfo_last.swpocc) 812 swpavg += 0.2*((sysinfo_now.swpque - sysinfo_last.swpque) 813 /(double)(sysinfo_now.swpocc - sysinfo_last.swpocc)); 814 *loadavg = runavg + swpavg; 815 sysinfo_last = sysinfo_now; 816 } 817 /* otherwise we leave load alone. */ 818 } 819# else /* not AIXV3 */ 820# if defined(MOTOROLA) && defined(SYSV) 821 { 822 static int init = 0; 823 static kmem; 824 static long loadavg_seek; 825 826#define CEXP 0.25 /* Constant used for load averaging */ 827 828 struct sysinfo sysinfod; 829 static double oldloadavg; 830 static double cexp = CEXP; 831 static long sv_rq, sv_oc; /* save old values */ 832 double rq, oc; /* amount values have changed */ 833 834 if (!init) 835 { 836 if (nlist(KERNEL_FILE,namelist) == -1) 837 { 838 perror("xload: nlist()"); 839 xload_error("cannot get name list from", KERNEL_FILE); 840 } 841 loadavg_seek = namelist[0].n_value; 842 843 kmem = open(KMEM_FILE, O_RDONLY); 844 if (kmem < 0) 845 { 846 perror("xload: open()"); 847 xload_error("cannot open", KMEM_FILE); 848 } 849 } 850 851 lseek(kmem, loadavg_seek, 0); 852 if (read(kmem, &sysinfod, (int) sizeof (struct sysinfo)) == -1) 853 { 854 perror("xload: read() SYSINFONL"); 855 xload_error("read failed from", KMEM_FILE); 856 } 857 858 if (!init) 859 { 860 init = 1; 861 sv_rq = sysinfod.runque; 862 sv_oc = sysinfod.runocc; 863 oldloadavg = *loadavg = 0.0; 864 return; 865 } 866 /* 867 * calculate the amount the values have 868 * changed since last update 869 */ 870 rq = (double) sysinfod.runque - sv_rq; 871 oc = (double) sysinfod.runocc - sv_oc; 872 873 /* 874 * save old values for next time 875 */ 876 sv_rq = sysinfod.runque; 877 sv_oc = sysinfod.runocc; 878 879 if (oc == 0.0) /* avoid divide by zero */ 880 { 881 *loadavg = (1.0 - cexp) * oldloadavg; 882 883 } 884 else 885 { 886 *loadavg = ((1.0 - cexp) * oldloadavg) + ((rq / oc) * cexp); 887 } 888 oldloadavg = *loadavg; 889 } 890# else /* not MOTOROLA */ 891# if defined(sony) && OSMAJORVERSION == 4 892# ifdef mips 893 { 894 fix temp; 895 (void) read(kmem, (char *)&temp, sizeof(fix)); 896 *loadavg = FIX_TO_DBL(temp); 897 } 898# else /* not mips */ 899 { 900 long temp; 901 (void) read(kmem, (char *)&temp, sizeof(long)); 902 *loadavg = (double)temp/FSCALE; 903 } 904# endif /* mips */ 905# else /* not sony NEWSOS4 */ 906 (void) read(kmem, (char *)loadavg, sizeof(double)); 907# endif /* sony NEWOS4 */ 908# endif /* MOTOROLA else */ 909# endif /* AIXV3 else */ 910# endif /* umips else */ 911#endif /* SVR4 or ... else */ 912 return; 913} 914#endif /* HAVE_GETLOADAVG else */ 915#endif /* __bsdi__ else */ 916#endif /* __QNXNTO__ else */ 917#endif /* __osf__ else */ 918#endif /* LOADSTUB else */ 919#endif /* __APPLE__ else */ 920#endif /* __GNU__ else */ 921#endif /* linux else */ 922#endif /* SYSV && i386 else */ 923 924static void xload_error(const char *str1, const char *str2) 925{ 926 (void) fprintf(stderr,"xload: %s %s\n", str1, str2); 927#ifdef __bsdi__ 928 if (kd) 929 kvm_close(kd); 930#endif 931 exit(-1); 932} 933 934#endif /* END of __CYGWIN__ */ 935