added files
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / ucd-snmp / vmstat_hpux.c
1 /*
2  *  vmstat_hpux.c
3  *  UCD SNMP module for systemStats section of UCD-SNMP-MIB for HPUX 10.x/11.x
4  */
5
6 /*
7  * To make lint skip the debug code and stop complaining 
8  */
9 #ifdef __lint
10 #define SNMP_NO_DEBUGGING 1
11 #endif
12
13 /*
14  * Includes start here 
15  */
16
17 /*
18  * UCD-SNMP config details 
19  */
20 #include <net-snmp/net-snmp-config.h>
21
22 /*
23  * Standard includes 
24  */
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/time.h>
29 #include <string.h>
30
31 /*
32  * pstat and sysinfo structs 
33  */
34 #include <sys/pstat.h>
35 #include <sys/dk.h>
36
37
38 /*
39  * Includes needed for all modules 
40  */
41 #include <net-snmp/net-snmp-includes.h>
42 #include <net-snmp/agent/net-snmp-agent-includes.h>
43 #include "mibdefs.h"
44
45 /*
46  * Utility functions for UCD-SNMP 
47  */
48 #include "util_funcs.h"
49
50 /*
51  * Header file for this module 
52  */
53 #include "vmstat.h"
54 #include "vmstat_hpux.h"
55
56 /*
57  * Includes end here 
58  */
59
60
61 /*
62  * Global structures start here 
63  */
64
65 /*
66  * A structure to save data gathered from the kernel pstat interface to.
67  * CPUSTATES are defined as (see sys/dk.h):
68  * #define CPUSTATES       9       -- number of CPU states
69  * #define CP_USER         0       -- user mode of USER process
70  * #define CP_NICE         1       -- user mode of USER process at nice priority
71  * #define CP_SYS          2       -- kernel mode of USER process
72  * #define CP_IDLE         3       -- IDLE mode
73  * #define CP_WAIT         4       
74  * #define CP_BLOCK        5       -- time blocked on a spinlock
75  * #define CP_SWAIT        6       -- time blocked on the kernel semaphore
76  * #define CP_INTR         7       -- INTERRUPT mode
77  * #define CP_SSYS         8       -- kernel mode of KERNEL process
78  */
79
80 struct cpu_stat_snapshot {
81     time_t          css_time;
82     unsigned int    css_cpus;
83     unsigned long long css_swapin;
84     unsigned long long css_swapout;
85     unsigned long long css_blocks_read;
86     unsigned long long css_blocks_write;
87     unsigned long long css_interrupts;
88     unsigned long long css_context_sw;
89     unsigned long long css_cpu[CPUSTATES];
90 };
91
92 /*
93  * Define a structure to hold kernel static information 
94  */
95 struct pst_static pst;
96
97 /*
98  * Global structures end here 
99  */
100
101 /*
102  * Global variables start here 
103  */
104
105 /*
106  * Variables for the calculated values, filled in update_stats    
107  */
108 /*
109  * Need to be global since we need them in more than one function 
110  */
111 static unsigned long swapin;
112 static unsigned long swapout;
113 static unsigned long blocks_read;
114 static unsigned long blocks_write;
115 static unsigned long interrupts;
116 static unsigned long context_sw;
117
118 /*
119  * Since MIB wants CPU_SYSTEM, which is CP_SYS + CP_WAIT (see sys/dk.h) 
120  */
121 static long     cpu_perc[CPUSTATES + 1];
122
123 /*
124  * How many snapshots we have already taken, needed for the first 
125  */
126 /*
127  * POLL_INTERVAL * POLL_VALUES seconds of agent running 
128  */
129 static unsigned int number_of_snapshots;
130
131 /*
132  * The place to store the snapshots of system data in 
133  */
134 static struct cpu_stat_snapshot snapshot[POLL_VALUES + 1];
135
136 /*
137  * And one for the raw counters, which we fill when the raw values are 
138  */
139 /*
140  * requested, as opposed to the absolute values, which are taken every 
141  */
142 /*
143  * POLL_INTERVAL seconds and calculated over POLL_INTERVAL * POLL_VALUES time 
144  */
145 static struct cpu_stat_snapshot raw_values;
146
147 /*
148  * Global variables end here 
149  */
150
151
152 /*
153  * Functions start here 
154  */
155
156 /*
157  * Function prototype 
158  */
159 static void     update_stats(unsigned int registrationNumber,
160                              void *clientarg);
161 static int      take_snapshot(struct cpu_stat_snapshot *css);
162
163 /*
164  * init_vmstat_hpux starts here 
165  */
166 /*
167  * Init function for this module, from prototype 
168  */
169 /*
170  * Defines variables handled by this module, defines root OID for 
171  */
172 /*
173  * this module and registers it with the agent 
174  */
175
176 FindVarMethod var_extensible_vmstat;
177
178 void
179 init_vmstat_hpux(void)
180 {
181
182     /*
183      * Which variables do we service ? 
184      */
185     struct variable2 extensible_vmstat_variables[] = {
186         {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
187          {MIBINDEX}},
188         {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_vmstat, 1,
189          {ERRORNAME}},
190         {SWAPIN, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {SWAPIN}},
191         {SWAPOUT, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {SWAPOUT}},
192         {IOSENT, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {IOSENT}},
193         {IORECEIVE, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
194          {IORECEIVE}},
195         {SYSINTERRUPTS, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
196          {SYSINTERRUPTS}},
197         {SYSCONTEXT, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
198          {SYSCONTEXT}},
199         {CPUUSER, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {CPUUSER}},
200         {CPUSYSTEM, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
201          {CPUSYSTEM}},
202         {CPUIDLE, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {CPUIDLE}},
203         {CPURAWUSER, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
204          {CPURAWUSER}},
205         {CPURAWNICE, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
206          {CPURAWNICE}},
207         {CPURAWSYSTEM, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
208          {CPURAWSYSTEM}},
209         {CPURAWIDLE, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
210          {CPURAWIDLE}},
211         {CPURAWWAIT, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
212          {CPURAWWAIT}},
213         {CPURAWKERNEL, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
214          {CPURAWKERNEL}},
215         {IORAWSENT, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
216          {IORAWSENT}},
217         {IORAWRECEIVE, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
218          {IORAWRECEIVE}},
219         /*
220          * Future use: 
221          */
222         /*
223          * {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {ERRORFLAG }},
224          * {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_vmstat, 1, {ERRORMSG }}
225          */
226     };
227
228     /*
229      * Define the OID pointer to the top of the mib tree that we're 
230      */
231     /*
232      * registering underneath 
233      */
234     oid             vmstat_variables_oid[] = { UCDAVIS_MIB, 11 };
235
236     /*
237      * register ourselves with the agent to handle our mib tree 
238      */
239     /*
240      * LINTED Trust me, I know what I'm doing 
241      */
242     REGISTER_MIB("ucd-snmp/vmstat", extensible_vmstat_variables, variable2,
243                  vmstat_variables_oid);
244
245     /*
246      * Start with some useful data 
247      */
248     update_stats(0, NULL);
249
250     /*
251      * update_stats is run every POLL_INTERVAL seconds using this routine 
252      */
253     /*
254      * (see 'man snmp_alarm') 
255      */
256     /*
257      * This is only executed once to get some useful data in the beginning 
258      */
259     if (snmp_alarm_register(5, NULL, update_stats, NULL) == 0) {
260         snmp_log(LOG_WARNING,
261                  "vmstat_hpux (init): snmp_alarm_register failed.\n");
262     }
263     /*
264      * This is the one that runs update_stats every POLL_INTERVAL seconds 
265      */
266     if (snmp_alarm_register(POLL_INTERVAL, SA_REPEAT, update_stats, NULL)
267         == 0) {
268         snmp_log(LOG_ERR,
269                  "vmstat_hpux (init): snmp_alarm_register failed, cannot service requests.\n");
270     }
271
272 }                               /* init_vmstat_hpux ends here */
273
274 /*
275  * Data collection function take_snapshot starts here 
276  */
277 /*
278  * Get data from kernel and save into the snapshot strutcs 
279  */
280 /*
281  * Argument is the snapshot struct to save to. Global anyway, but looks nicer 
282  */
283 static int
284 take_snapshot(struct cpu_stat_snapshot *css)
285 {
286     /*
287      * Variables start here 
288      */
289
290     struct pst_dynamic psd;
291     struct pst_processor *psp;
292     struct pst_vminfo psv;
293
294     /*
295      * time counter 
296      */
297     time_t          current_time;
298
299     /*
300      * The usual stuff to count on, err, by 
301      */
302     int             i;
303
304     /*
305      * Variables end here 
306      */
307
308     /*
309      * Function starts here 
310      */
311
312     /*
313      * Get time 
314      */
315     time(&current_time);
316
317     /*
318      * If we have just gotten the data, return the values from last run (skip if-clause) 
319      */
320     /*
321      * This happens on a snmpwalk request.  No need to read the pstat again 
322      */
323     /*
324      * if we just did it less than 2 seconds ago 
325      */
326     /*
327      * Jumps into if-clause either when snapshot is empty or when too old 
328      */
329
330     if ((css->css_time == 0) || (current_time > css->css_time + 2)) {
331         /*
332          * Make sure we clean up before we put new data into snapshot 
333          */
334         memset(css, 0, sizeof *css);
335
336         /*
337          * Update timer 
338          */
339         css->css_time = current_time;
340
341         if (pstat_getdynamic(&psd, sizeof(psd), (size_t) 1, 0) != -1) {
342             css->css_cpus = psd.psd_proc_cnt;
343             DEBUGMSGTL(("take_snapshot", "*** Number of CPUs: %d\n",
344                         css->css_cpus));
345
346             /*
347              * We need a for-loop for the CPU values 
348              */
349             for (i = 0; i < CPUSTATES; i++) {
350                 css->css_cpu[i] = (unsigned long long) psd.psd_cpu_time[i];
351                 DEBUGMSGTL(("take_snapshot",
352                             "*** Time for CPU state %d: %d\n", i,
353                             psd.psd_cpu_time[i]));
354             }
355             psp =
356                 (struct pst_processor *) malloc(css->css_cpus *
357                                                 sizeof(*psp));
358             if (pstat_getprocessor(psp, sizeof(*psp), css->css_cpus, 0) !=
359                 -1) {
360                 int             i;
361                 for (i = 0; i < css->css_cpus; i++) {
362                     css->css_blocks_read = psp[i].psp_phread;
363                     css->css_blocks_write = psp[i].psp_phwrite;
364                 }
365             } else
366                 snmp_log(LOG_ERR,
367                          "vmstat_hpux (take_snapshot): pstat_getprocessor failed!\n");
368         } else
369             snmp_log(LOG_ERR,
370                      "vmstat_hpux (take_snapshot): pstat_getdynamic failed!\n");
371
372         if (pstat_getvminfo(&psv, sizeof(psv), (size_t) 1, 0) != -1) {
373             css->css_swapin = psv.psv_sswpin;
374             css->css_swapout = psv.psv_sswpout;
375             css->css_interrupts = psv.psv_sintr;
376             css->css_context_sw = psv.psv_sswtch;
377         } else
378             snmp_log(LOG_ERR,
379                      "vmstat_hpux (take_snapshot): pstat_getvminfo failed!\n");
380
381     }
382
383     /*
384      * All engines running at warp speed, no problems (if there are any engines, that is) 
385      */
386     return (css->css_cpus > 0 ? 0 : -1);
387 }                               /* take_snapshot ends here */
388
389 /*
390  * This gets called every POLL_INTERVAL seconds to update the snapshots.  It takes a new snapshot and 
391  */
392 /*
393  * drops the oldest one.  This way we move the time window so we always take the values over 
394  */
395 /*
396  * POLL_INTERVAL * POLL_VALUES seconds and update the data used every POLL_INTERVAL seconds 
397  */
398 /*
399  * The alarm timer is in the init function of this module (snmp_alarm_register) 
400  */
401 /*
402  * ARGSUSED0 
403  */
404 static void
405 update_stats(unsigned int registrationNumber, void *clientarg)
406 {
407     /*
408      * The time between the samples we compare 
409      */
410     time_t          time_diff;
411
412     /*
413      * Easier to use these than the snapshots, short hand pointers 
414      */
415     struct cpu_stat_snapshot *css_old, *css_new;
416
417     /*
418      * The usual stuff to count on, err, by 
419      */
420     int             i;
421
422     /*
423      * The sum of the CPU ticks that have passed on the different CPU states, so we can calculate 
424      */
425     /*
426      * the percentages of each state 
427      */
428     unsigned long long cpu_sum = 0;
429
430     DEBUGMSGTL(("ucd-snmp/vmstat_hpux.c:update_stats",
431                 "updating stats\n"));
432
433     /*
434      * Take the current snapshot 
435      */
436     if (take_snapshot(&snapshot[0]) == -1) {
437         snmp_log(LOG_WARNING,
438                  "vmstat_hpux (update_stats): Something went wrong with take_snapshot.\n");
439         return;
440     }
441
442     /*
443      * Do we have some data we can use ?  An issue right after the start of the agent 
444      */
445     if (number_of_snapshots > 0) {
446         /*
447          * Huh, the number of CPUs changed during run time.  That is indeed s.th. worth noting, we 
448          */
449         /*
450          * output a humorous (more or less) syslog message and need to retake the snapshots 
451          */
452         if (snapshot[0].css_cpus != snapshot[1].css_cpus) {
453             if (snapshot[0].css_cpus > snapshot[1].css_cpus) {
454                 snmp_log(LOG_NOTICE,
455                          "vmstat_hpux (update_stats): Cool ! Number of CPUs increased, must be hot-pluggable.\n");
456             } else {
457                 snmp_log(LOG_NOTICE,
458                          "vmstat_hpux (update_stats): Lost at least one CPU, RIP.\n");
459             }
460             /*
461              * Make all snapshots but the current one invalid 
462              */
463             number_of_snapshots = 1;
464             /*
465              * Move the current one in the "first" [1] slot 
466              */
467             memmove(&snapshot[1], &snapshot[0], sizeof snapshot[0]);
468             /*
469              * Erase the current one 
470              */
471             memset(&snapshot[0], 0, sizeof snapshot[0]);
472             /*
473              * Try to get a new snapshot in five seconds so we can return s.th. useful 
474              */
475             if (snmp_alarm_register(5, NULL, update_stats, NULL) == 0) {
476                 snmp_log(LOG_WARNING,
477                          "vmstat_hpux (update_stats): snmp_alarm_register failed.\n");
478             }
479             return;
480         }
481
482         /*
483          * Short hand pointers 
484          */
485         css_new = &snapshot[0];
486         css_old = &snapshot[number_of_snapshots];
487
488         /*
489          * How much time has passed between the snapshots we get the values from ? 
490          */
491         time_diff =
492             (snapshot[0].css_time -
493              snapshot[number_of_snapshots].css_time);
494
495         DEBUGMSGTL(("ucd-snmp/vmstat_hpux.c:update_stats",
496                     "time_diff: %lld\n", time_diff));
497
498         /*
499          * swapin and swapout are in pages, MIB wants kB/s,so we just need to get kB and seconds 
500          */
501         /*
502          * For the others we need to get value per second 
503          */
504         /*
505          * Retreive static information to obtain memory page_size 
506          */
507         if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) == -1) {
508             snmp_log(LOG_ERR, "vmstat_hpux: pstat_getstatic failed!\n");
509         }
510
511         /*
512          * LINTED cast needed, really 
513          */
514         swapin =
515             (unsigned int) ((css_new->css_swapin - css_old->css_swapin) *
516                             pst.page_size / 1024 / time_diff);
517         /*
518          * LINTED cast needed, really 
519          */
520         swapout =
521             (unsigned int) ((css_new->css_swapout - css_old->css_swapout) *
522                             pst.page_size / 1024 / time_diff);
523         /*
524          * LINTED cast needed, really 
525          */
526         blocks_read =
527             (unsigned
528              int) ((css_new->css_blocks_read -
529                     css_old->css_blocks_read) / time_diff);
530         /*
531          * LINTED cast needed, really 
532          */
533         blocks_write =
534             (unsigned
535              int) ((css_new->css_blocks_write -
536                     css_old->css_blocks_write) / time_diff);
537         /*
538          * LINTED cast needed, really 
539          */
540         interrupts =
541             (unsigned
542              int) ((css_new->css_interrupts -
543                     css_old->css_interrupts) / time_diff);
544         /*
545          * LINTED cast needed, really 
546          */
547         context_sw =
548             (unsigned
549              int) ((css_new->css_context_sw -
550                     css_old->css_context_sw) / time_diff);
551
552         /*
553          * Loop thru all the CPUSTATES and get the differences 
554          */
555         for (i = 0; i < CPUSTATES; i++) {
556             cpu_sum += (css_new->css_cpu[i] - css_old->css_cpu[i]);
557         }
558
559         /*
560          * Now calculate the absolute percentage values 
561          */
562         /*
563          * Looks somewhat complicated sometimes but tries to get around using floats to increase speed 
564          */
565         for (i = 0; i < CPUSTATES; i++) {
566             /*
567              * Since we don't return fractions we use + 0.5 to get between 99 and 101 percent adding the values 
568              */
569             /*
570              * together, otherwise we would get less than 100 most of the time 
571              */
572             /*
573              * LINTED has to be 'long' 
574              */
575             cpu_perc[i] =
576                 (long) (((css_new->css_cpu[i] -
577                           css_old->css_cpu[i]) * 100 +
578                          (cpu_sum / 2)) / cpu_sum);
579         }
580
581         /*
582          * As said before, MIB wants CPU_SYSTEM which is CP_SYS + CP_WAIT 
583          */
584         /*
585          * LINTED has to be 'long' 
586          */
587         cpu_perc[CPU_SYSTEM] =
588             (long) ((((css_new->css_cpu[CP_SYS] - css_old->css_cpu[CP_SYS])
589                       + (css_new->css_cpu[CP_WAIT] -
590                          css_old->css_cpu[CP_WAIT]))
591                      * 100 + (cpu_sum / 2)) / cpu_sum);
592     }
593
594     /*
595      * Make the current one the first one and move the whole thing one place down 
596      */
597     memmove(&snapshot[1], &snapshot[0],
598             (size_t) (((char *) &snapshot[POLL_VALUES]) -
599                       ((char *) &snapshot[0])));
600
601     /*
602      * Erase the current one 
603      */
604     memset(&snapshot[0], 0, sizeof snapshot[0]);
605
606     /*
607      * Only important on start up, we keep track of how many snapshots we have taken so far 
608      */
609     if (number_of_snapshots < POLL_VALUES) {
610         number_of_snapshots++;
611     }
612 }                               /* update_stats ends here */
613
614 /*
615  * *var_extensible_vmstat starts here 
616  */
617 /*
618  * The guts of the module, this routine gets called to service a request 
619  */
620 unsigned char *
621 var_extensible_vmstat(struct variable *vp,
622                       oid * name,
623                       size_t * length,
624                       int exact,
625                       size_t * var_len, WriteMethod ** write_method)
626 {
627     /*
628      * Needed for returning the values 
629      */
630     static long     long_ret;
631     static char     errmsg[300];
632
633     /*
634      * set to 0 as default 
635      */
636     long_ret = 0;
637
638     /*
639      * generic check whether the options passed make sense and whether the 
640      */
641     /*
642      * right variable is requested 
643      */
644     if (header_generic(vp, name, length, exact, var_len, write_method) !=
645         MATCH_SUCCEEDED) {
646         return (NULL);
647     }
648
649     /*
650      * The function that actually returns s.th. 
651      */
652     switch (vp->magic) {
653     case MIBINDEX:
654         long_ret = 1;
655         return ((u_char *) (&long_ret));
656     case ERRORNAME:            /* dummy name */
657         sprintf(errmsg, "systemStats");
658         *var_len = strlen(errmsg);
659         return ((u_char *) (errmsg));
660     case SWAPIN:
661         return ((u_char *) (&swapin));
662     case SWAPOUT:
663         return ((u_char *) (&swapout));
664     case IOSENT:
665         return ((u_char *) (&blocks_write));
666     case IORECEIVE:
667         return ((u_char *) (&blocks_read));
668     case SYSINTERRUPTS:
669         return ((u_char *) (&interrupts));
670     case SYSCONTEXT:
671         return ((u_char *) (&context_sw));
672     case CPUUSER:
673         return ((u_char *) (&cpu_perc[CP_USER]));
674     case CPUSYSTEM:
675         return ((u_char *) (&cpu_perc[CPU_SYSTEM]));
676     case CPUIDLE:
677         return ((u_char *) (&cpu_perc[CP_IDLE]));
678     case CPURAWUSER:
679         take_snapshot(&raw_values);
680         /*
681          * LINTED has to be 'long' 
682          */
683         long_ret =
684             (long) (raw_values.css_cpu[CP_USER] / raw_values.css_cpus);
685         return ((u_char *) (&long_ret));
686     case CPURAWNICE:
687         take_snapshot(&raw_values);
688         /*
689          * LINTED has to be 'long' 
690          */
691         long_ret =
692             (long) (raw_values.css_cpu[CP_NICE] / raw_values.css_cpus);
693         return ((u_char *) (&long_ret));
694     case CPURAWSYSTEM:
695         take_snapshot(&raw_values);
696         /*
697          * LINTED has to be 'long' 
698          */
699         long_ret =
700             (long) ((raw_values.css_cpu[CP_SYS] +
701                      raw_values.css_cpu[CP_WAIT]) / raw_values.css_cpus);
702         return ((u_char *) (&long_ret));
703     case CPURAWIDLE:
704         take_snapshot(&raw_values);
705         /*
706          * LINTED has to be 'long' 
707          */
708         long_ret =
709             (long) (raw_values.css_cpu[CP_IDLE] / raw_values.css_cpus);
710         return ((u_char *) (&long_ret));
711     case CPURAWWAIT:
712         take_snapshot(&raw_values);
713         /*
714          * LINTED has to be 'long' 
715          */
716         long_ret =
717             (long) (raw_values.css_cpu[CP_WAIT] / raw_values.css_cpus);
718         return ((u_char *) (&long_ret));
719     case CPURAWKERNEL:
720         take_snapshot(&raw_values);
721         /*
722          * LINTED has to be 'long' 
723          */
724         long_ret =
725             (long) (raw_values.css_cpu[CP_SYS] / raw_values.css_cpus);
726         return ((u_char *) (&long_ret));
727     case IORAWSENT:
728         take_snapshot(&raw_values);
729         /*
730          * LINTED has to be 'long' 
731          */
732         long_ret = (long) (raw_values.css_blocks_write);
733         return ((u_char *) (&long_ret));
734     case IORAWRECEIVE:
735         take_snapshot(&raw_values);
736         /*
737          * LINTED has to be 'long' 
738          */
739         long_ret = (long) (raw_values.css_blocks_read);
740         return ((u_char *) (&long_ret));
741
742         /*
743          * reserved for future use 
744          */
745         /*
746          * case ERRORFLAG:
747          * return((u_char *) (&long_ret));
748          * case ERRORMSG:
749          * return((u_char *) (&long_ret));
750          */
751     default:
752         snmp_log(LOG_ERR,
753                  "vmstat_hpux: Error in request, no match found.\n");
754     }
755     return (NULL);
756 }                               /* *var_extensible_vmstat ends here */
757
758 /*
759  * Functions end here 
760  */
761
762 /*
763  * Program ends here 
764  */