1/*
2 * Copyright (c) 2002-2004 Apple Computer, Inc.  All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include <mach/boolean.h>
24#include <mach/host_info.h>
25#include <mach/task_info.h>
26#include <mach/vm_types.h>
27#include <stdarg.h>
28#include <sys/time.h>
29#include <sys/sysctl.h>
30
31__BEGIN_DECLS
32
33/*
34 * Flags for determining whether to collect memory region information on a
35 * per-process basis, used byt libtop_preg().
36 */
37typedef enum {
38	/*
39	 * Collect memory region information iff libtop_sample()'s a_reg
40	 * parameter is TRUE.
41	 */
42	LIBTOP_PREG_default = 0,
43	/* Do not collect memory region information. */
44	LIBTOP_PREG_off,
45	/* Always collect memory region information. */
46	LIBTOP_PREG_on
47} libtop_preg_t;
48
49typedef struct libtop_i64 {
50	uint64_t accumulator;
51	int last_value;
52} libtop_i64_t;
53
54typedef struct libtop_i64_values {
55	libtop_i64_t i64;
56	uint64_t now;
57	uint64_t began;
58	uint64_t previous;
59} libtop_i64_values_t;
60
61/*
62 * Type used for specifying a printing function that is called when an error
63 * occurs.  libtop does not print a '\n' at the end of the string, so it is
64 * up to the printing function to add it if desired.
65 */
66typedef boolean_t libtop_print_t (void *a_user_data, const char *a_format, ...);
67
68/*
69 * General sample information.
70 *
71 * Fields prefix meanings:
72 *
73 *   b_ : Value for first sample.
74 *   p_ : Value for previous sample (same as b_ if p_seq is 0).
75 */
76typedef struct {
77	/*
78	 * Sample sequence number, incremented for every sample.  The first
79	 * sample has a sequence number of 1.
80	 */
81	uint32_t		seq;
82
83	/* Number of processes. */
84	uint32_t		nprocs;
85
86	/* CPU loads. */
87	host_cpu_load_info_data_t cpu;
88	host_cpu_load_info_data_t b_cpu;
89	host_cpu_load_info_data_t p_cpu;
90
91	/* Load averages for 1, 5, and 15 minutes. */
92	float			loadavg[3];
93
94	/* Start time, previous sample time, and current sample time. */
95	struct timeval		time;
96	struct timeval		b_time;
97	struct timeval		p_time;
98
99	/* Total number of threads. */
100	uint32_t		threads;
101
102	/* VM page size. */
103	vm_size_t		pagesize;
104
105	/* Physical memory size. */
106	uint64_t		memsize;
107
108	/* VM statistics. */
109	vm_statistics64_data_t	vm_stat;
110	vm_statistics64_data_t	b_vm_stat;
111	vm_statistics64_data_t	p_vm_stat;
112
113	boolean_t		purgeable_is_valid;
114
115	/* Swap usage */
116	struct xsw_usage	xsu;
117	boolean_t		xsu_is_valid;
118
119	/* Total number of memory regions. */
120	uint32_t		reg;
121
122	/* Total shared, private, virtual sizes. */
123	uint64_t		rshrd;
124	uint64_t		rprvt;
125	uint64_t		vsize;
126
127	/* Total private resident memory used by frameworks. */
128	uint64_t		fw_private;
129
130	/* Total virtual memory used by frameworks. */
131	uint64_t		fw_vsize;
132
133	/* Number of frameworks. */
134	uint32_t		fw_count;
135
136	/* Code size of frameworks. */
137	uint64_t		fw_code;
138
139	/* Data size of frameworks. */
140	uint64_t		fw_data;
141
142	/* Linkedit size of frameworks. */
143	uint64_t		fw_linkedit;
144
145#define LIBTOP_STATE_MAX	7
146#define LIBTOP_NSTATES		(LIBTOP_STATE_MAX + 1)
147#define LIBTOP_STATE_MAXLEN	8
148	int			state_breakdown[LIBTOP_NSTATES];
149
150	/* Network statistics. */
151	uint64_t		net_ipackets;
152	uint64_t		b_net_ipackets;
153	uint64_t		p_net_ipackets;
154
155	uint64_t		net_opackets;
156	uint64_t		b_net_opackets;
157	uint64_t		p_net_opackets;
158
159	uint64_t		net_ibytes;
160	uint64_t		b_net_ibytes;
161	uint64_t		p_net_ibytes;
162
163	uint64_t		net_obytes;
164	uint64_t		b_net_obytes;
165	uint64_t		p_net_obytes;
166
167	/* Disk statistics. */
168	uint64_t		disk_rops;
169	uint64_t		b_disk_rops;
170	uint64_t		p_disk_rops;
171
172	uint64_t		disk_wops;
173	uint64_t		b_disk_wops;
174	uint64_t		p_disk_wops;
175
176	uint64_t		disk_rbytes;
177	uint64_t		b_disk_rbytes;
178	uint64_t		p_disk_rbytes;
179
180	uint64_t		disk_wbytes;
181	uint64_t		b_disk_wbytes;
182	uint64_t		p_disk_wbytes;
183
184	uint64_t		pages_stolen;
185} libtop_tsamp_t;
186
187/*
188 * Process sample information.
189 *
190 * Fields prefix meanings:
191 *
192 *   b_ : Value for first sample.
193 *   p_ : Value for previous sample (invalid if p_seq is 0).
194 */
195typedef struct libtop_psamp_s libtop_psamp_t;
196struct libtop_psamp_s {
197	uid_t			uid;
198	pid_t			pid;
199	pid_t			ppid;
200	gid_t			pgrp;
201
202	/* Memory statistics. */
203	uint64_t		rsize;
204	uint64_t		vsize;
205	uint64_t		rprvt;
206	uint64_t		vprvt;
207	uint64_t		rshrd;
208	uint64_t		fw_private;
209	uint64_t		empty;
210
211	uint32_t		reg;
212	uint32_t		p_reg;
213
214	uint64_t		p_rsize;
215	uint64_t		p_vprvt;
216	uint64_t		p_vsize;
217	uint64_t		p_rprvt;
218	uint64_t		p_rshrd;
219	uint64_t		p_empty;
220
221	/* Anonymous/purgeable memory statistics. */
222	uint64_t anonymous;
223	uint64_t purgeable;
224	uint64_t p_anonymous;
225	uint64_t p_purgeable;
226
227	/* Compressed memory statistics. */
228	uint64_t compressed;
229	uint64_t p_compressed;
230
231	/* Number of threads. */
232	uint32_t		th;
233	uint32_t		p_th;
234
235	uint32_t		running_th;
236	uint32_t		p_running_th;
237
238
239	/* Number of ports. */
240	uint32_t		prt;
241	uint32_t		p_prt;
242
243	/* CPU state/usage statistics. */
244	int			state; /* Process state. */
245
246	/* Total time consumed by process. */
247	struct timeval		total_time;
248	struct timeval		b_total_time;
249	struct timeval		p_total_time;
250
251	/* Total on behalf cpu time. */
252	uint64_t 	cpu_billed_to_me;
253	uint64_t	cpu_billed_to_others;
254	uint64_t 	b_cpu_billed_to_me;
255	uint64_t	b_cpu_billed_to_others;
256	uint64_t 	p_cpu_billed_to_me;
257	uint64_t	p_cpu_billed_to_others;
258
259	/* assert counts */
260	uint64_t	assertcnt;
261	uint64_t	p_assertcnt;
262	uint64_t	b_assertcnt;
263
264	/* boost transition counts */
265	uint64_t	boosts;
266	uint64_t	b_boosts;
267	uint64_t	p_boosts;
268
269	/* last seq we were boost donating */
270	boolean_t	boost_donating;
271	uint32_t	boost_last_donating_seq;
272
273	/* Event counters. */
274	task_events_info_data_t	events;
275	task_events_info_data_t	b_events;
276	task_events_info_data_t	p_events;
277
278	libtop_i64_values_t faults;
279	libtop_i64_values_t pageins;
280	libtop_i64_values_t cow_faults;
281	libtop_i64_values_t messages_sent;
282	libtop_i64_values_t messages_recv;
283	libtop_i64_values_t syscalls_mach;
284	libtop_i64_values_t syscalls_bsd;
285	libtop_i64_values_t csw;
286
287	uint64_t	palloc;
288	uint64_t	pfree;
289	uint64_t	salloc;
290	uint64_t	sfree;
291
292	uint64_t	p_palloc;
293	uint64_t	p_pfree;
294	uint64_t	p_salloc;
295	uint64_t	p_sfree;
296
297	/* malloc()ed '\0'-terminated string. */
298	char			*command;
299
300	/* Sequence number, used to detect defunct processes. */
301	uint32_t		seq;
302
303	/*
304	 * Previous sequence number, used to detect processes that have only
305	 * existed for the current sample (p_seq == 0).
306	 */
307	uint32_t		p_seq;
308
309	/* time process was started */
310	struct timeval		started;
311       /* process cpu type */
312	cpu_type_t	cputype;
313
314	uint32_t	wq_nthreads;
315	uint32_t	wq_run_threads;
316	uint32_t	wq_blocked_threads;
317
318	uint32_t	p_wq_nthreads;
319	uint32_t	p_wq_run_threads;
320	uint32_t	p_wq_blocked_threads;
321
322	/* Power info. */
323	task_power_info_data_t power;
324	task_power_info_data_t b_power;
325	task_power_info_data_t p_power;
326};
327
328/*
329 * Initialize libtop.  If a non-NULL printing function pointer is passed in,
330 * libtop will call the printing function when errors occur.
331 *
332 * Returns zero for success, non-zero for error.
333 */
334int
335libtop_init(libtop_print_t *a_print, void *a_user_data);
336
337/* Shut down libtop. */
338void
339libtop_fini(void);
340
341/*
342 * Take a sample.
343 *
344 * If a_reg is FALSE, do not calculate reg, vprvt, rprvt, or rshrd.
345 *
346 * If a_fw is FALSE, do not calculate fw_count, fw_code, fw_data, or
347 * fw_linkedit.
348 *
349 * Returns zero for success, non-zero for error.
350 */
351int
352libtop_sample(boolean_t a_reg, boolean_t a_fw);
353
354/*
355 * Return a pointer to a structure containing the generic information collected
356 * during the most recent sample.  The return value from this function can be
357 * used for the duration of program execution (i.e. the return value does not
358 * change between samples).
359 */
360const libtop_tsamp_t *
361libtop_tsamp(void);
362
363/*
364 * Type for psamp comparison function.
365 *
366 * Arguments : (void *) : Opaque data pointer.
367 *             (libtop_psamp_t *) : psamp.
368 *
369 * Return values : -1 : Second argument less than third argument.
370 *                  0 : Second argument equal to third argument.
371 *                  1 : Second argument greater than third argument.
372 */
373typedef int libtop_sort_t (void *, const libtop_psamp_t *,
374    const libtop_psamp_t *);
375
376/*
377 * Sort processes using a_sort().  Pass a_data as the opaque data pointer to
378 * a_sort().
379 */
380void
381libtop_psort(libtop_sort_t *a_sort, void *a_data);
382
383/*
384 * Iteratively return a pointer to each process which was in the most recent
385 * sample.  If libtop_psort() was called after the most recent libtop_sample()
386 * call, the processes are iterated over in sorted order.  Otherwise, they are
387 * iterated over in increasing pid order.
388 *
389 * A NULL return value indicates that there are no more processes to iterate
390 * over.
391 */
392const libtop_psamp_t *
393libtop_piterate(void);
394
395/*
396 * Set whether to collect memory region information for the process with pid
397 * a_pid.
398 *
399 * Returns zero for success, non-zero for error.
400 */
401int
402libtop_preg(pid_t a_pid, libtop_preg_t a_preg);
403
404/*
405 * Set the interval between framework updates.
406 *
407 * Returns zero for success, non-zero for error.
408 */
409int
410libtop_set_interval(uint32_t ival);
411#define LIBTOP_MAX_INTERVAL 100
412
413/*
414 * Return a pointer to a username string (truncated to the first 8 characters),
415 * given a uid.  If the uid cannot be matched to a username, NULL is returned.
416 */
417const char *
418libtop_username(uid_t a_uid);
419
420/*
421 * Return a pointer to a string representation of a process state (names of
422 * states that are contained in libtop_tsamp_t's state_breakdown array).
423 */
424const char *
425libtop_state_str(uint32_t a_state);
426
427/*
428 * These i64 functions are special functions that operate on an accumulator
429 * and work with overflowing 32-bit integers.  So if the value overflows in the kernel
430 * counter, because it is a 32-bit value, they will in most cases capture the
431 * changes overtime to the value.  The assumption is that all updates are increments
432 * of 0 or more (based on the deltas) so this doesn't work with values that
433 * potentially go negative.
434 */
435
436libtop_i64_t
437libtop_i64_init(uint64_t acc, int last_value);
438
439void
440libtop_i64_update(libtop_i64_t *i, int value);
441
442uint64_t
443libtop_i64_value(libtop_i64_t *i);
444
445__END_DECLS
446