]>
Commit | Line | Data |
---|---|---|
39236c6e A |
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 | ||
23 | inline int UT_VFORK = 0x02000000; /* thread has vfork children */ | |
24 | #pragma D binding "1.0" UT_VFORK | |
25 | ||
26 | inline uthread_t uthread = (mach_kernel`uthread_t)(curthread->uthread); /* ` */ | |
27 | #pragma D binding "1.0" uthread | |
28 | ||
29 | inline 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 | */ | |
38 | inline uint32_t THREAD_TAG_MAINTHREAD = 0x1; | |
39 | inline uint32_t THREAD_TAG_CALLOUT = 0x2; | |
40 | inline uint32_t THREAD_TAG_IOWORKLOOP = 0x4; | |
41 | ||
42 | /* | |
43 | * The following miscellaneous constants are used by the proc(4) translators | |
44 | * defined below. | |
45 | */ | |
46 | inline char SIDL = 1; | |
47 | #pragma D binding "1.0" SIDL | |
48 | inline char SRUN = 2; | |
49 | #pragma D binding "1.0" SRUN | |
50 | inline char SSLEEP = 3; | |
51 | #pragma D binding "1.0" SSLEEP | |
52 | inline char SSTOP = 4; | |
53 | #pragma D binding "1.0" SSTOP | |
54 | inline char SZOMB = 5; | |
55 | #pragma D binding "1.0" SZOMB | |
56 | /* | |
57 | * SONPROC defined here for compatability with ported scripts | |
58 | */ | |
59 | inline char SONPROC = 6; | |
60 | #pragma D binding "1.0" SONPROC | |
61 | ||
62 | inline char SOBJ_NONE = 0; | |
63 | #pragma D binding "1.0" SOBJ_NONE | |
64 | /* | |
65 | * SOBJ_* defined here for compatability with ported scripts | |
66 | */ | |
67 | inline char SOBJ_MUTEX = 1; | |
68 | #pragma D binding "1.0" SOBJ_MUTEX | |
69 | inline char SOBJ_RWLOCK = 2; | |
70 | #pragma D binding "1.0" SOBJ_RWLOCK | |
71 | inline char SOBJ_CV = 3; | |
72 | #pragma D binding "1.0" SOBJ_CV | |
73 | inline char SOBJ_SEMA = 4; | |
74 | #pragma D binding "1.0" SOBJ_SEMA | |
75 | inline char SOBJ_USER = 5; | |
76 | #pragma D binding "1.0" SOBJ_USER | |
77 | inline char SOBJ_USER_PI = 6; | |
78 | #pragma D binding "1.0" SOBJ_USER_PI | |
79 | inline char SOBJ_SHUTTLE = 7; | |
80 | #pragma D binding "1.0" SOBJ_SHUTTLE | |
81 | ||
82 | inline char PR_MODEL_ILP32 = 1; | |
83 | #pragma D binding "1.0" PR_MODEL_ILP32 | |
84 | inline 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 | */ | |
90 | inline int PR_STOPPED = 0x00000001; | |
91 | #pragma D binding "1.0" PR_STOPPED | |
92 | inline int PR_ISTOP = 0x00000002; | |
93 | #pragma D binding "1.0" PR_ISTOP | |
94 | inline int PR_DSTOP = 0x00000004; | |
95 | #pragma D binding "1.0" PR_DSTOP | |
96 | inline int PR_STEP = 0x00000008; | |
97 | #pragma D binding "1.0" PR_STEP | |
98 | inline int PR_ASLEEP = 0x00000010; | |
99 | #pragma D binding "1.0" PR_ASLEEP | |
100 | inline int PR_PCINVAL = 0x00000020; | |
101 | #pragma D binding "1.0" PR_PCINVAL | |
102 | inline int PR_ASLWP = 0x00000040; | |
103 | #pragma D binding "1.0" PR_ASLWP | |
104 | inline int PR_AGENT = 0x00000080; | |
105 | #pragma D binding "1.0" PR_AGENT | |
106 | inline int PR_DETACH = 0x00000100; | |
107 | #pragma D binding "1.0" PR_DETACH | |
108 | inline int PR_DAEMON = 0x00000200; | |
109 | #pragma D binding "1.0" PR_DAEMON | |
110 | inline int PR_ISSYS = 0x00001000; | |
111 | #pragma D binding "1.0" PR_ISSYS | |
112 | inline int PR_VFORKP = 0x00002000; | |
113 | #pragma D binding "1.0" PR_VFORKP | |
114 | inline int PR_ORPHAN = 0x00004000; | |
115 | #pragma D binding "1.0" PR_ORPHAN | |
116 | inline int PR_FORK = 0x00100000; | |
117 | #pragma D binding "1.0" PR_FORK | |
118 | inline int PR_RLC = 0x00200000; | |
119 | #pragma D binding "1.0" PR_RLC | |
120 | inline int PR_KLC = 0x00400000; | |
121 | #pragma D binding "1.0" PR_KLC | |
122 | inline int PR_ASYNC = 0x00800000; | |
123 | #pragma D binding "1.0" PR_ASYNC | |
124 | inline int PR_MSACCT = 0x01000000; | |
125 | #pragma D binding "1.0" PR_MSACCT | |
126 | inline int PR_BPTADJ = 0x02000000; | |
127 | #pragma D binding "1.0" PR_BPTADJ | |
128 | inline int PR_PTRACE = 0x04000000; | |
129 | #pragma D binding "1.0" PR_PTRACE | |
130 | inline int PR_MSFORK = 0x08000000; | |
131 | #pragma D binding "1.0" PR_MSFORK | |
132 | inline 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 | */ | |
145 | typedef int taskid_t; | |
146 | typedef int projid_t; | |
147 | typedef int poolid_t; | |
148 | typedef struct timespec timestruc_t; /* (SECONDS, NANOSECONDS) */ | |
149 | ||
150 | typedef 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 | ||
177 | inline int P_LP64 = 0x00000004; /* Process is LP64 */ | |
178 | #pragma D binding "1.0" P_LP64 | |
179 | ||
180 | #pragma D binding "1.0" translator | |
181 | translator 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 | |
230 | translator 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 | ||
264 | inline processor_t PROCESSOR_NULL = ((processor_t) 0); | |
265 | #pragma D binding "1.0" PROCESSOR_NULL | |
266 | ||
267 | typedef int psetid_t; | |
268 | ||
269 | typedef 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 | |
286 | translator 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 | ||
311 | inline psinfo_t *curpsinfo = xlate <psinfo_t *> (curproc); | |
312 | #pragma D attributes Stable/Stable/Common curpsinfo | |
313 | #pragma D binding "1.0" curpsinfo | |
314 | ||
315 | inline 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 */ | |
320 | inline 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 */ | |
326 | inline 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 |