1/*
2 * Copyright (c) 2005-2006 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
23inline int UT_VFORK = 0x02000000;  /* thread has vfork children */
24#pragma D binding "1.0" UT_VFORK
25
26inline uthread_t uthread = (mach_kernel`uthread_t)(curthread->uthread); /* ` */
27#pragma D binding "1.0" uthread
28
29inline struct proc * curproc =
30	(uthread && (uthread->uu_flag & UT_VFORK) && uthread->uu_proc) ? (struct proc *)uthread->uu_proc :
31	((struct proc *)(curthread->task->bsd_info)) != NULL ? ((struct proc *)(curthread->task->bsd_info)) :
32	mach_kernel`kernproc; /* ` */
33#pragma D binding "1.0" curproc
34
35/*
36 * curthread->thread_tag will have this set if the thread is the main thread
37 */
38inline uint32_t THREAD_TAG_MAINTHREAD = 0x1;
39inline uint32_t THREAD_TAG_CALLOUT = 0x2;
40inline uint32_t THREAD_TAG_IOWORKLOOP = 0x4;
41
42/*
43 * The following miscellaneous constants are used by the proc(4) translators
44 * defined below.
45 */
46inline char SIDL = 1;
47#pragma D binding "1.0" SIDL
48inline char SRUN = 2;
49#pragma D binding "1.0" SRUN
50inline char SSLEEP = 3;
51#pragma D binding "1.0" SSLEEP
52inline char SSTOP = 4;
53#pragma D binding "1.0" SSTOP
54inline char SZOMB = 5;
55#pragma D binding "1.0" SZOMB
56/*
57 * SONPROC defined here for compatability with ported scripts
58 */
59inline char SONPROC = 6;
60#pragma D binding "1.0" SONPROC
61
62inline char SOBJ_NONE = 0;
63#pragma D binding "1.0" SOBJ_NONE
64/*
65 * SOBJ_* defined here for compatability with ported scripts
66 */
67inline char SOBJ_MUTEX = 1;
68#pragma D binding "1.0" SOBJ_MUTEX
69inline char SOBJ_RWLOCK = 2;
70#pragma D binding "1.0" SOBJ_RWLOCK
71inline char SOBJ_CV = 3;
72#pragma D binding "1.0" SOBJ_CV
73inline char SOBJ_SEMA = 4;
74#pragma D binding "1.0" SOBJ_SEMA
75inline char SOBJ_USER = 5;
76#pragma D binding "1.0" SOBJ_USER
77inline char SOBJ_USER_PI = 6;
78#pragma D binding "1.0" SOBJ_USER_PI
79inline char SOBJ_SHUTTLE = 7;
80#pragma D binding "1.0" SOBJ_SHUTTLE
81
82inline char PR_MODEL_ILP32 = 1;
83#pragma D binding "1.0" PR_MODEL_ILP32
84inline char PR_MODEL_LP64 = 2;
85#pragma D binding "1.0" PR_MODEL_LP64
86
87/*
88 * PR_* defined here for compatability with ported scripts
89 */
90inline int PR_STOPPED = 0x00000001;
91#pragma D binding "1.0" PR_STOPPED
92inline int PR_ISTOP = 0x00000002;
93#pragma D binding "1.0" PR_ISTOP
94inline int PR_DSTOP = 0x00000004;
95#pragma D binding "1.0" PR_DSTOP
96inline int PR_STEP = 0x00000008;
97#pragma D binding "1.0" PR_STEP
98inline int PR_ASLEEP = 0x00000010;
99#pragma D binding "1.0" PR_ASLEEP
100inline int PR_PCINVAL = 0x00000020;
101#pragma D binding "1.0" PR_PCINVAL
102inline int PR_ASLWP = 0x00000040;
103#pragma D binding "1.0" PR_ASLWP
104inline int PR_AGENT = 0x00000080;
105#pragma D binding "1.0" PR_AGENT
106inline int PR_DETACH = 0x00000100;
107#pragma D binding "1.0" PR_DETACH
108inline int PR_DAEMON = 0x00000200;
109#pragma D binding "1.0" PR_DAEMON
110inline int PR_ISSYS = 0x00001000;
111#pragma D binding "1.0" PR_ISSYS
112inline int PR_VFORKP = 0x00002000;
113#pragma D binding "1.0" PR_VFORKP
114inline int PR_ORPHAN = 0x00004000;
115#pragma D binding "1.0" PR_ORPHAN
116inline int PR_FORK = 0x00100000;
117#pragma D binding "1.0" PR_FORK
118inline int PR_RLC = 0x00200000;
119#pragma D binding "1.0" PR_RLC
120inline int PR_KLC = 0x00400000;
121#pragma D binding "1.0" PR_KLC
122inline int PR_ASYNC = 0x00800000;
123#pragma D binding "1.0" PR_ASYNC
124inline int PR_MSACCT = 0x01000000;
125#pragma D binding "1.0" PR_MSACCT
126inline int PR_BPTADJ = 0x02000000;
127#pragma D binding "1.0" PR_BPTADJ
128inline int PR_PTRACE = 0x04000000;
129#pragma D binding "1.0" PR_PTRACE
130inline int PR_MSFORK = 0x08000000;
131#pragma D binding "1.0" PR_MSFORK
132inline int PR_IDLE = 0x10000000;
133#pragma D binding "1.0" PR_IDLE
134
135/*
136 * Translate from the kernel's proc_t structure to a proc(4) psinfo_t struct.
137 * We do not provide support for pr_size, pr_rssize, pr_pctcpu, and pr_pctmem.
138 * We also do not fill in pr_lwp (the lwpsinfo_t for the representative LWP)
139 * because we do not have the ability to select and stop any representative.
140 * Also, for the moment, pr_wstat, pr_time, and pr_ctime are not supported,
141 * but these could be supported by DTrace in the future using subroutines.
142 * Note that any member added to this translator should also be added to the
143 * kthread_t-to-psinfo_t translator, below.
144 */
145typedef int taskid_t;
146typedef int projid_t;
147typedef int poolid_t;
148typedef struct timespec timestruc_t; /* (SECONDS, NANOSECONDS) */
149
150typedef struct psinfo {
151	int	pr_nlwp;	/* number of active lwps in the process */
152	pid_t	pr_pid;		/* unique process id */
153	pid_t	pr_ppid;	/* process id of parent */
154	pid_t	pr_pgid;	/* pid of process group leader */
155	pid_t	pr_sid;		/* session id */
156	uid_t	pr_uid;		/* real user id */
157	uid_t	pr_euid;	/* effective user id */
158	gid_t	pr_gid;		/* real group id */
159	gid_t	pr_egid;	/* effective group id */
160	uintptr_t pr_addr;	/* address of process */
161	dev_t	pr_ttydev;	/* controlling tty device (or PRNODEV) */
162	timestruc_t pr_start;/* process start time, DEPRECATED, see pr_start_tv below */
163	char pr_fname[16];	/* name of execed file */
164	char pr_psargs[80];	/* initial characters of arg list */
165	int pr_argc;    	/* initial argument count */
166	user_addr_t pr_argv;  /* address of initial argument vector */
167	user_addr_t pr_envp;  /* address of initial environment vector */
168	char    pr_dmodel;  /* data model of the process */
169	taskid_t pr_taskid; /* task id */
170	projid_t pr_projid; /* project id */
171	poolid_t pr_poolid; /* pool id */
172	zoneid_t pr_zoneid; /* zone id */
173
174	struct timeval pr_start_tv; /* process start time, from the epoch (SECONDS, MICROSECONDS) */
175} psinfo_t;
176
177inline int P_LP64 = 0x00000004;  /* Process is LP64 */
178#pragma D binding "1.0" P_LP64
179
180#pragma D binding "1.0" translator
181translator psinfo_t < struct proc * P > {
182	pr_nlwp = 	((struct task *)(P->task))->thread_count;
183	pr_pid = 	P->p_pid;
184	pr_ppid = 	P->p_ppid;
185	pr_pgid = 	P->p_pgrp->pg_id;
186	pr_sid = 	P->p_pgrp->pg_session->s_sid;
187 	pr_uid = 	P->p_ucred->cr_posix.cr_ruid;
188 	pr_euid = 	P->p_ucred->cr_posix.cr_uid;
189 	pr_gid = 	P->p_ucred->cr_posix.cr_rgid;
190 	pr_egid = 	P->p_ucred->cr_posix.cr_groups[0];
191	pr_addr = 	(uintptr_t)P;
192
193	pr_ttydev = (P->p_pgrp->pg_session->s_ttyvp == NULL) ? (dev_t)-1 :
194		P->p_pgrp->pg_session->s_ttyp->t_dev;
195
196	/*
197	 * timestruct_t (SECONDS, NANOSECONDS) is not available directly nor can a further translation
198	 * be specified here. Zero the structure. Use pr_start_tv instead.
199	 */
200	pr_start = *((timestruc_t *)`dtrace_zero); /* ` */
201
202	pr_fname = 	P->p_comm;
203	pr_psargs = P->p_comm; /* XXX omits command line arguments XXX */
204	pr_argc = P->p_argc;
205	pr_argv = P->p_dtrace_argv;
206	pr_envp = P->p_dtrace_envp;
207
208	pr_dmodel = (P->p_flag & P_LP64) ? PR_MODEL_LP64 : PR_MODEL_ILP32;
209
210	pr_taskid = 0;
211	pr_projid = 0;
212	pr_poolid = 0;
213	pr_zoneid = 0;
214
215	/*
216	 * pstats->pstart is a struct timeval: (SECONDS, MICROSECONDS).
217	 */
218	pr_start_tv = P->p_start;
219};
220
221/*
222 * Translate from the kernel's kthread_t structure to a proc(4) psinfo_t
223 * struct.  Lacking a facility to define one translator only in terms of
224 * another, we explicitly define each member by using the proc_t-to-psinfo_t
225 * translator, above; any members added to that translator should also be
226 * added here.  (The only exception to this is pr_start, which -- due to it
227 * being a structure -- cannot be defined in terms of a translator at all.)
228 */
229#pragma D binding "1.0" translator
230translator psinfo_t < thread_t T > {
231	pr_nlwp = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_nlwp;
232	pr_pid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_pid;
233	pr_ppid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_ppid;
234	pr_pgid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_pgid;
235	pr_sid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_sid;
236	pr_uid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_uid;
237	pr_euid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_euid;
238	pr_gid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_gid;
239	pr_egid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_egid;
240	pr_addr = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_addr;
241	pr_ttydev = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_ttydev;
242	pr_start = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_start;
243	pr_fname = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_fname;
244	pr_psargs = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_psargs; /* XXX omits command line arguments XXX */
245	pr_argc = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_argc;
246	pr_argv = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_argv;
247	pr_envp = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_envp;
248	pr_dmodel = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_dmodel;
249	pr_taskid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_taskid;
250	pr_projid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_projid;
251	pr_poolid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_poolid;
252	pr_zoneid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_zoneid;
253
254	pr_start_tv = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_start_tv;
255};
256
257/*
258 * Translate from the kernel's kthread_t structure to a proc(4) lwpsinfo_t.
259 * We do not provide support for pr_nice, pr_oldpri, pr_cpu, or pr_pctcpu.
260 * Also, for the moment, pr_start and pr_time are not supported, but these
261 * could be supported by DTrace in the future using subroutines.
262 */
263
264inline processor_t PROCESSOR_NULL = ((processor_t) 0);
265#pragma D binding "1.0" PROCESSOR_NULL
266
267typedef int psetid_t;
268
269typedef struct lwpsinfo {
270	int	pr_flag;	/* lwp flags (DEPRECATED; do not use) */
271	id_t	pr_lwpid;	/* lwp id */
272	uintptr_t pr_addr;	/* internal address of lwp */
273	uintptr_t pr_wchan;	/* wait addr for sleeping lwp */
274	char	pr_stype;	/* synchronization event type */
275	char	pr_state;	/* numeric lwp state */
276	char	pr_sname;	/* printable character for pr_state */
277	short	pr_syscall;	/* system call number (if in syscall) */
278	int	pr_pri;		/* priority, high value is high priority */
279	char	pr_clname[8];	/* scheduling class name */
280	processorid_t pr_onpro;		/* processor which last ran this lwp */
281	processorid_t pr_bindpro;	/* processor to which lwp is bound */
282	psetid_t pr_bindpset;	/* processor set to which lwp is bound */
283} lwpsinfo_t;
284
285#pragma D binding "1.0" translator
286translator lwpsinfo_t < thread_t T > {
287	pr_flag = 0; /* lwp flags (DEPRECATED; do not use) */
288	pr_lwpid = (id_t)T->thread_id;
289	pr_addr = (uintptr_t)T;
290	pr_wchan = (uintptr_t)(((uthread_t)(T->uthread))->uu_wchan);
291
292	pr_stype = SOBJ_NONE; /* XXX Undefined synch object (or none) XXX */
293	pr_state = curproc->p_stat;
294	pr_sname = (curproc->p_stat == SIDL) ? 'I' :
295			(curproc->p_stat == SRUN) ? 'R' :
296			(curproc->p_stat == SSLEEP) ? 'S' :
297			(curproc->p_stat == SSTOP) ? 'T' :
298			(curproc->p_stat == SZOMB) ? 'Z' : '?';
299
300	pr_syscall = ((uthread_t)(T->uthread))->uu_code;
301	pr_pri = T->sched_pri;
302
303	pr_clname = (T->sched_mode & 0x0001) ? "RT" :
304			(T->sched_mode & 0x0002) ? "TS" : "SYS";
305
306	pr_onpro = (T->last_processor == PROCESSOR_NULL) ? -1 : T->last_processor->cpu_id;
307	pr_bindpro = -1; /* Darwin does not bind threads to processors. */
308	pr_bindpset = -1; /* Darwin does not partition processors. */
309};
310
311inline psinfo_t *curpsinfo = xlate <psinfo_t *> (curproc);
312#pragma D attributes Stable/Stable/Common curpsinfo
313#pragma D binding "1.0" curpsinfo
314
315inline lwpsinfo_t *curlwpsinfo = xlate <lwpsinfo_t *> (curthread);
316#pragma D attributes Stable/Stable/Common curlwpsinfo
317#pragma D binding "1.0" curlwpsinfo
318
319/* XXX Really want vn_getpath(curproc->p_fd->fd_cdir, , ) but that takes namecache_rw_lock XXX */
320inline string cwd = curproc->p_fd->fd_cdir->v_name == NULL ?
321	"<unknown>" : stringof(curproc->p_fd->fd_cdir->v_name);
322#pragma D attributes Stable/Stable/Common cwd
323#pragma D binding "1.0" cwd
324
325/* XXX Really want vn_getpath(curproc->p_fd->fd_rdir, , ) but that takes namecache_rw_lock XXX */
326inline string root = curproc->p_fd->fd_rdir == NULL ? "/" :
327	curproc->p_fd->fd_rdir->v_name == NULL ? "<unknown>" :
328	stringof(curproc->p_fd->fd_rdir->v_name);
329#pragma D attributes Stable/Stable/Common root
330#pragma D binding "1.0" root
331