]>
git.saurik.com Git - apple/system_cmds.git/blob - ltop.tproj/ltop.c
9 #include <sys/sysctl.h>
10 #include <Kernel/kern/ledger.h>
11 #include <mach/mach_types.h>
13 extern int ledger(int cmd
, caddr_t arg1
, caddr_t arg2
, caddr_t arg3
);
16 char *group_print
= NULL
;
17 char *resource_print
= NULL
;
24 struct ledger
*ledger
;
25 struct proc_list
*next
;
28 struct proc_list
*procs
= NULL
;
29 struct ledger_template_info
*template = NULL
;
36 struct ledger_entry_info
*info
;
37 struct ledger_entry_info
*old_info
;
41 struct ledger
*ledgers
= NULL
;
51 /* Allocate enough space to accomodate a few new entries */
53 buf
= malloc(cnt
* sizeof (struct ledger_template_info
));
55 fprintf(stderr
, "Out of memory\n");
59 if (ledger(LEDGER_TEMPLATE_INFO
, (caddr_t
)buf
, (caddr_t
)&cnt
, NULL
) < 0) {
60 perror("ledger() system call failed");
64 /* We underestimated how many entries we needed. Let's try again */
65 if (cnt
== entry_cnt
+ 5) {
75 * Note - this is a destructive operation. Unless we're about to exit, this
76 * needs to be followed by another call to get_template_info().
82 const char *group
= NULL
;
84 printf("Resources being tracked:\n");
85 printf("\t%10s %15s %8s\n", "GROUP", "RESOURCE", "UNITS");
86 for (i
= 0; i
< entry_cnt
; i
++) {
87 if (strlen(template[i
].lti_name
) == 0)
90 group
= template[i
].lti_group
;
91 for (j
= i
; j
< entry_cnt
; j
++) {
92 if (strcmp(template[j
].lti_group
, group
))
94 printf("\t%10s %15s %8s\n", template[j
].lti_group
,
95 template[j
].lti_name
, template[j
].lti_units
);
96 template[j
].lti_name
[0] = '\0';
106 if (template == NULL
)
109 for (i
= 0; i
< entry_cnt
; i
++)
110 if (!strcmp(group_print
, template[i
].lti_group
))
113 fprintf(stderr
, "No such group: %s\n", group_print
);
122 if (template == NULL
)
125 for (i
= 0; i
< entry_cnt
; i
++)
126 if (!strcmp(resource_print
, template[i
].lti_name
))
129 fprintf(stderr
, "No such resource: %s\n", resource_print
);
134 get_kern_max_proc(void)
136 int mib
[] = { CTL_KERN
, KERN_MAXPROC
};
138 size_t max_sz
= sizeof (max
);
140 if (sysctl(mib
, 2, &max
, &max_sz
, NULL
, 0) < 0) {
141 perror("Failed to get max proc count");
149 get_proc_kinfo(pid_t pid
, struct kinfo_proc
*kinfo
)
151 int mib
[] = { CTL_KERN
, KERN_PROC
, KERN_PROC_PID
, pid
};
154 len
= sizeof(struct kinfo_proc
);
155 return (sysctl(mib
, 4, kinfo
, &len
, NULL
, 0) < 0);
158 static struct ledger
*
159 ledger_find(struct ledger_info
*li
)
163 for (l
= ledgers
; l
&& (li
->li_id
!= l
->id
); l
= l
->next
)
167 l
= (struct ledger
*)malloc(sizeof (*l
));
169 fprintf(stderr
, "Out of memory");
173 l
->entries
= li
->li_entries
;
185 ledger_update(pid_t pid
, struct ledger
*l
)
188 struct ledger_entry_info
*lei
;
194 arg
= (void *)(long)pid
;
195 lei
= (struct ledger_entry_info
*)malloc((size_t)(cnt
* sizeof (*lei
)));
196 if (ledger(LEDGER_ENTRY_INFO
, arg
, (caddr_t
)lei
, (caddr_t
)&cnt
) < 0) {
197 perror("ledger_info() failed: ");
204 get_proc_info(int pid
)
206 struct ledger_info li
;
207 struct ledger
*ledgerp
;
208 struct proc_list
*proc
;
209 struct kinfo_proc kinfo
;
215 arg
= (void *)(long)pid
;
217 if (ledger(LEDGER_INFO
, arg
, (caddr_t
)&li
, NULL
) < 0) {
219 if (errno
== ENOENT
|| errno
== ESRCH
)
222 perror("ledger_info() failed: ");
226 ledgerp
= ledger_find(&li
);
227 ledger_update(pid
, ledgerp
);
230 for (proc
= procs
; proc
; proc
= proc
->next
)
231 if (proc
->pid
== pid
)
234 proc
= (struct proc_list
*)malloc(sizeof (*proc
));
236 fprintf(stderr
, "Out of memory\n");
240 if (get_proc_kinfo(pid
, &kinfo
))
241 strlcpy(proc
->command
, "Error", sizeof (proc
->command
));
243 strlcpy(proc
->command
, kinfo
.kp_proc
.p_comm
,
244 sizeof (proc
->command
));
247 proc
->ledger
= ledgerp
;
255 pid_compare(const void *a
, const void *b
)
257 pid_t
*pid_a
= (pid_t
*)a
;
258 pid_t
*pid_b
= (pid_t
*)b
;
260 return (*pid_b
- *pid_a
);
270 cnt
= (int) get_kern_max_proc();
274 sz
= cnt
* sizeof(pid_t
);
275 pids
= (pid_t
*)malloc(sz
);
277 perror("can't allocate memory for proc buffer\n");
282 cnt
= proc_listallpids(pids
, sz
);
284 perror("failed to get list of active pids");
287 qsort(pids
, cnt
, sizeof (pid_t
), pid_compare
);
292 for (i
= 0; i
< cnt
; i
++)
293 get_proc_info(pids
[i
]);
298 print_num(int64_t num
, int64_t delta
)
307 if (num
== LEDGER_LIMIT_INFINITY
) {
308 printf("%10s ", "- ");
312 if (llabs(num
) > 10000000000) {
315 } else if (llabs(num
) > 10000000) {
318 } else if (llabs(num
) > 100000) {
322 posneg
= (delta
< 0) ? '-' : ((delta
> 0) ? '+' : ' ');
328 printf("%8lld%c%c ", num
, suf
, posneg
);
334 struct ledger_entry_info
*info
, *old
;
339 printf("\n%5s %10s %15s %10s %10s %10s %10s %10s\n", "PID", "COMMAND",
340 "RESOURCE", "CREDITS", "DEBITS", "BALANCE", "LIMIT", "PERIOD");
342 for (p
= procs
; p
; p
= p
->next
) {
346 printf("%5d %10.10s ", p
->pid
, p
->command
);
349 info
= p
->ledger
->info
;
350 old
= p
->ledger
->old_info
;
351 for (i
= 0; i
< p
->ledger
->entries
; i
++) {
353 strcmp(group_print
, template[i
].lti_group
))
356 if (resource_print
&&
357 strcmp(resource_print
, template[i
].lti_name
))
362 printf("%15s ", template[i
].lti_name
);
364 d
= old
? info
[i
].lei_credit
- old
[i
].lei_credit
: 0;
365 print_num(info
[i
].lei_credit
, d
);
367 d
= old
? info
[i
].lei_debit
- old
[i
].lei_debit
: 0;
368 print_num(info
[i
].lei_debit
, d
);
370 d
= old
? info
[i
].lei_balance
- old
[i
].lei_balance
: 0;
371 print_num(info
[i
].lei_balance
, d
);
373 if (info
[i
].lei_limit
== LEDGER_LIMIT_INFINITY
) {
374 printf("%10s %10s", "none", "- ");
376 print_num(info
[i
].lei_limit
, 0);
377 print_num(info
[i
].lei_refill_period
, 0);
390 struct proc_list
*p
, *pnext
, *plast
;
391 struct ledger
*l
, *lnext
, *llast
;
394 for (p
= procs
; p
; p
= pnext
) {
409 for (l
= ledgers
; l
; l
= lnext
) {
423 l
->old_info
= l
->info
;
437 printf("%s [-hdL] [-g group] [-p pid] [-r resource] [interval]\n", pname
);
441 main(int argc
, char **argv
)
448 while ((c
= getopt(argc
, argv
, "g:hdLp:r:")) != -1) {
451 group_print
= optarg
;
464 dump_template_info();
472 resource_print
= optarg
;
485 interval
= atoi(argv
[0]);
487 if (group_print
&& resource_print
) {
488 fprintf(stderr
, "Cannot specify both a resource and a group\n");