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	/* Event counters. */
252	task_events_info_data_t	events;
253	task_events_info_data_t	b_events;
254	task_events_info_data_t	p_events;
255
256	libtop_i64_values_t faults;
257	libtop_i64_values_t pageins;
258	libtop_i64_values_t cow_faults;
259	libtop_i64_values_t messages_sent;
260	libtop_i64_values_t messages_recv;
261	libtop_i64_values_t syscalls_mach;
262	libtop_i64_values_t syscalls_bsd;
263	libtop_i64_values_t csw;
264
265	uint64_t	palloc;
266	uint64_t	pfree;
267	uint64_t	salloc;
268	uint64_t	sfree;
269
270	uint64_t	p_palloc;
271	uint64_t	p_pfree;
272	uint64_t	p_salloc;
273	uint64_t	p_sfree;
274
275	/* malloc()ed '\0'-terminated string. */
276	char			*command;
277
278	/* Sequence number, used to detect defunct processes. */
279	uint32_t		seq;
280
281	/*
282	 * Previous sequence number, used to detect processes that have only
283	 * existed for the current sample (p_seq == 0).
284	 */
285	uint32_t		p_seq;
286
287	/* time process was started */
288	struct timeval		started;
289       /* process cpu type */
290	cpu_type_t	cputype;
291
292	uint32_t	wq_nthreads;
293	uint32_t	wq_run_threads;
294	uint32_t	wq_blocked_threads;
295
296	uint32_t	p_wq_nthreads;
297	uint32_t	p_wq_run_threads;
298	uint32_t	p_wq_blocked_threads;
299
300	/* Power info. */
301	task_power_info_data_t power;
302	task_power_info_data_t b_power;
303	task_power_info_data_t p_power;
304};
305
306/*
307 * Initialize libtop.  If a non-NULL printing function pointer is passed in,
308 * libtop will call the printing function when errors occur.
309 *
310 * Returns zero for success, non-zero for error.
311 */
312int
313libtop_init(libtop_print_t *a_print, void *a_user_data);
314
315/* Shut down libtop. */
316void
317libtop_fini(void);
318
319/*
320 * Take a sample.
321 *
322 * If a_reg is FALSE, do not calculate reg, vprvt, rprvt, or rshrd.
323 *
324 * If a_fw is FALSE, do not calculate fw_count, fw_code, fw_data, or
325 * fw_linkedit.
326 *
327 * Returns zero for success, non-zero for error.
328 */
329int
330libtop_sample(boolean_t a_reg, boolean_t a_fw);
331
332/*
333 * Return a pointer to a structure containing the generic information collected
334 * during the most recent sample.  The return value from this function can be
335 * used for the duration of program execution (i.e. the return value does not
336 * change between samples).
337 */
338const libtop_tsamp_t *
339libtop_tsamp(void);
340
341/*
342 * Type for psamp comparison function.
343 *
344 * Arguments : (void *) : Opaque data pointer.
345 *             (libtop_psamp_t *) : psamp.
346 *
347 * Return values : -1 : Second argument less than third argument.
348 *                  0 : Second argument equal to third argument.
349 *                  1 : Second argument greater than third argument.
350 */
351typedef int libtop_sort_t (void *, const libtop_psamp_t *,
352    const libtop_psamp_t *);
353
354/*
355 * Sort processes using a_sort().  Pass a_data as the opaque data pointer to
356 * a_sort().
357 */
358void
359libtop_psort(libtop_sort_t *a_sort, void *a_data);
360
361/*
362 * Iteratively return a pointer to each process which was in the most recent
363 * sample.  If libtop_psort() was called after the most recent libtop_sample()
364 * call, the processes are iterated over in sorted order.  Otherwise, they are
365 * iterated over in increasing pid order.
366 *
367 * A NULL return value indicates that there are no more processes to iterate
368 * over.
369 */
370const libtop_psamp_t *
371libtop_piterate(void);
372
373/*
374 * Set whether to collect memory region information for the process with pid
375 * a_pid.
376 *
377 * Returns zero for success, non-zero for error.
378 */
379int
380libtop_preg(pid_t a_pid, libtop_preg_t a_preg);
381
382/*
383 * Set the interval between framework updates.
384 *
385 * Returns zero for success, non-zero for error.
386 */
387int
388libtop_set_interval(uint32_t ival);
389#define LIBTOP_MAX_INTERVAL 100
390
391/*
392 * Return a pointer to a username string (truncated to the first 8 characters),
393 * given a uid.  If the uid cannot be matched to a username, NULL is returned.
394 */
395const char *
396libtop_username(uid_t a_uid);
397
398/*
399 * Return a pointer to a string representation of a process state (names of
400 * states that are contained in libtop_tsamp_t's state_breakdown array).
401 */
402const char *
403libtop_state_str(uint32_t a_state);
404
405/*
406 * These i64 functions are special functions that operate on an accumulator
407 * and work with overflowing 32-bit integers.  So if the value overflows in the kernel
408 * counter, because it is a 32-bit value, they will in most cases capture the
409 * changes overtime to the value.  The assumption is that all updates are increments
410 * of 0 or more (based on the deltas) so this doesn't work with values that
411 * potentially go negative.
412 */
413
414libtop_i64_t
415libtop_i64_init(uint64_t acc, int last_value);
416
417void
418libtop_i64_update(libtop_i64_t *i, int value);
419
420uint64_t
421libtop_i64_value(libtop_i64_t *i);
422
423__END_DECLS
424