Rename top(1) to mtop(1), import NetBSD top(1)
[minix3.git] / external / bsd / top / dist / machine / m_macosx.c
blob88e4b09e63434a8d24799f4348a191703de1dc53
1 /*
2 * Copyright (c) 1984 through 2008, William LeFebvre
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
16 * * Neither the name of William LeFebvre nor the names of other
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * m_macosx.c
36 * AUTHOR: Andrew S. Townley
37 * based on m_bsd44.c and m_next32.c
38 * by Christos Zoulas and Tim Pugh
39 * CREATED: Tue Aug 11 01:51:35 CDT 1998
40 * SYNOPSIS: MacOS X Server (Rhapsody Developer Release 2)
41 * DESCRIPTION:
42 * MacOS X Server (Rhapsody Developer Release 2)
44 * CFLAGS: -DHAVE_STRERROR
45 * TERMCAP: none
46 * MATH: none
50 * normal stuff
53 #include "config.h"
55 #include <stdio.h>
56 #include <stdarg.h>
57 #include <errno.h>
58 #include "os.h"
59 #include "top.h"
60 #include "machine.h"
61 #include "utils.h"
64 * MacOS kernel stuff
67 #include <kvm.h>
68 #include <fcntl.h>
69 #include <sys/dkstat.h>
70 #include <sys/sysctl.h>
71 #include <mach/message.h>
72 #include <mach/vm_statistics.h>
73 #include <mach/mach.h>
74 #include <mach/host_info.h>
76 #define VMUNIX "/mach_kernel"
77 #define MEM "/dev/mem"
78 #define SWAP NULL
80 #define NUM_AVERAGES 3
81 #define LOG1024 10
83 #define PP(pp, field) ((pp)->kp_proc . field)
84 #define EP(pp, field) ((pp)->kp_eproc . field)
85 #define VP(pp, field) ((pp)->kp_eproc.e_vm . field)
86 #define MPP(mp, field) (PP((mp)->kproc, field))
87 #define MEP(mp, field) (EP((mp)->kproc, field))
88 #define MVP(mp, field) (VP((mp)->kproc, field))
89 #define TP(mp, field) ((mp)->task_info . field)
90 #define RP(mp, field) ((mp)->thread_summary . field)
92 /* define what weighted cpu is */
93 #define weighted_cpu(pct, s) (s == 0 ? 0.0 : \
94 ((pct) / (1.0 - exp(s * logcpu))))
96 /* what we consider to be process size: */
97 #ifdef notdef
98 #define PROCSIZE(pp) (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize))
99 #endif
100 #define PROCSIZE(pp) (EP(pp, e_xsize))
101 #define TASKSIZE(t) (TP(t, virtual_size) + TP(t, resident_size))
103 /* what we consider to be resident set size: */
104 #ifdef notdef
105 #define RSSIZE(pp) (MVP((pp), vm_rssize))
106 #endif
107 #define RSSIZE(pp) (MEP((pp), e_xrssize))
109 #define pctdouble(p) ((double)(p) / FSCALE)
112 * globals
115 static kvm_t *kd = NULL;
116 static int nproc;
117 static int onproc = -1;
118 static int pref_len;
119 static int maxmem;
120 static char fmt[MAX_COLS];
121 static double logcpu = 1.0;
123 /* process array stuff */
125 static struct kinfo_proc *kproc_list = NULL;
126 static struct macos_proc *proc_list = NULL;
127 static struct macos_proc **proc_ref = NULL;
128 static int process_states[7];
129 static struct handle handle;
132 * The mach information hopefully will not be necessary
133 * when the kvm_* interfaces are supported completely.
135 * Since we're only concerned with task and thread info
136 * for 'interesting' processes, we're going to only allocate
137 * as many task and thread structures as needed.
140 static struct task_basic_info *task_list = NULL;
142 /* memory statistics */
144 static int pageshift = 0;
145 static int pagesize = 0;
146 #define pagetok(size) ((size) << pageshift)
148 static int swappgsin = -1;
149 static int swappgsout = -1;
150 static vm_statistics_data_t vm_stats;
151 static long memory_stats[7];
153 /* CPU state percentages */
155 host_cpu_load_info_data_t cpuload;
157 static long cp_time[CPU_STATE_MAX];
158 static long cp_old[CPU_STATE_MAX];
159 static long cp_diff[CPU_STATE_MAX];
160 static int cpu_states[CPU_STATE_MAX];
163 * types
166 typedef long pctcpu;
168 //struct statics
170 // char **procstate_names;
171 // char **cpustate_names;
172 // char **memory_names;
173 // char **order_names;
174 //};
176 //struct system_info
178 // int last_pid;
179 // double load_avg[NUM_AVERAGES];
180 // int p_total; /* total # of processes */
181 // int p_active; /* number processes considered active */
182 // int *procstates;
183 // int *cpustates;
184 // int *memory;
185 //};
187 //struct process_select
189 // int idle; /* show idle processes */
190 // int system; /* show system processes */
191 // int uid; /* show only this uid (unless -1) */
192 // char *command; /* only this command (unless NULL) */
193 //};
196 * We need to declare a hybrid structure which will store all
197 * of the stuff we care about for each process.
200 struct macos_proc
202 struct kinfo_proc *kproc;
203 task_t the_task;
204 struct task_basic_info task_info;
205 unsigned int thread_count;
206 struct thread_basic_info thread_summary;
209 struct handle
211 struct macos_proc **next_proc;
212 int remaining;
215 static char header[] =
216 " PID X PRI THRD SIZE RES STATE TIME MEM CPU COMMAND";
217 /* 0123456 -- field to fill in starts at header+6 */
218 #define UNAME_START 6
220 #define Proc_format \
221 "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %.16s"
224 int proc_compare(const void *, const void *);
228 * puke()
230 * This function is used to report errors to stderr.
233 static void puke(const char* fmt, ...)
235 va_list args;
236 va_start(args, fmt);
237 vfprintf(stderr, fmt, args);
238 va_end(args);
240 fputc('\n', stderr);
241 fflush(stderr);
245 * kread()
247 * This function is a wrapper for the kvm_read() function
248 * with the addition of a message parameter per kvm_open().
250 * All other behavior is per kvm_read except the error reporting.
253 static ssize_t kread(u_long addr, void *buf,
254 size_t nbytes, const char *errstr)
256 ssize_t s = 0;
258 s = kvm_read(kd, addr, buf, nbytes);
259 if(s == -1)
261 puke("error: kvm_read() failed for '%s' (%s)\n",
262 errstr, strerror(errno));
265 return s;
269 * prototypes for functions which top needs
272 char *printable();
275 * definitions for offsets
278 #define X_NPROC 0
279 #define X_HZ 1
280 #define X_MAXMEM 2
282 #define NLIST_LAST 3
284 static struct nlist nlst[] =
286 { "_maxproc" }, /* 0 *** maximum processes */
287 { "_hz" }, /* 1 */
288 { "_mem_size" }, /* 2 */
289 { 0 }
292 static char *procstates[] =
295 " starting, ",
296 " running, ",
297 " sleeping, ",
298 " stopped, ",
299 " zombie, ",
300 " swapped ",
301 NULL
304 static char *cpustates[] =
306 "user",
307 "system",
308 "idle",
309 "nice",
310 NULL
313 static char *state_abbrev[] =
316 "start",
317 "run\0\0\0",
318 "sleep",
319 "stop",
320 "zomb"
323 static char *mach_state[] =
326 "R",
327 "T",
328 "S",
329 "U",
333 static char *thread_state[] =
336 "run\0\0\0",
337 "stop",
338 "wait",
339 "uwait",
340 "halted",
343 static char *flags_state[] =
346 "W",
350 static char *memnames[] =
352 "K Tot, ",
353 "K Free, ",
354 "K Act, ",
355 "K Inact, ",
356 "K Wired, ",
357 "K in, ",
358 "K out ",
359 NULL
363 * format_header()
365 * This function is used to add the username into the
366 * header information.
369 char *format_header(register char *uname_field)
371 register char *ptr;
373 ptr = header + UNAME_START;
374 while(*uname_field != '\0')
375 *ptr++ = *uname_field++;
377 return(header);
381 * format_next_process()
383 * This function actuall is responsible for the formatting of
384 * each row which is displayed.
387 char *format_next_process(caddr_t handle, char *(*getuserid)())
389 register struct macos_proc *pp;
390 register long cputime;
391 register double pct;
392 register int vsize;
393 register int rsize;
394 struct handle *hp;
397 * we need to keep track of the next proc structure.
400 hp = (struct handle*)handle;
401 pp = *(hp->next_proc++);
402 hp->remaining--;
405 * get the process structure and take care of the cputime
408 if((MPP(pp, p_flag) & P_INMEM) == 0)
410 /* we want to print swapped processes as <pname> */
411 char *comm = MPP(pp, p_comm);
412 #define COMSIZ sizeof(MPP(pp, p_comm))
413 char buf[COMSIZ];
414 strncpy(buf, comm, COMSIZ);
415 comm[0] = '<';
416 strncpy(&comm[1], buf, COMSIZ - 2);
417 comm[COMSIZ - 2] = '\0';
418 strncat(comm, ">", COMSIZ - 1);
419 comm[COMSIZ - 1] = '\0';
423 * count the cpu time, but ignore the interrupts
425 * At the present time (DR2 8/1998), MacOS X doesn't
426 * correctly report this information through the
427 * kinfo_proc structure. We need to get it from the
428 * task threads.
430 * cputime = PP(pp, p_rtime).tv_sec;
433 cputime = RP(pp, user_time).seconds + RP(pp, system_time).seconds;
436 * calculate the base cpu percentages
438 * Again, at the present time, MacOS X doesn't report
439 * this information through the kinfo_proc. We need
440 * to talk to the threads.
443 // pct = pctdouble(PP(pp, p_pctcpu));
444 pct = (double)(RP(pp, cpu_usage))/TH_USAGE_SCALE;
447 * format the entry
451 * In the final version, I would expect this to work correctly,
452 * but it seems that not all of the fields in the proc
453 * structure are being used.
455 * For now, we'll attempt to get some of the things we need
456 * from the mach task info.
459 sprintf(fmt,
460 Proc_format,
461 MPP(pp, p_pid),
462 (*getuserid)(MEP(pp, e_pcred.p_ruid)),
463 // TP(pp, base_priority),
465 pp->thread_count,
466 format_k(TASKSIZE(pp) / 1024),
467 format_k(pagetok(RSSIZE(pp))),
468 state_abbrev[(u_char)MPP(pp, p_stat)],
469 format_time(cputime),
470 100.0 * TP(pp, resident_size) / maxmem,
471 // 100.0 * weighted_cpu(pct, (RP(pp, user_time).seconds + RP(pp, system_time).seconds)),
472 100.0 * pct,
473 printable(MPP(pp, p_comm)));
475 return(fmt);
479 * get_process_info()
481 * This function returns information about the processes
482 * on the system.
485 caddr_t get_process_info(struct system_info *si,
486 struct process_select *sel, int x)
489 register int i;
490 register int total_procs;
491 register int active_procs;
492 register struct macos_proc **prefp;
493 register struct macos_proc *pp;
494 register struct kinfo_proc *pp2;
495 register struct kinfo_proc **prefp2;
496 register struct thread_basic_info *thread;
499 * these are copied out of sel for speed
502 int show_idle;
503 int show_system;
504 int show_uid;
505 int show_command;
507 kproc_list = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);
509 if(nproc > onproc)
511 proc_list = (struct macos_proc*)realloc(proc_list, sizeof(struct macos_proc) * nproc);
512 proc_ref = (struct macos_proc **)realloc(proc_ref, sizeof(struct macos_proc *) * (onproc = nproc));
515 if(proc_ref == NULL || proc_list == NULL || kproc_list == NULL)
517 puke("error: out of memory (%s)", strerror(errno));
518 return(NULL);
522 * now, our task is to build the array of information we
523 * need to function correctly. This involves setting a pointer
524 * to each real kinfo_proc structure returned by kvm_getprocs()
525 * in addition to getting the mach information for each of
526 * those processes.
529 for(pp2 = kproc_list, i = 0; i < nproc; pp2++, i++)
531 kern_return_t rc;
532 u_int info_count = TASK_BASIC_INFO_COUNT;
535 * first, we set the pointer to the reference in
536 * the kproc list.
539 proc_list[i].kproc = pp2;
542 * then, we load all of the task info for the process
545 if(PP(pp2, p_stat) != SZOMB)
547 rc = task_for_pid(mach_task_self(),
548 PP(pp2, p_pid),
549 &(proc_list[i].the_task));
551 if(rc != KERN_SUCCESS)
553 puke("error: get task info for pid %d failed with rc = %d", PP(pp2, p_pid), rc);
557 * load the task information
560 rc = task_info(proc_list[i].the_task, TASK_BASIC_INFO,
561 (task_info_t)&(proc_list[i].task_info),
562 &info_count);
564 if(rc != KERN_SUCCESS)
566 puke("error: couldn't get task info (%s); rc = %d", strerror(errno), rc);
570 * load the thread summary information
573 load_thread_info(&proc_list[i]);
577 /* get a pointer to the states summary array */
578 si->procstates = process_states;
580 /* set up flags which define what we are going to select */
581 show_idle = sel->idle;
582 show_system = sel->system;
583 show_uid = sel->uid != -1;
584 show_command = sel->command != NULL;
586 /* count up process states and get pointers to interesting procs */
587 total_procs = 0;
588 active_procs = 0;
589 memset((char *)process_states, 0, sizeof(process_states));
590 prefp = proc_ref;
591 for(pp = proc_list, i = 0; i < nproc; pp++, i++)
594 * Place pointers to each valid proc structure in
595 * proc_ref[]. Process slots that are actually in use
596 * have a non-zero status field. Processes with
597 * P_SYSTEM set are system processes---these get
598 * ignored unless show_sysprocs is set.
600 if(MPP(pp, p_stat) != 0 &&
601 (show_system || ((MPP(pp, p_flag) & P_SYSTEM) == 0)))
603 total_procs++;
604 process_states[(unsigned char) MPP(pp, p_stat)]++;
605 if((MPP(pp, p_stat) != SZOMB) &&
606 (show_idle || (MPP(pp, p_pctcpu) != 0) ||
607 (MPP(pp, p_stat) == SRUN)) &&
608 (!show_uid || MEP(pp, e_pcred.p_ruid) == (uid_t)sel->uid))
610 *prefp++ = pp;
611 active_procs++;
617 * if requested, sort the "interesting" processes
620 qsort((char *)proc_ref, active_procs, sizeof(struct macos_proc *), proc_compare);
622 /* remember active and total counts */
623 si->p_total = total_procs;
624 si->p_active = pref_len = active_procs;
626 /* pass back a handle */
627 handle.next_proc = proc_ref;
628 handle.remaining = active_procs;
629 return((caddr_t)&handle);
633 * get_system_info()
635 * This function is responsible for geting the periodic
636 * system information snapshot.
639 void get_system_info(struct system_info *si)
641 register long total;
642 register int i;
643 unsigned int count = HOST_CPU_LOAD_INFO_COUNT;
645 if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO,
646 (host_info_t)&cpuload, &count) == KERN_SUCCESS)
648 for (i = 0; i < CPU_STATE_MAX; i++)
650 cp_time[i] = cpuload.cpu_ticks[i];
654 #ifdef MAX_VERBOSE
657 * print out the entries
660 for(i = 0; i < CPU_STATE_MAX; i++)
661 printf("cp_time[%d] = %d\n", i, cp_time[i]);
662 fflush(stdout);
664 #endif /* MAX_VERBOSE */
667 * get the load averages
670 if(kvm_getloadavg(kd, si->load_avg, NUM_AVERAGES) == -1)
672 puke("error: kvm_getloadavg() failed (%s)", strerror(errno));
673 return;
676 #ifdef MAX_VERBOSE
677 printf("%-30s%03.2f, %03.2f, %03.2f\n",
678 "load averages:",
679 si->load_avg[0],
680 si->load_avg[1],
681 si->load_avg[2]);
682 #endif /* MAX_VERBOSE */
684 total = percentages(CPU_STATE_MAX, cpu_states, cp_time, cp_old, cp_diff);
686 * get the memory statistics
690 kern_return_t status;
692 count = HOST_VM_INFO_COUNT;
693 status = host_statistics(mach_host_self(), HOST_VM_INFO,
694 (host_info_t)&vm_stats, &count);
696 if(status != KERN_SUCCESS)
698 puke("error: vm_statistics() failed (%s)", strerror(errno));
699 return;
703 * we already have the total memory, we just need
704 * to get it in the right format.
707 memory_stats[0] = pagetok(maxmem / pagesize);
708 memory_stats[1] = pagetok(vm_stats.free_count);
709 memory_stats[2] = pagetok(vm_stats.active_count);
710 memory_stats[3] = pagetok(vm_stats.inactive_count);
711 memory_stats[4] = pagetok(vm_stats.wire_count);
713 if(swappgsin < 0)
715 memory_stats[5] = 1;
716 memory_stats[6] = 1;
718 else
720 memory_stats[5] = pagetok(((vm_stats.pageins - swappgsin)));
721 memory_stats[6] = pagetok(((vm_stats.pageouts - swappgsout)));
723 swappgsin = vm_stats.pageins;
724 swappgsout = vm_stats.pageouts;
727 si->cpustates = cpu_states;
728 si->memory = memory_stats;
729 si->last_pid = -1;
731 return;
735 * machine_init()
737 * This function is responsible for filling in the values of the
738 * statics structure.
741 int machine_init(struct statics *stat)
743 register int rc = 0;
744 register int i = 0;
745 size_t size;
747 size = sizeof(maxmem);
748 sysctlbyname("hw.physmem", &maxmem, &size, NULL, 0);
750 size = sizeof(nproc);
751 sysctlbyname("kern.maxproc", &nproc, &size, NULL, 0);
753 #ifdef MAX_VERBOSE
754 printf("%-30s%10d\n", "total system memory:", maxmem);
755 #endif /* MAX_VERBOSE */
758 * calculate the pageshift from the system page size
761 pagesize = getpagesize();
762 pageshift = 0;
763 while((pagesize >>= 1) > 0)
764 pageshift++;
766 pageshift -= LOG1024;
769 * fill in the statics information
772 stat->procstate_names = procstates;
773 stat->cpustate_names = cpustates;
774 stat->memory_names = memnames;
776 if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL)
777 return -1;
779 return(0);
782 /* comparison routine for qsort */
785 * proc_compare - comparison function for "qsort"
786 * Compares the resource consumption of two processes using five
787 * distinct keys. The keys (in descending order of importance) are:
788 * percent cpu, cpu ticks, state, resident set size, total virtual
789 * memory usage. The process states are ordered as follows (from least
790 * to most important): WAIT, zombie, sleep, stop, start, run. The
791 * array declaration below maps a process state index into a number
792 * that reflects this ordering.
795 static unsigned char sorted_state[] =
797 0, /* not used */
798 3, /* sleep */
799 1, /* ABANDONED (WAIT) */
800 6, /* run */
801 5, /* start */
802 2, /* zombie */
803 4 /* stop */
806 int proc_compare(const void *pp1, const void *pp2)
808 register struct macos_proc *p1;
809 register struct macos_proc *p2;
810 register int result;
811 register pctcpu lresult;
813 /* remove one level of indirection */
814 p1 = *(struct macos_proc **) pp1;
815 p2 = *(struct macos_proc **) pp2;
817 /* compare percent cpu (pctcpu) */
818 if ((lresult = RP(p2, cpu_usage) - RP(p1, cpu_usage)) == 0)
820 /* use cpticks to break the tie */
821 if ((result = MPP(p2, p_cpticks) - MPP(p1, p_cpticks)) == 0)
823 /* use process state to break the tie */
824 if ((result = sorted_state[(unsigned char) MPP(p2, p_stat)] -
825 sorted_state[(unsigned char) MPP(p1, p_stat)]) == 0)
827 /* use priority to break the tie */
828 if ((result = MPP(p2, p_priority) - MPP(p1, p_priority)) == 0)
830 /* use resident set size (rssize) to break the tie */
831 if ((result = RSSIZE(p2) - RSSIZE(p1)) == 0)
833 /* use total memory to break the tie */
834 result = PROCSIZE(p2->kproc) - PROCSIZE(p1->kproc);
840 else
842 result = lresult < 0 ? -1 : 1;
845 return(result);
850 * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
851 * the process does not exist.
852 * It is EXTREMLY IMPORTANT that this function work correctly.
853 * If top runs setuid root (as in SVR4), then this function
854 * is the only thing that stands in the way of a serious
855 * security problem. It validates requests for the "kill"
856 * and "renice" commands.
859 int proc_owner(pid)
861 int pid;
864 register int cnt;
865 register struct macos_proc **prefp;
866 register struct macos_proc *pp;
868 prefp = proc_ref;
869 cnt = pref_len;
870 while (--cnt >= 0)
872 pp = *prefp++;
873 if (MPP(pp, p_pid) == (pid_t)pid)
875 return((int)MEP(pp, e_pcred.p_ruid));
878 return(-1);
882 * load_thread_info()
884 * This function will attempt to load the thread summary info
885 * for a Mach task. The task is located as part of the macos_proc
886 * structure.
888 * returns the kern_return_t value of any failed call or KERN_SUCCESS
889 * if everything works.
892 int load_thread_info(struct macos_proc *mp)
894 register kern_return_t rc = 0;
895 register int i = 0;
896 register int t_utime = 0;
897 register int t_stime = 0;
898 register int t_cpu = 0;
899 register int t_state = 0;
900 register task_t the_task = mp->the_task;
902 thread_array_t thread_list = NULL;
905 * We need to load all of the threads for the
906 * given task so we can get the performance
907 * data from them.
910 mp->thread_count = 0;
911 rc = task_threads(the_task, &thread_list, &(mp->thread_count));
913 if(rc != KERN_SUCCESS)
915 // puke("error: unable to load threads for task (%s); rc = %d", strerror(errno), rc);
916 return(rc);
920 * now, for each of the threads, we need to sum the stats
921 * so we can present the whole thing to the caller.
924 for(i = 0; i < mp->thread_count; i++)
926 struct thread_basic_info t_info;
927 unsigned int icount = THREAD_BASIC_INFO_COUNT;
928 kern_return_t rc = 0;
930 rc = thread_info(thread_list[i], THREAD_BASIC_INFO,
931 (thread_info_t)&t_info, &icount);
933 if(rc != KERN_SUCCESS)
935 puke("error: unable to load thread info for task (%s); rc = %d", strerror(errno), rc);
936 return(rc);
939 t_utime += t_info.user_time.seconds;
940 t_stime += t_info.system_time.seconds;
941 t_cpu += t_info.cpu_usage;
944 vm_deallocate(mach_task_self(), (vm_address_t)thread_list, sizeof(thread_array_t)*(mp->thread_count));
947 * Now, we load the values in the structure above.
950 RP(mp, user_time).seconds = t_utime;
951 RP(mp, system_time).seconds = t_stime;
952 RP(mp, cpu_usage) = t_cpu;
954 return(KERN_SUCCESS);