get_load.c revision 953c684b
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
51fd0c672fSmrg#if defined(__CYGWIN__)
52953c684bSmrg# define WIN32_LEAN_AND_MEAN
53953c684bSmrg# include <windows.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
131953c684bSmrg#  if defined(att) || defined(QNX4)
132953c684bSmrg#   define LOADSTUB
133953c684bSmrg#  endif
134fd0c672fSmrg
135953c684bSmrg#  ifndef LOADSTUB
136953c684bSmrg#   if !defined(linux) && !defined(__GLIBC__)
137953c684bSmrg#    include <nlist.h>
138953c684bSmrg#   endif /* !linux && ... */
139953c684bSmrg#  endif /* LOADSTUB */
140fd0c672fSmrg
141953c684bSmrg#  ifdef CSRG_BASED
142953c684bSmrg#   include <sys/param.h>
143953c684bSmrg#  endif
144fd0c672fSmrg
145953c684bSmrg#  ifdef sgi
146953c684bSmrg#   define FSCALE	1024.0
147953c684bSmrg#  endif
148fd0c672fSmrg
149953c684bSmrg#  ifdef __osf__
150fd0c672fSmrg/*
151fd0c672fSmrg * Use the table(2) interface; it doesn't require setuid root.
152fd0c672fSmrg *
153fd0c672fSmrg * Select 0, 1, or 2 for 5, 30, or 60 second load averages.
154fd0c672fSmrg */
155953c684bSmrg#   ifndef WHICH_AVG
156953c684bSmrg#    define WHICH_AVG 1
157953c684bSmrg#   endif
158953c684bSmrg#   include <sys/table.h>
159953c684bSmrg#  endif
160953c684bSmrg
161953c684bSmrg#  ifdef SVR4
162953c684bSmrg#   ifndef FSCALE
163953c684bSmrg#    define FSCALE	(1 << 8)
164953c684bSmrg#   endif
165953c684bSmrg#  endif
166953c684bSmrg
167953c684bSmrg#  if defined(SYSV) && defined(i386)
168fd0c672fSmrg/*
169fd0c672fSmrg * inspired by 'avgload' by John F. Haugh II
170fd0c672fSmrg */
171953c684bSmrg#   include <sys/param.h>
172953c684bSmrg#   include <sys/buf.h>
173953c684bSmrg#   include <sys/immu.h>
174953c684bSmrg#   include <sys/region.h>
175953c684bSmrg#   include <sys/var.h>
176953c684bSmrg#   include <sys/proc.h>
177953c684bSmrg#   define KERNEL_FILE "/unix"
178953c684bSmrg#   define KMEM_FILE "/dev/kmem"
179953c684bSmrg#   define VAR_NAME "v"
180953c684bSmrg#   define PROC_NAME "proc"
181953c684bSmrg#   define BUF_NAME "buf"
182953c684bSmrg#   define DECAY 0.8
183fd0c672fSmrgstruct nlist namelist[] = {
184fd0c672fSmrg  {VAR_NAME},
185fd0c672fSmrg  {PROC_NAME},
186fd0c672fSmrg  {BUF_NAME},
187fd0c672fSmrg  {0},
188fd0c672fSmrg};
189fd0c672fSmrg
190fd0c672fSmrgstatic int kmem;
191fd0c672fSmrgstatic struct var v;
192fd0c672fSmrgstatic struct proc *p;
193fd0c672fSmrgstatic XtPointer first_buf, last_buf;
194fd0c672fSmrg
195fd0c672fSmrgvoid InitLoadPoint()				/* SYSV386 version */
196fd0c672fSmrg{
197fd0c672fSmrg    int i;
198fd0c672fSmrg
199fd0c672fSmrg    nlist( KERNEL_FILE, namelist);
200fd0c672fSmrg
201953c684bSmrg    for (i=0; namelist[i].n_name; i++)
202fd0c672fSmrg	if (namelist[i].n_value == 0)
203fd0c672fSmrg	    xload_error("cannot get name list from", KERNEL_FILE);
204fd0c672fSmrg
205fd0c672fSmrg    if ((kmem = open(KMEM_FILE, O_RDONLY)) < 0)
206fd0c672fSmrg	xload_error("cannot open", KMEM_FILE);
207fd0c672fSmrg
208fd0c672fSmrg    if (lseek(kmem, namelist[0].n_value, 0) == -1)
209fd0c672fSmrg	xload_error("cannot seek", VAR_NAME);
210fd0c672fSmrg
211fd0c672fSmrg    if (read(kmem, &v, sizeof(v)) != sizeof(v))
212fd0c672fSmrg	xload_error("cannot read", VAR_NAME);
213fd0c672fSmrg
214fd0c672fSmrg    if ((p=(struct proc *)malloc(v.v_proc*sizeof(*p))) == NULL)
215fd0c672fSmrg	xload_error("cannot allocat space for", PROC_NAME);
216953c684bSmrg
217fd0c672fSmrg    first_buf = (XtPointer) namelist[2].n_value;
218fd0c672fSmrg    last_buf  = (char *)first_buf + v.v_buf * sizeof(struct buf);
219fd0c672fSmrg}
220953c684bSmrg
221fd0c672fSmrg/* ARGSUSED */
222fd0c672fSmrgvoid GetLoadPoint( w, closure, call_data )	/* SYSV386 version */
223fd0c672fSmrgWidget	w;		/* unused */
224fd0c672fSmrgXtPointer	closure;	/* unused */
225fd0c672fSmrgXtPointer	call_data;	/* pointer to (double) return value */
226fd0c672fSmrg{
227fd0c672fSmrg    double *loadavg = (double *)call_data;
228fd0c672fSmrg    static double avenrun = 0.0;
229fd0c672fSmrg    int i, nproc, size;
230953c684bSmrg
231fd0c672fSmrg    (void) lseek(kmem, namelist[0].n_value, 0);
232fd0c672fSmrg    (void) read(kmem, &v, sizeof(v));
233fd0c672fSmrg
234fd0c672fSmrg    size = (struct proc *)v.ve_proc - (struct proc *)namelist[1].n_value;
235fd0c672fSmrg
236fd0c672fSmrg    (void) lseek(kmem, namelist[1].n_value, 0);
237fd0c672fSmrg    (void) read(kmem, p, size * sizeof(struct proc));
238fd0c672fSmrg
239953c684bSmrg    for (nproc = 0, i=0; i<size; i++)
240fd0c672fSmrg	  if ((p[i].p_stat == SRUN) ||
241fd0c672fSmrg	      (p[i].p_stat == SIDL) ||
242fd0c672fSmrg	      (p[i].p_stat == SXBRK) ||
243fd0c672fSmrg	      (p[i].p_stat == SSLEEP && (p[i].p_pri < PZERO) &&
244fd0c672fSmrg	       (p[i].p_wchan >= (char *)first_buf) && (p[i].p_wchan < (char *)last_buf)))
245fd0c672fSmrg	    nproc++;
246fd0c672fSmrg
247fd0c672fSmrg    /* update the load average using a decay filter */
248fd0c672fSmrg    avenrun = DECAY * avenrun + nproc * (1.0 - DECAY);
249fd0c672fSmrg    *loadavg = avenrun;
250fd0c672fSmrg
251fd0c672fSmrg    return;
252fd0c672fSmrg}
253953c684bSmrg#  else /* not (SYSV && i386) */
254fd0c672fSmrg
255953c684bSmrg#   if defined(linux) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
256fd0c672fSmrg
25748e69166Smrgvoid InitLoadPoint(void)
258fd0c672fSmrg{
259fd0c672fSmrg      return;
260fd0c672fSmrg}
261fd0c672fSmrg
26248e69166Smrgvoid GetLoadPoint(
26348e69166Smrg    Widget	w,		/* unused */
26448e69166Smrg    XtPointer	closure,	/* unused */
26548e69166Smrg    XtPointer	call_data)      /* pointer to (double) return value */
266fd0c672fSmrg{
267fd0c672fSmrg      static int fd = -1;
268fd0c672fSmrg      int n;
269fd0c672fSmrg      char buf[10] = {0, };
270953c684bSmrg#    ifndef X_LOCALE
271fd0c672fSmrg      char *dp;
272fd0c672fSmrg      static char ldp = 0;
273953c684bSmrg#    endif
274fd0c672fSmrg
275fd0c672fSmrg
276fd0c672fSmrg      if (fd < 0)
277fd0c672fSmrg      {
278fd0c672fSmrg              if (fd == -2 ||
279fd0c672fSmrg                  (fd = open("/proc/loadavg", O_RDONLY)) < 0)
280fd0c672fSmrg              {
281fd0c672fSmrg                      fd = -2;
282fd0c672fSmrg                      *(double *)call_data = 0.0;
283fd0c672fSmrg                      return;
284fd0c672fSmrg              }
285953c684bSmrg#    ifndef X_LOCALE
286fd0c672fSmrg	      ldp = *localeconv()->decimal_point;
287953c684bSmrg#    endif
288fd0c672fSmrg      }
289fd0c672fSmrg      else
290fd0c672fSmrg              lseek(fd, 0, 0);
291fd0c672fSmrg
292fd0c672fSmrg      if ((n = read(fd, buf, sizeof(buf)-1)) > 0) {
293953c684bSmrg#    ifndef X_LOCALE
294fd0c672fSmrg	  if (ldp != '.')
295fd0c672fSmrg	      while ((dp = memchr(buf,'.',sizeof(buf)-1)) != NULL) {
296fd0c672fSmrg		  *(char *)dp = ldp;
297fd0c672fSmrg	      }
298953c684bSmrg
299953c684bSmrg#    endif
300fd0c672fSmrg	  if (sscanf(buf, "%lf", (double *)call_data) == 1)
301fd0c672fSmrg	      return;
302fd0c672fSmrg      }
303953c684bSmrg
304fd0c672fSmrg
305fd0c672fSmrg      *(double *)call_data = 0.0;     /* temporary hiccup */
306fd0c672fSmrg
307fd0c672fSmrg      return;
308fd0c672fSmrg}
309fd0c672fSmrg
310953c684bSmrg#   else /* linux */
311fd0c672fSmrg
312953c684bSmrg#    ifdef __GNU__
313fd0c672fSmrg
314953c684bSmrg#     include <mach.h>
315fd0c672fSmrg
316fd0c672fSmrgstatic processor_set_t default_set;
317fd0c672fSmrg
31848e69166Smrgvoid InitLoadPoint(void)
319fd0c672fSmrg{
320fd0c672fSmrg  if (processor_set_default (mach_host_self (), &default_set) != KERN_SUCCESS)
321fd0c672fSmrg    xload_error("cannot get processor_set_default", "");
322fd0c672fSmrg}
323fd0c672fSmrg
324fd0c672fSmrg/* ARGSUSED */
32548e69166Smrgvoid GetLoadPoint(
32648e69166Smrg    Widget	w,		/* unused */
32748e69166Smrg    XtPointer	closure,	/* unused */
32848e69166Smrg    XtPointer	call_data)	/* pointer to (double) return value */
329fd0c672fSmrg{
330fd0c672fSmrg  host_t host;
331fd0c672fSmrg  struct processor_set_basic_info info;
332fd0c672fSmrg  unsigned info_count;
333fd0c672fSmrg
334fd0c672fSmrg  info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
335fd0c672fSmrg  if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host,
336fd0c672fSmrg			  (processor_set_info_t) &info, &info_count)
337fd0c672fSmrg      != KERN_SUCCESS)
338fd0c672fSmrg    {
339fd0c672fSmrg      InitLoadPoint();
340fd0c672fSmrg      info.load_average = 0;
341fd0c672fSmrg    }
342fd0c672fSmrg
343fd0c672fSmrg  *(double *)call_data = info.load_average * 1000 / LOAD_SCALE;
344fd0c672fSmrg
345fd0c672fSmrg  return;
346fd0c672fSmrg}
347fd0c672fSmrg
348953c684bSmrg#    else /* __GNU__ */
349fd0c672fSmrg
350953c684bSmrg#     ifdef __APPLE__
351fd0c672fSmrg
352953c684bSmrg#      include <mach/mach.h>
353fd0c672fSmrg
354fd0c672fSmrgstatic mach_port_t host_priv_port;
355fd0c672fSmrg
35648e69166Smrgvoid InitLoadPoint(void)
357fd0c672fSmrg{
358fd0c672fSmrg    host_priv_port = mach_host_self();
359fd0c672fSmrg}
360fd0c672fSmrg
361fd0c672fSmrg/* ARGSUSED */
36248e69166Smrgvoid GetLoadPoint(
36348e69166Smrg    Widget	w,		/* unused */
36448e69166Smrg    XtPointer	closure,	/* unused */
36548e69166Smrg    XtPointer	call_data)	/* pointer to (double) return value */
366fd0c672fSmrg{
367fd0c672fSmrg    double *loadavg = (double *)call_data;
368fd0c672fSmrg
369fd0c672fSmrg    struct host_load_info load_data;
370fd0c672fSmrg    int host_count;
371fd0c672fSmrg    kern_return_t kr;
372fd0c672fSmrg
373fd0c672fSmrg    host_count = sizeof(load_data)/sizeof(integer_t);
374fd0c672fSmrg    kr = host_statistics(host_priv_port, HOST_LOAD_INFO,
375fd0c672fSmrg                        (host_info_t)&load_data, &host_count);
376fd0c672fSmrg    if (kr != KERN_SUCCESS)
377fd0c672fSmrg        xload_error("cannot get host statistics", "");
378fd0c672fSmrg    *loadavg = (double)load_data.avenrun[0]/LOAD_SCALE;
379fd0c672fSmrg    return;
380fd0c672fSmrg}
381fd0c672fSmrg
382953c684bSmrg#     else /* __APPLE__ */
383fd0c672fSmrg
384953c684bSmrg#      ifdef LOADSTUB
385fd0c672fSmrg
386fd0c672fSmrgvoid InitLoadPoint()
387fd0c672fSmrg{
388fd0c672fSmrg}
389fd0c672fSmrg
390fd0c672fSmrg/* ARGSUSED */
391fd0c672fSmrgvoid GetLoadPoint( w, closure, call_data )
392fd0c672fSmrg     Widget	w;		/* unused */
393fd0c672fSmrg     XtPointer	closure;	/* unused */
394fd0c672fSmrg     XtPointer	call_data;	/* pointer to (double) return value */
395fd0c672fSmrg{
396fd0c672fSmrg	*(double *)call_data = 1.0;
397fd0c672fSmrg}
398fd0c672fSmrg
399953c684bSmrg#      else /* not LOADSTUB */
400fd0c672fSmrg
401953c684bSmrg#       ifdef __osf__
402fd0c672fSmrg
403fd0c672fSmrgvoid InitLoadPoint()
404fd0c672fSmrg{
405fd0c672fSmrg}
406fd0c672fSmrg
407fd0c672fSmrg/*ARGSUSED*/
408fd0c672fSmrgvoid GetLoadPoint( w, closure, call_data )
409fd0c672fSmrg     Widget   w;              /* unused */
410fd0c672fSmrg     XtPointer  closure;        /* unused */
411fd0c672fSmrg     XtPointer  call_data;      /* pointer to (double) return value */
412fd0c672fSmrg{
413fd0c672fSmrg    double *loadavg = (double *)call_data;
414fd0c672fSmrg    struct tbl_loadavg load_data;
415fd0c672fSmrg
416fd0c672fSmrg    if (table(TBL_LOADAVG, 0, (char *)&load_data, 1, sizeof(load_data)) < 0)
417fd0c672fSmrg	xload_error("error reading load average", "");
418fd0c672fSmrg    *loadavg = (load_data.tl_lscale == 0) ?
419fd0c672fSmrg	load_data.tl_avenrun.d[WHICH_AVG] :
420fd0c672fSmrg	load_data.tl_avenrun.l[WHICH_AVG] / (double)load_data.tl_lscale;
421fd0c672fSmrg}
422fd0c672fSmrg
423953c684bSmrg#       else /* not __osf__ */
424fd0c672fSmrg
425953c684bSmrg#        ifdef __QNXNTO__
426953c684bSmrg#         include <time.h>
427953c684bSmrg#         include <sys/neutrino.h>
428fd0c672fSmrgstatic _Uint64t          nto_idle = 0, nto_idle_last = 0;
429fd0c672fSmrgstatic  int       nto_idle_id;
430fd0c672fSmrgstatic  struct timespec nto_now, nto_last;
431fd0c672fSmrg
432fd0c672fSmrgvoid
43348e69166SmrgInitLoadPoint(void)
434fd0c672fSmrg{
435fd0c672fSmrg  nto_idle_id = ClockId(1, 1); /* Idle thread */
436fd0c672fSmrg  ClockTime(nto_idle_id, NULL, &nto_idle_last);
437fd0c672fSmrg  clock_gettime( CLOCK_REALTIME, &nto_last);
438fd0c672fSmrg}
439fd0c672fSmrg
440fd0c672fSmrg/* ARGSUSED */
441fd0c672fSmrgvoid
44248e69166SmrgGetLoadPoint(			/* QNX NTO version */
44348e69166Smrg    Widget	w,		/* unused */
44448e69166Smrg    XtPointer	closure,	/* unused */
44548e69166Smrg    XtPointer	call_data)	/* pointer to (double) return value */
446fd0c672fSmrg{
447fd0c672fSmrg    double *loadavg = (double *)call_data;
448fd0c672fSmrg    double timediff;
449fd0c672fSmrg    double temp = 0.0;
450fd0c672fSmrg
451fd0c672fSmrg    ClockTime(nto_idle_id, NULL, &nto_idle);
452fd0c672fSmrg    clock_gettime( CLOCK_REALTIME, &nto_now);
453fd0c672fSmrg    timediff = 1000000000.0 * (nto_now.tv_sec - nto_last.tv_sec)
454fd0c672fSmrg               + (nto_now.tv_nsec - nto_last.tv_nsec);
455fd0c672fSmrg    temp = 1.0 - (nto_idle-nto_idle_last)/timediff;
456fd0c672fSmrg    *loadavg = temp >= 0 ? temp : 0;
457fd0c672fSmrg    nto_idle_last = nto_idle;
458fd0c672fSmrg    nto_last = nto_now;
459fd0c672fSmrg}
460953c684bSmrg#        else /* not __QNXNTO__ */
461fd0c672fSmrg
462953c684bSmrg#         ifdef __bsdi__
463953c684bSmrg#          include <kvm.h>
464fd0c672fSmrg
465fd0c672fSmrgstatic struct nlist nl[] = {
466fd0c672fSmrg  { "_averunnable" },
467953c684bSmrg#          define X_AVERUNNABLE 0
468fd0c672fSmrg  { "_fscale" },
469953c684bSmrg#          define X_FSCALE      1
470fd0c672fSmrg  { "" },
471fd0c672fSmrg};
472fd0c672fSmrgstatic kvm_t *kd;
473fd0c672fSmrgstatic int fscale;
474fd0c672fSmrg
47548e69166Smrgvoid InitLoadPoint(void)
476fd0c672fSmrg{
477fd0c672fSmrg  fixpt_t averunnable[3];  /* unused really */
478fd0c672fSmrg
479fd0c672fSmrg  if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
480fd0c672fSmrg    xload_error("can't open kvm files", "");
481fd0c672fSmrg
482fd0c672fSmrg  if (kvm_nlist(kd, nl) != 0)
483fd0c672fSmrg    xload_error("can't read name list", "");
484fd0c672fSmrg
485fd0c672fSmrg  if (kvm_read(kd, (off_t)nl[X_AVERUNNABLE].n_value, (char *)averunnable,
486fd0c672fSmrg	       sizeof(averunnable)) != sizeof(averunnable))
487fd0c672fSmrg    xload_error("couldn't obtain _averunnable variable", "");
488fd0c672fSmrg
489fd0c672fSmrg  if (kvm_read(kd, (off_t)nl[X_FSCALE].n_value, (char *)&fscale,
490fd0c672fSmrg	       sizeof(fscale)) != sizeof(fscale))
491fd0c672fSmrg    xload_error("couldn't obtain _fscale variable", "");
492fd0c672fSmrg
493fd0c672fSmrg  return;
494fd0c672fSmrg}
495fd0c672fSmrg
49648e69166Smrgvoid GetLoadPoint(
49748e69166Smrg     Widget	w,		/* unused */
49848e69166Smrg     XtPointer	closure,	/* unused */
49948e69166Smrg    XtPointer	call_data)	/* ptr to (double) return value */
500fd0c672fSmrg{
501fd0c672fSmrg  double *loadavg = (double *)call_data;
502fd0c672fSmrg  fixpt_t t;
503fd0c672fSmrg
504fd0c672fSmrg  if (kvm_read(kd, (off_t)nl[X_AVERUNNABLE].n_value, (char *)&t,
505fd0c672fSmrg	       sizeof(t)) != sizeof(t))
506fd0c672fSmrg    xload_error("couldn't obtain load average", "");
507fd0c672fSmrg
508fd0c672fSmrg  *loadavg = (double)t/fscale;
509fd0c672fSmrg
510fd0c672fSmrg  return;
511fd0c672fSmrg}
512fd0c672fSmrg
513953c684bSmrg#         else /* not __bsdi__ */
514953c684bSmrg#          ifndef KMEM_FILE
515953c684bSmrg#           define KMEM_FILE "/dev/kmem"
516953c684bSmrg#          endif
517fd0c672fSmrg
518953c684bSmrg#          ifndef KERNEL_FILE
519fd0c672fSmrg
520953c684bSmrg#           ifdef hpux
521953c684bSmrg#            define KERNEL_FILE "/hp-ux"
522953c684bSmrg#           endif /* hpux */
523fd0c672fSmrg
524953c684bSmrg#           ifdef sgi
525953c684bSmrg#            if (OSMAJORVERSION > 4)
526953c684bSmrg#             define KERNEL_FILE "/unix"
527953c684bSmrg#            endif
528953c684bSmrg#           endif
529fd0c672fSmrg
530fd0c672fSmrg/*
531fd0c672fSmrg * provide default for everyone else
532fd0c672fSmrg */
533953c684bSmrg#           ifndef KERNEL_FILE
534953c684bSmrg#            ifdef SVR4
535953c684bSmrg#             define KERNEL_FILE "/stand/unix"
536953c684bSmrg#            else
537953c684bSmrg#             ifdef SYSV
538953c684bSmrg#              define KERNEL_FILE "/unix"
539953c684bSmrg#             else
540fd0c672fSmrg/* If a BSD system, check in <paths.h> */
541953c684bSmrg#              ifdef BSD
542953c684bSmrg#               include <paths.h>
543953c684bSmrg#               ifdef _PATH_UNIX
544953c684bSmrg#                define KERNEL_FILE _PATH_UNIX
545953c684bSmrg#               else
546953c684bSmrg#                ifdef _PATH_KERNEL
547953c684bSmrg#                 define KERNEL_FILE _PATH_KERNEL
548953c684bSmrg#                else
549953c684bSmrg#                 define KERNEL_FILE "/vmunix"
550953c684bSmrg#                endif
551953c684bSmrg#               endif
552953c684bSmrg#              else /* BSD */
553953c684bSmrg#               define KERNEL_FILE "/vmunix"
554953c684bSmrg#              endif /* BSD */
555953c684bSmrg#             endif /* SYSV */
556953c684bSmrg#            endif /* SVR4 */
557953c684bSmrg#           endif /* KERNEL_FILE */
558953c684bSmrg#          endif /* KERNEL_FILE */
559953c684bSmrg
560953c684bSmrg
561953c684bSmrg#          ifndef KERNEL_LOAD_VARIABLE
562953c684bSmrg#           if defined(BSD) && (BSD >= 199103)
563953c684bSmrg#            define KERNEL_LOAD_VARIABLE "_averunnable"
564953c684bSmrg#           endif /* BSD >= 199103 */
565953c684bSmrg
566953c684bSmrg#           ifdef hpux
567953c684bSmrg#            ifdef __hp9000s800
568953c684bSmrg#             define KERNEL_LOAD_VARIABLE "avenrun"
569953c684bSmrg#            endif /* hp9000s800 */
570953c684bSmrg#           endif /* hpux */
571953c684bSmrg
572953c684bSmrg#           ifdef sgi
573fd0c672fSmrg#	 define KERNEL_LOAD_VARIABLE "avenrun"
574953c684bSmrg#           endif /* sgi */
575fd0c672fSmrg
576953c684bSmrg#          endif /* KERNEL_LOAD_VARIABLE */
577fd0c672fSmrg
578fd0c672fSmrg/*
579fd0c672fSmrg * provide default for everyone else
580fd0c672fSmrg */
581fd0c672fSmrg
582953c684bSmrg#          ifndef KERNEL_LOAD_VARIABLE
583953c684bSmrg#           ifdef USG
584953c684bSmrg#            define KERNEL_LOAD_VARIABLE "sysinfo"
585953c684bSmrg#            define SYSINFO
586953c684bSmrg#           else
587953c684bSmrg#            ifdef SVR4
588953c684bSmrg#             define KERNEL_LOAD_VARIABLE "avenrun"
589953c684bSmrg#            else
590953c684bSmrg#             define KERNEL_LOAD_VARIABLE "_avenrun"
591953c684bSmrg#            endif
592953c684bSmrg#           endif
593953c684bSmrg#          endif /* KERNEL_LOAD_VARIABLE */
594fd0c672fSmrg
595fd0c672fSmrgstatic struct nlist namelist[] = {	    /* namelist for vmunix grubbing */
596953c684bSmrg#          define LOADAV 0
597fd0c672fSmrg    {KERNEL_LOAD_VARIABLE},
598fd0c672fSmrg    {0}
599fd0c672fSmrg};
600fd0c672fSmrg
601fd0c672fSmrgstatic int kmem;
602fd0c672fSmrgstatic long loadavg_seek;
603fd0c672fSmrg
604fd0c672fSmrgvoid InitLoadPoint()
605fd0c672fSmrg{
606953c684bSmrg#          if !defined(SVR4) && !defined(sgi) && !defined(AIXV5) && !(BSD >= 199103) && !defined(__APPLE__)
607fd0c672fSmrg    extern void nlist();
608953c684bSmrg#          endif
609fd0c672fSmrg
610fd0c672fSmrg    nlist( KERNEL_FILE, namelist);
611fd0c672fSmrg    /*
612fd0c672fSmrg     * Some systems appear to set only one of these to Zero if the entry could
613fd0c672fSmrg     * not be found, I hope no_one returns Zero as a good value, or bad things
614fd0c672fSmrg     * will happen to you.  (I have a hard time believing the value will
615fd0c672fSmrg     * ever really be zero anyway).   CDP 5/17/89.
616fd0c672fSmrg     */
617fd0c672fSmrg    if (namelist[LOADAV].n_type == 0 ||
618fd0c672fSmrg	namelist[LOADAV].n_value == 0) {
619fd0c672fSmrg	xload_error("cannot get name list from", KERNEL_FILE);
620fd0c672fSmrg	exit(-1);
621fd0c672fSmrg    }
622fd0c672fSmrg    loadavg_seek = namelist[LOADAV].n_value;
623fd0c672fSmrg    kmem = open(KMEM_FILE, O_RDONLY);
624fd0c672fSmrg    if (kmem < 0) xload_error("cannot open", KMEM_FILE);
625fd0c672fSmrg}
626fd0c672fSmrg
627fd0c672fSmrg/* ARGSUSED */
628fd0c672fSmrgvoid GetLoadPoint( w, closure, call_data )
629fd0c672fSmrg     Widget	w;		/* unused */
630fd0c672fSmrg     XtPointer	closure;	/* unused */
631fd0c672fSmrg     XtPointer	call_data;	/* pointer to (double) return value */
632fd0c672fSmrg{
633fd0c672fSmrg  	double *loadavg = (double *)call_data;
634fd0c672fSmrg
635fd0c672fSmrg	(void) lseek(kmem, loadavg_seek, 0);
636fd0c672fSmrg
637953c684bSmrg#          if defined(SVR4) || defined(sgi) || (BSD >= 199103)
638fd0c672fSmrg	{
639fd0c672fSmrg		long temp;
640fd0c672fSmrg		(void) read(kmem, (char *)&temp, sizeof(long));
641fd0c672fSmrg		*loadavg = (double)temp/FSCALE;
642fd0c672fSmrg	}
643953c684bSmrg#          else /* else not SVR4 or sgi or BSD */
644fd0c672fSmrg	(void) read(kmem, (char *)loadavg, sizeof(double));
645953c684bSmrg#          endif /* SVR4 or ... else */
646fd0c672fSmrg	return;
647fd0c672fSmrg}
648953c684bSmrg#         endif /* __bsdi__ else */
649953c684bSmrg#        endif /* __QNXNTO__ else */
650953c684bSmrg#       endif /* __osf__ else */
651953c684bSmrg#      endif /* LOADSTUB else */
652953c684bSmrg#     endif /* __APPLE__ else */
653953c684bSmrg#    endif /* __GNU__ else */
654953c684bSmrg#   endif /* linux else */
655953c684bSmrg#  endif /* SYSV && i386 else */
656953c684bSmrg# endif /* HAVE_GETLOADAVG else */
657fd0c672fSmrg
658a8bb11d0Smrgstatic void xload_error(const char *str1, const char *str2)
659fd0c672fSmrg{
660fd0c672fSmrg    (void) fprintf(stderr,"xload: %s %s\n", str1, str2);
661953c684bSmrg# ifdef __bsdi__
662fd0c672fSmrg    if (kd)
663fd0c672fSmrg	kvm_close(kd);
664953c684bSmrg# endif
665fd0c672fSmrg    exit(-1);
666fd0c672fSmrg}
667fd0c672fSmrg
668fd0c672fSmrg#endif /* END of __CYGWIN__ */
669