get_load.c revision fd0c672f
1/* $XdotOrg: xc/programs/xload/get_load.c,v 1.2 2004/04/23 19:54:57 eich Exp $ */
2/* $XConsortium: get_load.c /main/37 1996/03/09 09:38:04 kaleb $ */
3/* $XFree86: xc/programs/xload/get_load.c,v 1.21tsi Exp $ */
4/*
5
6Copyright (c) 1989  X Consortium
7
8Permission is hereby granted, free of charge, to any person obtaining
9a copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sublicense, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice shall be included
17in all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
23OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25OTHER DEALINGS IN THE SOFTWARE.
26
27Except as contained in this notice, the name of the X Consortium shall
28not be used in advertising or otherwise to promote the sale, use or
29other dealings in this Software without prior written authorization
30from the X Consortium.
31
32*/
33
34/*
35 * get_load - get system load
36 *
37 * Authors:  Many and varied...
38 *
39 * Call InitLoadPoint() to initialize.
40 * GetLoadPoint() is a callback for the StripChart widget.
41 */
42
43#ifdef HAVE_CONFIG_H
44# include "config.h"
45#endif
46
47#include <X11/Xos.h>
48#include <X11/Intrinsic.h>
49#include <X11/Xlocale.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include "xload.h"
53
54#if defined(__CYGWIN__)
55#include <windows.h>
56typedef struct {
57  DWORD stat;
58  union {
59    LONG vLong;
60    double vDouble;
61    LONGLONG vLongLong;
62    void *string;
63  } u;
64} COUNTER;
65static HANDLE query;
66static HANDLE counter;
67static HINSTANCE hdll;
68static long (__stdcall *pdhopen)(LPCSTR, DWORD, HANDLE);
69static long (__stdcall *pdhaddcounter)(HANDLE, LPCSTR, DWORD, HANDLE*);
70static long (__stdcall *pdhcollectquerydata)(HANDLE);
71static long (__stdcall *pdhgetformattedcountervalue)(HANDLE, DWORD, LPDWORD, COUNTER*);
72#define CYGWIN_PERF
73void InitLoadPoint()
74{
75  long ret;
76  hdll=LoadLibrary("pdh.dll");
77  if (!hdll) exit(-1);
78  pdhopen=(void*)GetProcAddress(hdll, "PdhOpenQueryA");
79  if (!pdhopen) exit(-1);
80  pdhaddcounter=(void*)GetProcAddress(hdll, "PdhAddCounterA");
81  if (!pdhaddcounter) exit(-1);
82  pdhcollectquerydata=(void*)GetProcAddress(hdll, "PdhCollectQueryData");
83  if (!pdhcollectquerydata) exit(-1);
84  pdhgetformattedcountervalue=(void*)GetProcAddress(hdll, "PdhGetFormattedCounterValue");
85  if (!pdhgetformattedcountervalue) exit(-1);
86  ret = pdhopen( NULL , 0, &query );
87  if (ret!=0) exit(-1);
88  ret = pdhaddcounter(query, "\\Processor(_Total)\\% Processor Time", 0, &counter);
89  if (ret!=0) exit(-1);
90}
91void GetLoadPoint( w, closure, call_data )      /* SYSV386 version */
92     Widget  w;              /* unused */
93     XtPointer       closure;        /* unused */
94     XtPointer       call_data;      /* pointer to (double) return value */
95{
96  double *loadavg = (double *)call_data;
97  COUNTER fmtvalue;
98  long ret;
99  *loadavg = 0.0;
100  ret = pdhcollectquerydata(query);
101  if (ret!=0) return;
102  ret = pdhgetformattedcountervalue(counter, 0x200, NULL, &fmtvalue);
103  if (ret!=0) return;
104  *loadavg = (fmtvalue.u.vDouble-0.01)/100.0;
105}
106#else
107
108
109#if !defined(DGUX)
110#if defined(att) || defined(QNX4)
111#define LOADSTUB
112#endif
113
114#ifndef macII
115#ifndef apollo
116#ifndef LOADSTUB
117#if !defined(linux) && !defined(__UNIXOS2__) && !defined(__GLIBC__)
118#include <nlist.h>
119#endif /* !linux && ... */
120#endif /* LOADSTUB */
121#endif /* apollo */
122#endif /* macII */
123
124#if defined(MOTOROLA) && defined(SYSV)
125#include <sys/sysinfo.h>
126#endif
127
128#ifdef sun
129#    include <sys/param.h>
130#    if !defined(HAVE_CONFIG_H) && defined(SVR4)
131# 	define HAVE_LIBKSTAT 1
132#    endif
133#    ifdef HAVE_LIBKSTAT
134#	include <kstat.h>
135#	include <errno.h>
136#    elif defined(i386) && !defined(SVR4)
137#        include <kvm.h>
138#        define	KVM_ROUTINES
139#    endif /* i386 */
140#endif
141
142#ifdef CSRG_BASED
143#include <sys/param.h>
144#endif
145
146#if defined(umips) || (defined(ultrix) && defined(mips))
147#include <sys/fixpoint.h>
148#endif
149
150#if  defined(CRAY) || defined(AIXV3)
151#include <sys/param.h>
152#define word word_t
153#include <sys/sysinfo.h>
154#undef word
155#undef n_type
156#define n_type n_value
157#endif	/* CRAY */
158
159#ifdef sequent
160#include <sys/vm.h>
161#endif /* sequent */
162
163#ifdef macII
164#include <a.out.h>
165#include <sys/var.h>
166#define X_AVENRUN 0
167#define fxtod(i) (vec[i].high+(vec[i].low/65536.0))
168struct lavnum {
169    unsigned short high;
170    unsigned short low;
171};
172#endif /* macII */
173
174#ifdef hcx
175#include <sys/param.h>
176#endif /* hcx */
177
178#if defined(UTEK) || defined(alliant) || (defined(MOTOROLA) && defined(SVR4))
179#define FSCALE	100.0
180#endif
181
182#ifdef sequent
183#define FSCALE	1000.0
184#endif
185
186#ifdef sgi
187#define FSCALE	1024.0
188#endif
189
190#if defined(sony) && OSMAJORVERSION == 4
191#ifdef mips
192#include <sys/fixpoint.h>
193#else
194#include <sys/param.h>
195#endif
196#endif
197
198#ifdef __osf__
199/*
200 * Use the table(2) interface; it doesn't require setuid root.
201 *
202 * Select 0, 1, or 2 for 5, 30, or 60 second load averages.
203 */
204#ifndef WHICH_AVG
205#define WHICH_AVG 1
206#endif
207#include <sys/table.h>
208#endif
209
210#ifdef SVR4
211#ifndef FSCALE
212#define FSCALE	(1 << 8)
213#endif
214#endif
215
216#ifdef X_NOT_POSIX
217extern long lseek();
218#endif
219
220void xload_error(char *, char *);
221
222
223#ifdef apollo
224#include <apollo/base.h>
225#include <apollo/time.h>
226typedef struct {
227	short		state;		/* ready, waiting, etc. */
228	pinteger	usr;		/* user sr */
229	linteger	upc;		/* user pc */
230	linteger	usp;		/* user stack pointer */
231	linteger	usb;		/* user sb ptr (A6) */
232	time_$clock_t	cpu_total;	/* cumulative cpu used by process */
233	unsigned short	priority;	/* process priority */
234    } proc1_$info_t;
235
236void proc1_$get_cput(
237	time_$clock_t	*cput
238);
239
240void proc1_$get_info(
241	short		&pid,
242	proc1_$info_t	*info,
243	status_$t	*sts
244);
245
246static int     lastNullCpu;
247static int     lastClock;
248
249void InitLoadPoint()				/* Apollo version */
250{
251     time_$clock_t  timeNow;
252     proc1_$info_t  info;
253     status_$t      st;
254
255     proc1_$get_info( (short) 2, &info, &st );
256     time_$clock( &timeNow );
257
258     lastClock = timeNow.low32;
259     lastNullCpu = info.cpu_total.low32;
260}
261
262/* ARGSUSED */
263void GetLoadPoint( w, closure, call_data ) 	/* Apollo version */
264     Widget	w;		/* unused */
265     XtPointer	closure;	/* unused */
266     XtPointer	call_data;	/* pointer to (double) return value */
267{
268     time_$clock_t  timeNow;
269     double         temp;
270     proc1_$info_t  info;
271     status_$t      st;
272
273     proc1_$get_info( (short) 2, &info, &st );
274     time_$clock( &timeNow );
275
276     temp = info.cpu_total.low32 - lastNullCpu;
277     *(double *)call_data = 1.0 - temp / (timeNow.low32 - lastClock);
278
279     lastClock = timeNow.low32;
280     lastNullCpu = info.cpu_total.low32;
281}
282#else /* not apollo */
283#if defined(SYSV) && defined(i386)
284/*
285 * inspired by 'avgload' by John F. Haugh II
286 */
287#include <sys/param.h>
288#include <sys/buf.h>
289#include <sys/immu.h>
290#include <sys/region.h>
291#include <sys/var.h>
292#include <sys/proc.h>
293#define KERNEL_FILE "/unix"
294#define KMEM_FILE "/dev/kmem"
295#define VAR_NAME "v"
296#define PROC_NAME "proc"
297#define BUF_NAME "buf"
298#define DECAY 0.8
299struct nlist namelist[] = {
300  {VAR_NAME},
301  {PROC_NAME},
302  {BUF_NAME},
303  {0},
304};
305
306static int kmem;
307static struct var v;
308static struct proc *p;
309static XtPointer first_buf, last_buf;
310
311void InitLoadPoint()				/* SYSV386 version */
312{
313    int i;
314
315    nlist( KERNEL_FILE, namelist);
316
317    for (i=0; namelist[i].n_name; i++)
318	if (namelist[i].n_value == 0)
319	    xload_error("cannot get name list from", KERNEL_FILE);
320
321    if ((kmem = open(KMEM_FILE, O_RDONLY)) < 0)
322	xload_error("cannot open", KMEM_FILE);
323
324    if (lseek(kmem, namelist[0].n_value, 0) == -1)
325	xload_error("cannot seek", VAR_NAME);
326
327    if (read(kmem, &v, sizeof(v)) != sizeof(v))
328	xload_error("cannot read", VAR_NAME);
329
330    if ((p=(struct proc *)malloc(v.v_proc*sizeof(*p))) == NULL)
331	xload_error("cannot allocat space for", PROC_NAME);
332
333    first_buf = (XtPointer) namelist[2].n_value;
334    last_buf  = (char *)first_buf + v.v_buf * sizeof(struct buf);
335}
336
337/* ARGSUSED */
338void GetLoadPoint( w, closure, call_data )	/* SYSV386 version */
339Widget	w;		/* unused */
340XtPointer	closure;	/* unused */
341XtPointer	call_data;	/* pointer to (double) return value */
342{
343    double *loadavg = (double *)call_data;
344    static double avenrun = 0.0;
345    int i, nproc, size;
346
347    (void) lseek(kmem, namelist[0].n_value, 0);
348    (void) read(kmem, &v, sizeof(v));
349
350    size = (struct proc *)v.ve_proc - (struct proc *)namelist[1].n_value;
351
352    (void) lseek(kmem, namelist[1].n_value, 0);
353    (void) read(kmem, p, size * sizeof(struct proc));
354
355    for (nproc = 0, i=0; i<size; i++)
356	  if ((p[i].p_stat == SRUN) ||
357	      (p[i].p_stat == SIDL) ||
358	      (p[i].p_stat == SXBRK) ||
359	      (p[i].p_stat == SSLEEP && (p[i].p_pri < PZERO) &&
360	       (p[i].p_wchan >= (char *)first_buf) && (p[i].p_wchan < (char *)last_buf)))
361	    nproc++;
362
363    /* update the load average using a decay filter */
364    avenrun = DECAY * avenrun + nproc * (1.0 - DECAY);
365    *loadavg = avenrun;
366
367    return;
368}
369#else /* not (SYSV && i386) */
370#ifdef KVM_ROUTINES
371/*
372 *	Sun 386i Code - abstracted to see the wood for the trees
373 */
374
375static struct nlist nl[2];
376static kvm_t *kd;
377
378void
379InitLoadPoint()					/* Sun 386i version */
380{
381    kd = kvm_open("/vmunix", NULL, NULL, O_RDONLY, "Load Widget");
382    if (kd == (kvm_t *)0) {
383	xload_error("cannot get access to kernel address space", "");
384    }
385
386    nl[0].n_name = "avenrun";
387    nl[1].n_name = NULL;
388
389    if (kvm_nlist(kd, nl) != 0) {
390	xload_error("cannot get name list", "");
391    }
392
393    if (nl[0].n_value == 0) {
394	xload_error("Cannot find address for avenrun in the kernel\n", "");
395    }
396}
397
398/* ARGSUSED */
399void
400GetLoadPoint( w, closure, call_data ) 		/* Sun 386i version */
401Widget	w;		/* unused */
402XtPointer closure;	/* unused */
403XtPointer call_data;	/* pointer to (double) return value */
404{
405    double *loadavg = (double *)call_data;
406    long	temp;
407
408    if (kvm_read(kd, nl[0].n_value, (char *)&temp, sizeof (temp)) !=
409	sizeof (temp)) {
410	xload_error("Kernel read error", "");
411    }
412    *loadavg = (double)temp/FSCALE;
413}
414#else /* not KVM_ROUTINES */
415
416#if defined(linux) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
417
418void InitLoadPoint()
419{
420      return;
421}
422
423void GetLoadPoint( w, closure, call_data )
424     Widget   w;              /* unused */
425     XtPointer  closure;        /* unused */
426     XtPointer  call_data;      /* pointer to (double) return value */
427{
428      static int fd = -1;
429      int n;
430      char buf[10] = {0, };
431#ifndef X_LOCALE
432      char *dp;
433      static char ldp = 0;
434#endif
435
436
437      if (fd < 0)
438      {
439              if (fd == -2 ||
440                  (fd = open("/proc/loadavg", O_RDONLY)) < 0)
441              {
442                      fd = -2;
443                      *(double *)call_data = 0.0;
444                      return;
445              }
446#ifndef X_LOCALE
447	      ldp = *localeconv()->decimal_point;
448#endif
449      }
450      else
451              lseek(fd, 0, 0);
452
453      if ((n = read(fd, buf, sizeof(buf)-1)) > 0) {
454#ifndef X_LOCALE
455	  if (ldp != '.')
456	      while ((dp = memchr(buf,'.',sizeof(buf)-1)) != NULL) {
457		  *(char *)dp = ldp;
458	      }
459
460#endif
461	  if (sscanf(buf, "%lf", (double *)call_data) == 1)
462	      return;
463      }
464
465
466      *(double *)call_data = 0.0;     /* temporary hiccup */
467
468      return;
469}
470
471#else /* linux */
472
473#ifdef __GNU__
474
475#include <mach.h>
476
477static processor_set_t default_set;
478
479void InitLoadPoint()
480{
481  if (processor_set_default (mach_host_self (), &default_set) != KERN_SUCCESS)
482    xload_error("cannot get processor_set_default", "");
483}
484
485/* ARGSUSED */
486void GetLoadPoint( w, closure, call_data )
487     Widget	w;		/* unused */
488     XtPointer	closure;	/* unused */
489     XtPointer	call_data;	/* pointer to (double) return value */
490{
491  host_t host;
492  struct processor_set_basic_info info;
493  unsigned info_count;
494
495  info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
496  if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host,
497			  (processor_set_info_t) &info, &info_count)
498      != KERN_SUCCESS)
499    {
500      InitLoadPoint();
501      info.load_average = 0;
502    }
503
504  *(double *)call_data = info.load_average * 1000 / LOAD_SCALE;
505
506  return;
507}
508
509#else /* __GNU__ */
510
511#ifdef __DARWIN__
512
513#include <mach/mach.h>
514
515static mach_port_t host_priv_port;
516
517void InitLoadPoint()
518{
519    host_priv_port = mach_host_self();
520}
521
522/* ARGSUSED */
523void GetLoadPoint( w, closure, call_data )
524    Widget	w;		/* unused */
525    XtPointer	closure;	/* unused */
526    XtPointer	call_data;	/* pointer to (double) return value */
527{
528    double *loadavg = (double *)call_data;
529
530    struct host_load_info load_data;
531    int host_count;
532    kern_return_t kr;
533
534    host_count = sizeof(load_data)/sizeof(integer_t);
535    kr = host_statistics(host_priv_port, HOST_LOAD_INFO,
536                        (host_info_t)&load_data, &host_count);
537    if (kr != KERN_SUCCESS)
538        xload_error("cannot get host statistics", "");
539    *loadavg = (double)load_data.avenrun[0]/LOAD_SCALE;
540    return;
541}
542
543#else /* __DARWIN__ */
544
545#ifdef LOADSTUB
546
547void InitLoadPoint()
548{
549}
550
551/* ARGSUSED */
552void GetLoadPoint( w, closure, call_data )
553     Widget	w;		/* unused */
554     XtPointer	closure;	/* unused */
555     XtPointer	call_data;	/* pointer to (double) return value */
556{
557	*(double *)call_data = 1.0;
558}
559
560#else /* not LOADSTUB */
561
562#ifdef __osf__
563
564void InitLoadPoint()
565{
566}
567
568/*ARGSUSED*/
569void GetLoadPoint( w, closure, call_data )
570     Widget   w;              /* unused */
571     XtPointer  closure;        /* unused */
572     XtPointer  call_data;      /* pointer to (double) return value */
573{
574    double *loadavg = (double *)call_data;
575    struct tbl_loadavg load_data;
576
577    if (table(TBL_LOADAVG, 0, (char *)&load_data, 1, sizeof(load_data)) < 0)
578	xload_error("error reading load average", "");
579    *loadavg = (load_data.tl_lscale == 0) ?
580	load_data.tl_avenrun.d[WHICH_AVG] :
581	load_data.tl_avenrun.l[WHICH_AVG] / (double)load_data.tl_lscale;
582}
583
584#else /* not __osf__ */
585
586#ifdef __QNXNTO__
587#include <time.h>
588#include <sys/neutrino.h>
589static _Uint64t          nto_idle = 0, nto_idle_last = 0;
590static  int       nto_idle_id;
591static  struct timespec nto_now, nto_last;
592
593void
594InitLoadPoint()
595{
596  nto_idle_id = ClockId(1, 1); /* Idle thread */
597  ClockTime(nto_idle_id, NULL, &nto_idle_last);
598  clock_gettime( CLOCK_REALTIME, &nto_last);
599}
600
601/* ARGSUSED */
602void
603GetLoadPoint( w, closure, call_data )           /* QNX NTO version */
604Widget  w;              /* unused */
605XtPointer closure;      /* unused */
606XtPointer call_data;    /* pointer to (double) return value */
607{
608    double *loadavg = (double *)call_data;
609    double timediff;
610    double temp = 0.0;
611
612    ClockTime(nto_idle_id, NULL, &nto_idle);
613    clock_gettime( CLOCK_REALTIME, &nto_now);
614    timediff = 1000000000.0 * (nto_now.tv_sec - nto_last.tv_sec)
615               + (nto_now.tv_nsec - nto_last.tv_nsec);
616    temp = 1.0 - (nto_idle-nto_idle_last)/timediff;
617    *loadavg = temp >= 0 ? temp : 0;
618    nto_idle_last = nto_idle;
619    nto_last = nto_now;
620}
621#else /* not __QNXNTO__ */
622
623#ifdef __bsdi__
624#include <kvm.h>
625
626static struct nlist nl[] = {
627  { "_averunnable" },
628#define X_AVERUNNABLE 0
629  { "_fscale" },
630#define X_FSCALE      1
631  { "" },
632};
633static kvm_t *kd;
634static int fscale;
635
636void InitLoadPoint()
637{
638  fixpt_t averunnable[3];  /* unused really */
639
640  if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
641    xload_error("can't open kvm files", "");
642
643  if (kvm_nlist(kd, nl) != 0)
644    xload_error("can't read name list", "");
645
646  if (kvm_read(kd, (off_t)nl[X_AVERUNNABLE].n_value, (char *)averunnable,
647	       sizeof(averunnable)) != sizeof(averunnable))
648    xload_error("couldn't obtain _averunnable variable", "");
649
650  if (kvm_read(kd, (off_t)nl[X_FSCALE].n_value, (char *)&fscale,
651	       sizeof(fscale)) != sizeof(fscale))
652    xload_error("couldn't obtain _fscale variable", "");
653
654  return;
655}
656
657void GetLoadPoint(w, closure, call_data)
658     Widget w;          /* unused */
659     XtPointer closure;   /* unused */
660     XtPointer call_data; /* ptr to (double) return value */
661{
662  double *loadavg = (double *)call_data;
663  fixpt_t t;
664
665  if (kvm_read(kd, (off_t)nl[X_AVERUNNABLE].n_value, (char *)&t,
666	       sizeof(t)) != sizeof(t))
667    xload_error("couldn't obtain load average", "");
668
669  *loadavg = (double)t/fscale;
670
671  return;
672}
673
674#else /* not __bsdi__ */
675#if defined(BSD) && (BSD >= 199306)
676#include <stdlib.h>
677
678void InitLoadPoint()
679{
680}
681
682void GetLoadPoint(w, closure, call_data)
683     Widget w;          /* unused */
684     XtPointer closure;   /* unused */
685     XtPointer call_data; /* ptr to (double) return value */
686{
687  double *loadavg = (double *)call_data;
688
689  if (getloadavg(loadavg, 1) < 0)
690    xload_error("couldn't obtain load average", "");
691}
692
693#else /* not BSD >= 199306 */
694#if defined(sun) && defined(HAVE_LIBKSTAT)
695
696static kstat_t		*ksp;
697static kstat_ctl_t	*kc;
698
699void
700InitLoadPoint(void)
701{
702	if ((kc = kstat_open()) == NULL)
703		xload_error("kstat_open failed:", strerror(errno));
704
705	if ((ksp = kstat_lookup(kc, "unix", 0, "system_misc")) == NULL)
706		xload_error("kstat_lookup failed:", strerror(errno));
707}
708
709void
710GetLoadPoint(Widget w, XtPointer closure, XtPointer call_data)
711{
712	kstat_named_t *vp;
713	double *loadavg = (double *)call_data;
714
715	if (kstat_read(kc, ksp, NULL) == -1)
716		xload_error("kstat_read failed:", strerror(errno));
717
718	if ((vp = kstat_data_lookup(ksp, "avenrun_1min")) == NULL)
719		xload_error("kstat_data_lookup failed:", strerror(errno));
720
721	*loadavg = (double)vp->value.l / FSCALE;
722}
723#else /* not Solaris */
724
725#ifndef KMEM_FILE
726#define KMEM_FILE "/dev/kmem"
727#endif
728
729#ifndef KERNEL_FILE
730
731#ifdef alliant
732#define KERNEL_FILE "/vmunix"
733#endif /* alliant */
734
735#ifdef CRAY
736#define KERNEL_FILE "/unicos"
737#endif /* CRAY */
738
739#ifdef hpux
740#define KERNEL_FILE "/hp-ux"
741#endif /* hpux */
742
743#ifdef macII
744#define KERNEL_FILE "/unix"
745#endif /* macII */
746
747#ifdef umips
748# ifdef SYSTYPE_SYSV
749# define KERNEL_FILE "/unix"
750# else
751# define KERNEL_FILE "/vmunix"
752# endif /* SYSTYPE_SYSV */
753#endif /* umips */
754
755#ifdef sequent
756#define KERNEL_FILE "/dynix"
757#endif /* sequent */
758
759#ifdef hcx
760#define KERNEL_FILE "/unix"
761#endif /* hcx */
762
763#ifdef MOTOROLA
764#if defined(SYSV) && defined(m68k)
765#define KERNEL_FILE "/sysV68"
766#endif
767#if defined(SYSV) && defined(m88k)
768#define KERNEL_FILE "/unix"
769#endif
770#ifdef SVR4
771#define KERNEL_FILE "/unix"
772#endif
773#endif /* MOTOROLA */
774
775#if defined(sun) && defined(SVR4)
776#define KERNEL_FILE "/kernel/unix"
777#endif
778
779#ifdef sgi
780#if (OSMAJORVERSION > 4)
781#define KERNEL_FILE "/unix"
782#endif
783#endif
784
785/*
786 * provide default for everyone else
787 */
788#ifndef KERNEL_FILE
789#ifdef SVR4
790#define KERNEL_FILE "/stand/unix"
791#else
792#ifdef SYSV
793#define KERNEL_FILE "/unix"
794#else
795/* If a BSD system, check in <paths.h> */
796#   ifdef BSD
797#    include <paths.h>
798#    ifdef _PATH_UNIX
799#     define KERNEL_FILE _PATH_UNIX
800#    else
801#     ifdef _PATH_KERNEL
802#      define KERNEL_FILE _PATH_KERNEL
803#     else
804#      define KERNEL_FILE "/vmunix"
805#     endif
806#    endif
807#   else /* BSD */
808#    define KERNEL_FILE "/vmunix"
809#   endif /* BSD */
810#endif /* SYSV */
811#endif /* SVR4 */
812#endif /* KERNEL_FILE */
813#endif /* KERNEL_FILE */
814
815
816#ifndef KERNEL_LOAD_VARIABLE
817#    if defined(BSD) && (BSD >= 199103)
818#        define KERNEL_LOAD_VARIABLE "_averunnable"
819#    endif /* BSD >= 199103 */
820
821#    ifdef alliant
822#        define KERNEL_LOAD_VARIABLE "_Loadavg"
823#    endif /* alliant */
824
825#    ifdef CRAY
826#        if defined(CRAY2) && OSMAJORVERSION == 4
827#            define KERNEL_LOAD_VARIABLE "avenrun"
828#        else
829#            define KERNEL_LOAD_VARIABLE "sysinfo"
830#            define SYSINFO
831#        endif /* defined(CRAY2) && OSMAJORVERSION == 4 */
832#    endif /* CRAY */
833
834#    ifdef hpux
835#        ifdef __hp9000s800
836#            define KERNEL_LOAD_VARIABLE "avenrun"
837#        endif /* hp9000s800 */
838#    endif /* hpux */
839
840#    ifdef umips
841#        ifdef SYSTYPE_SYSV
842#            define KERNEL_LOAD_VARIABLE "avenrun"
843#        else
844#            define KERNEL_LOAD_VARIABLE "_avenrun"
845#        endif /* SYSTYPE_SYSV */
846#    endif /* umips */
847
848#    ifdef sgi
849#	 define KERNEL_LOAD_VARIABLE "avenrun"
850#    endif /* sgi */
851
852#    ifdef AIXV3
853#        define KERNEL_LOAD_VARIABLE "sysinfo"
854#    endif /* AIXV3 */
855
856#    ifdef MOTOROLA
857#        if defined(SYSV) && defined(m68k)
858#            define KERNEL_LOAD_VARIABLE "sysinfo"
859#        endif
860#        if defined(SYSV) && defined(m88k)
861#            define KERNEL_LOAD_VARIABLE "_sysinfo"
862#        endif
863#        ifdef SVR4
864#            define KERNEL_LOAD_VARIABLE "avenrun"
865#        endif
866#    endif /* MOTOROLA */
867
868#endif /* KERNEL_LOAD_VARIABLE */
869
870/*
871 * provide default for everyone else
872 */
873
874#ifndef KERNEL_LOAD_VARIABLE
875#    ifdef USG
876#        define KERNEL_LOAD_VARIABLE "sysinfo"
877#        define SYSINFO
878#    else
879#    ifdef SVR4
880#        define KERNEL_LOAD_VARIABLE "avenrun"
881#    else
882#        define KERNEL_LOAD_VARIABLE "_avenrun"
883#    endif
884#    endif
885#endif /* KERNEL_LOAD_VARIABLE */
886
887#ifdef macII
888static struct var v;
889static int pad[2];	/* This padding is needed if xload compiled on */
890			/* a/ux 1.1 is executed on a/ux 1.0, because */
891			/* the var structure had too much padding in 1.0, */
892			/* so the 1.0 kernel writes past the end of the 1.1 */
893			/* var structure in the uvar() call. */
894static struct nlist nl[2];
895static struct lavnum vec[3];
896#else /* not macII */
897static struct nlist namelist[] = {	    /* namelist for vmunix grubbing */
898#define LOADAV 0
899    {KERNEL_LOAD_VARIABLE},
900    {0}
901};
902#endif /* macII */
903
904static int kmem;
905static long loadavg_seek;
906
907void InitLoadPoint()
908{
909#ifdef macII
910    extern nlist();
911
912    int i;
913
914    strcpy(nl[0].n_name, "avenrun");
915    nl[1].n_name[0] = '\0';
916
917    kmem = open(KMEM_FILE, O_RDONLY);
918    if (kmem < 0) {
919	xload_error("cannot open", KMEM_FILE);
920    }
921
922    uvar(&v);
923
924    if (nlist( KERNEL_FILE, nl) != 0) {
925	xload_error("cannot get name list from", KERNEL_FILE);
926    }
927    for (i = 0; i < 2; i++) {
928	nl[i].n_value = (int)nl[i].n_value - v.v_kvoffset;
929    }
930#else /* not macII */
931#if !defined(SVR4) && !defined(sgi) && !defined(MOTOROLA) && !defined(AIXV5) && !(BSD >= 199103)
932    extern void nlist();
933#endif
934
935#ifdef AIXV3
936    knlist( namelist, 1, sizeof(struct nlist));
937#else
938    nlist( KERNEL_FILE, namelist);
939#endif
940    /*
941     * Some systems appear to set only one of these to Zero if the entry could
942     * not be found, I hope no_one returns Zero as a good value, or bad things
943     * will happen to you.  (I have a hard time believing the value will
944     * ever really be zero anyway).   CDP 5/17/89.
945     */
946#ifdef hcx
947    if (namelist[LOADAV].n_type == 0 &&
948#else
949    if (namelist[LOADAV].n_type == 0 ||
950#endif /* hcx */
951	namelist[LOADAV].n_value == 0) {
952	xload_error("cannot get name list from", KERNEL_FILE);
953	exit(-1);
954    }
955    loadavg_seek = namelist[LOADAV].n_value;
956#if defined(umips) && defined(SYSTYPE_SYSV)
957    loadavg_seek &= 0x7fffffff;
958#endif /* umips && SYSTYPE_SYSV */
959#if (defined(CRAY) && defined(SYSINFO))
960    loadavg_seek += ((char *) (((struct sysinfo *)NULL)->avenrun)) -
961	((char *) NULL);
962#endif /* CRAY && SYSINFO */
963    kmem = open(KMEM_FILE, O_RDONLY);
964    if (kmem < 0) xload_error("cannot open", KMEM_FILE);
965#endif /* macII else */
966}
967
968/* ARGSUSED */
969void GetLoadPoint( w, closure, call_data )
970     Widget	w;		/* unused */
971     XtPointer	closure;	/* unused */
972     XtPointer	call_data;	/* pointer to (double) return value */
973{
974  	double *loadavg = (double *)call_data;
975
976#ifdef macII
977	lseek(kmem, (long)nl[X_AVENRUN].n_value, 0);
978#else
979	(void) lseek(kmem, loadavg_seek, 0);
980#endif
981
982#if defined(sun) || defined (UTEK) || defined(sequent) || defined(alliant) || defined(SVR4) || defined(sgi) || defined(hcx) || (BSD >= 199103)
983	{
984		long temp;
985		(void) read(kmem, (char *)&temp, sizeof(long));
986		*loadavg = (double)temp/FSCALE;
987	}
988#else /* else not sun or UTEK or sequent or alliant or SVR4 or sgi or hcx */
989# ifdef macII
990        {
991                read(kmem, vec, 3*sizeof(struct lavnum));
992                *loadavg = fxtod(0);
993        }
994# else /* else not macII */
995#  if defined(umips) || (defined(ultrix) && defined(mips))
996	{
997		fix temp;
998		(void) read(kmem, (char *)&temp, sizeof(fix));
999		*loadavg = FIX_TO_DBL(temp);
1000	}
1001#  else /* not umips or ultrix risc */
1002#    ifdef AIXV3
1003        {
1004          struct sysinfo sysinfo_now;
1005          struct sysinfo sysinfo_last;
1006          static firsttime = TRUE;
1007          static double runavg = 0.0, swpavg = 0.0;
1008
1009          (void) lseek(kmem, loadavg_seek, 0);
1010          (void) read(kmem, (char *)&sysinfo_last, sizeof(struct sysinfo));
1011          if (firsttime)
1012            {
1013              *loadavg = 0.0;
1014              firsttime = FALSE;
1015            }
1016          else
1017            {
1018              sleep(1);
1019              (void) lseek(kmem, loadavg_seek, 0);
1020              (void) read(kmem, (char *)&sysinfo_now, sizeof(struct sysinfo));
1021              runavg *= 0.8; swpavg *= 0.8;
1022              if (sysinfo_now.runocc != sysinfo_last.runocc)
1023                runavg += 0.2*((sysinfo_now.runque - sysinfo_last.runque - 1)
1024                          /(double)(sysinfo_now.runocc - sysinfo_last.runocc));
1025              if (sysinfo_now.swpocc != sysinfo_last.swpocc)
1026                swpavg += 0.2*((sysinfo_now.swpque - sysinfo_last.swpque)
1027                          /(double)(sysinfo_now.swpocc - sysinfo_last.swpocc));
1028              *loadavg = runavg + swpavg;
1029              sysinfo_last = sysinfo_now;
1030            }
1031          /* otherwise we leave load alone. */
1032        }
1033#    else /* not AIXV3 */
1034#      if defined(MOTOROLA) && defined(SYSV)
1035	{
1036        static int init = 0;
1037        static kmem;
1038        static long loadavg_seek;
1039
1040#define CEXP    0.25            /* Constant used for load averaging */
1041
1042        struct sysinfo sysinfod;
1043        static double oldloadavg;
1044        static double cexp = CEXP;
1045        static long sv_rq, sv_oc;   /* save old values */
1046        double rq, oc;              /* amount values have changed */
1047
1048        if (!init)
1049        {
1050            if (nlist(KERNEL_FILE,namelist) == -1)
1051            {
1052                perror("xload: nlist()");
1053                xload_error("cannot get name list from", KERNEL_FILE);
1054            }
1055            loadavg_seek = namelist[0].n_value;
1056
1057            kmem = open(KMEM_FILE, O_RDONLY);
1058            if (kmem < 0)
1059            {
1060                perror("xload: open()");
1061                xload_error("cannot open", KMEM_FILE);
1062            }
1063        }
1064
1065        lseek(kmem, loadavg_seek, 0);
1066        if (read(kmem, &sysinfod, (int) sizeof (struct sysinfo)) == -1)
1067        {
1068             perror("xload: read() SYSINFONL");
1069             xload_error("read failed from", KMEM_FILE);
1070        }
1071
1072        if (!init)
1073        {
1074            init = 1;
1075            sv_rq = sysinfod.runque;
1076            sv_oc = sysinfod.runocc;
1077            oldloadavg = *loadavg = 0.0;
1078            return;
1079        }
1080        /*
1081         * calculate the amount the values have
1082         * changed since last update
1083         */
1084        rq = (double) sysinfod.runque - sv_rq;
1085        oc = (double) sysinfod.runocc - sv_oc;
1086
1087        /*
1088         * save old values for next time
1089         */
1090        sv_rq = sysinfod.runque;
1091        sv_oc = sysinfod.runocc;
1092
1093        if (oc == 0.0)          /* avoid divide by zero  */
1094        {
1095                *loadavg = (1.0 - cexp) * oldloadavg;
1096
1097        }
1098        else
1099        {
1100                *loadavg = ((1.0 - cexp) * oldloadavg) + ((rq / oc) * cexp);
1101        }
1102        oldloadavg = *loadavg;
1103	}
1104#      else /* not MOTOROLA */
1105#     if defined(sony) && OSMAJORVERSION == 4
1106#      ifdef mips
1107	{
1108		fix temp;
1109		(void) read(kmem, (char *)&temp, sizeof(fix));
1110		*loadavg = FIX_TO_DBL(temp);
1111	}
1112#      else /* not mips */
1113	{
1114		long temp;
1115		(void) read(kmem, (char *)&temp, sizeof(long));
1116		*loadavg = (double)temp/FSCALE;
1117	}
1118#      endif /* mips */
1119#     else /* not sony NEWSOS4 */
1120	(void) read(kmem, (char *)loadavg, sizeof(double));
1121#      endif /* sony NEWOS4 */
1122#     endif /* MOTOROLA else */
1123#    endif /* AIXV3 else */
1124#  endif /* umips else */
1125# endif /* macII else */
1126#endif /* sun or SVR4 or ... else */
1127	return;
1128}
1129#endif /* sun else */
1130#endif /* BSD >= 199306 else */
1131#endif /* __bsdi__ else */
1132#endif /* __QNXNTO__ else */
1133#endif /* __osf__ else */
1134#endif /* LOADSTUB else */
1135#endif /* __DARWIN__ else */
1136#endif /* __GNU__ else */
1137#endif /* linux else */
1138#endif /* KVM_ROUTINES else */
1139#endif /* SYSV && i386 else */
1140
1141void xload_error(str1, str2)
1142char *str1, *str2;
1143{
1144    (void) fprintf(stderr,"xload: %s %s\n", str1, str2);
1145#ifdef __bsdi__
1146    if (kd)
1147	kvm_close(kd);
1148#endif
1149    exit(-1);
1150}
1151
1152#endif /* apollo else */
1153
1154#else /* !DGUX */
1155
1156/* INTEL DGUX Release 4.20MU04
1157 * Copyright 1999 Takis Psarogiannakopoulos
1158 * Cambridge, UK
1159 * <takis@dpmms.cam.ac.uk>
1160 */
1161
1162#include <errno.h>
1163#include <nlist.h>
1164#include <sys/dg_sys_info.h>
1165
1166static struct dg_sys_info_load_info load_info;  /* DG/ux */
1167
1168#define KERNEL_FILE "/dgux"
1169#define LDAV_SYMBOL "_avenrun"
1170
1171void InitLoadPoint()
1172{
1173
1174}
1175
1176void GetLoadPoint(w, closure, call_data)
1177     Widget w;          /* unused */
1178     XtPointer closure;   /* unused */
1179     XtPointer call_data; /* ptr to (double) return value */
1180{
1181  double *loadavg = (double *)call_data;
1182
1183  if (getloadavg(loadavg, 1) < 0)
1184    xload_error("couldn't obtain load average", "");
1185}
1186
1187xload_error(str1, str2)
1188char *str1, *str2;
1189{
1190    (void) fprintf(stderr,"xload: %s %s\n", str1, str2);
1191    exit(-1);
1192}
1193
1194#if !defined (LDAV_CVT) && defined (FSCALE)
1195#define LDAV_CVT(n) (((double) (n)) / FSCALE)
1196#endif
1197#if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT)
1198#define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0)
1199#endif
1200#define LOAD_AVE_TYPE double
1201#ifndef LDAV_CVT
1202#define LDAV_CVT(n) ((double) (n))
1203#endif /* !LDAV_CVT */
1204static int channel;
1205static int getloadavg_initialized;
1206static long offset;
1207static struct nlist nl[2];
1208
1209
1210/* GETLOADAVG FUNCTION FOR DG/ux R4.20MU04 */
1211
1212int
1213getloadavg (double loadavg[], int nelem)
1214{
1215  int elem = 0;                 /* Return value.  */
1216  int result =0 ;
1217
1218  /* This call can return -1 for an error, but with good args
1219     it's not supposed to fail.  The first argument is for no
1220     apparent reason of type `long int *'.  */
1221  result = dg_sys_info ((long int *) &load_info,
1222		DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
1223  if ( result == -1)
1224  {
1225     return(-1);
1226  }
1227  if (nelem > 0)
1228    loadavg[elem++] = load_info.one_minute;
1229  if (nelem > 1)
1230    loadavg[elem++] = load_info.five_minute;
1231  if (nelem > 2)
1232    loadavg[elem++] = load_info.fifteen_minute;
1233
1234  return elem;
1235}
1236
1237#endif /* END OF DG/ux */
1238
1239
1240#endif /* END of __CYGWIN__ */
1241