xref: /dragonfly/sys/kern/kern_kinfo.c (revision 2b3f93ea)
1 /*-
2  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
6  * by Thomas E. Spanjaard <tgen@netphreax.net>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  * 3. Neither the name of The DragonFly Project nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific, prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
26  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 /*
37  * This is a source file used by both the kernel and libkvm.
38  */
39 
40 #ifndef _KERNEL
41 #define _KERNEL_STRUCTURES
42 #endif
43 
44 #include <sys/proc.h>
45 #include <vm/vm_map.h>
46 #include <sys/kinfo.h>
47 #include <sys/tty.h>
48 #include <sys/conf.h>
49 #include <sys/jail.h>
50 #include <sys/mplock2.h>
51 #include <sys/globaldata.h>
52 #ifdef _KERNEL
53 #include <sys/systm.h>
54 #else
55 #include <string.h>
56 
57 dev_t devid_from_dev(cdev_t dev);	/* kvm_proc.c */
58 #endif
59 
60 
61 #ifndef _KERNEL
62 /*
63  * This is a temporary hack for when libkvm compiles in this file
64  * from userland.  These functions don't belong here.
65  */
66 static void
timevalfix(struct timeval * t1)67 timevalfix(struct timeval *t1)
68 {
69 
70 	if (t1->tv_usec < 0) {
71 		t1->tv_sec--;
72 		t1->tv_usec += 1000000;
73 	}
74 	if (t1->tv_usec >= 1000000) {
75 		t1->tv_sec++;
76 		t1->tv_usec -= 1000000;
77 	}
78 }
79 
80 static void
timevaladd(struct timeval * t1,const struct timeval * t2)81 timevaladd(struct timeval *t1, const struct timeval *t2)
82 {
83 
84 	t1->tv_sec += t2->tv_sec;
85 	t1->tv_usec += t2->tv_usec;
86 	timevalfix(t1);
87 }
88 
89 static void
ruadd(struct rusage * ru,struct rusage * ru2)90 ruadd(struct rusage *ru, struct rusage *ru2)
91 {
92 	long *ip, *ip2;
93 	int i;
94 
95 	timevaladd(&ru->ru_utime, &ru2->ru_utime);
96 	timevaladd(&ru->ru_stime, &ru2->ru_stime);
97 	if (ru->ru_maxrss < ru2->ru_maxrss)
98 		ru->ru_maxrss = ru2->ru_maxrss;
99 	ip = &ru->ru_first; ip2 = &ru2->ru_first;
100 	for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
101 		*ip++ += *ip2++;
102 }
103 
104 #endif
105 
106 /*
107  * Fill in a struct kinfo_proc, and zero the lwp fields for a possible
108  * fill_kinfo_lwp() aggregation.
109  *
110  * NOTE!  We may be asked to fill in kinfo_proc for a zombied process, and
111  * the process may be in the middle of being deallocated.  Check all pointers
112  * for NULL.
113  *
114  * Caller must hold p->p_token
115  */
116 void
fill_kinfo_proc(struct proc * p,struct kinfo_proc * kp)117 fill_kinfo_proc(struct proc *p, struct kinfo_proc *kp)
118 {
119 	struct session *sess;
120 	struct pgrp *pgrp;
121 	struct vmspace *vm;
122 
123 	pgrp = p->p_pgrp;
124 	sess = pgrp ? pgrp->pg_session : NULL;
125 
126 	bzero(kp, sizeof(*kp));
127 
128 	kp->kp_paddr = (uintptr_t)p;
129 	kp->kp_fd = (uintptr_t)p->p_fd;
130 
131 	kp->kp_flags = p->p_flags;
132 	kp->kp_stat = p->p_stat;
133 	kp->kp_lock = p->p_lock;
134 	kp->kp_acflag = p->p_acflag;
135 	kp->kp_traceflag = p->p_traceflag;
136 	kp->kp_siglist = p->p_siglist;
137 	if (p->p_sigacts) {
138 		kp->kp_sigignore = p->p_sigignore;	/* p_sigacts-> */
139 		kp->kp_sigcatch = p->p_sigcatch;	/* p_sigacts-> */
140 		kp->kp_sigflag = p->p_sigacts->ps_flag;
141 	}
142 	kp->kp_start = p->p_start;
143 
144 	strncpy(kp->kp_comm, p->p_comm, sizeof(kp->kp_comm) - 1);
145 	kp->kp_comm[sizeof(kp->kp_comm) - 1] = 0;
146 
147 	if (p->p_ucred) {
148 		kp->kp_uid = p->p_ucred->cr_uid;
149 		kp->kp_ngroups = p->p_ucred->cr_ngroups;
150 		if (p->p_ucred->cr_groups) {
151 			bcopy(p->p_ucred->cr_groups, kp->kp_groups,
152 			      NGROUPS * sizeof(kp->kp_groups[0]));
153 		}
154 		kp->kp_ruid = p->p_ucred->cr_ruid;
155 		kp->kp_svuid = p->p_ucred->cr_svuid;
156 		kp->kp_rgid = p->p_ucred->cr_rgid;
157 		kp->kp_svgid = p->p_ucred->cr_svgid;
158 
159 		/*
160 		 * Copy just some of the capabilities for now to avoid
161 		 * changing the size of the kp structure.
162 		 */
163 		bcopy(p->p_ucred->cr_caps.caps, kp->kp_syscaps,
164 		      sizeof(kp->kp_syscaps));
165 	}
166 
167 	kp->kp_pid = p->p_pid;
168 	if (p->p_oppid != 0)
169 		kp->kp_ppid = p->p_oppid;
170 	else
171 		kp->kp_ppid = p->p_pptr != NULL ? p->p_pptr->p_pid : -1;
172 	if (pgrp) {
173 		kp->kp_pgid = pgrp->pg_id;
174 		kp->kp_jobc = pgrp->pg_jobc;
175 	}
176 	if (sess) {
177 		kp->kp_sid = sess->s_sid;
178 		bcopy(sess->s_login, kp->kp_login, MAXLOGNAME);
179 		if (sess->s_ttyvp != NULL)
180 			kp->kp_auxflags |= KI_CTTY;
181 		if ((p->p_session != NULL) && SESS_LEADER(p))
182 			kp->kp_auxflags |= KI_SLEADER;
183 	}
184 	if (sess && (p->p_flags & P_CONTROLT) != 0 && sess->s_ttyp != NULL) {
185 		kp->kp_tdev = devid_from_dev(sess->s_ttyp->t_dev);
186 		if (sess->s_ttyp->t_pgrp != NULL)
187 			kp->kp_tpgid = sess->s_ttyp->t_pgrp->pg_id;
188 		else
189 			kp->kp_tpgid = -1;
190 		if (sess->s_ttyp->t_session != NULL)
191 			kp->kp_tsid = sess->s_ttyp->t_session->s_sid;
192 		else
193 			kp->kp_tsid = -1;
194 	} else {
195 		kp->kp_tdev = NOUDEV;
196 	}
197 	kp->kp_exitstat = p->p_xstat;
198 	kp->kp_nthreads = p->p_nthreads;
199 	kp->kp_nice = p->p_nice;
200 	kp->kp_swtime = p->p_swtime;
201 
202 	if ((vm = p->p_vmspace) != NULL) {
203 		kp->kp_vm_map_size = vm->vm_map.size;
204 		kp->kp_vm_rssize = vmspace_resident_count(vm);
205 		kp->kp_vm_swrss = vm->vm_swrss;
206 		kp->kp_vm_tsize = btoc(vm->vm_tsize);
207 		kp->kp_vm_dsize = btoc(vm->vm_dsize);
208 		kp->kp_vm_ssize = btoc(vm->vm_ssize);
209 	}
210 
211 	if (p->p_ucred && jailed(p->p_ucred))
212 		kp->kp_jailid = p->p_ucred->cr_prison->pr_id;
213 
214 	kp->kp_ru = p->p_ru;
215 	kp->kp_cru = p->p_cru;
216 }
217 
218 /*
219  * Fill in a struct kinfo_lwp.  This routine also doubles as an aggregator
220  * of lwps for the proc.
221  *
222  * The kl structure must be initially zerod by the caller.  Note that
223  * fill_kinfo_proc() will do this for us.
224  */
225 void
fill_kinfo_lwp(struct lwp * lwp,struct kinfo_lwp * kl)226 fill_kinfo_lwp(struct lwp *lwp, struct kinfo_lwp *kl)
227 {
228 	kl->kl_pid = lwp->lwp_proc->p_pid;
229 	kl->kl_tid = lwp->lwp_tid;
230 
231 	kl->kl_flags = lwp->lwp_flags;
232 	kl->kl_stat = lwp->lwp_stat;
233 	kl->kl_lock = lwp->lwp_lock;
234 	kl->kl_tdflags = lwp->lwp_thread->td_flags;
235 
236 	/*
237 	 * The process/lwp stat may not reflect whether the process is
238 	 * actually sleeping or not if the related thread was directly
239 	 * descheduled by LWKT.  Adjust the stat if the thread is not
240 	 * runnable and not waiting to be scheduled on a cpu by the
241 	 * user process scheduler.
242 	 */
243 	if (kl->kl_stat == LSRUN) {
244 		if ((kl->kl_tdflags & TDF_RUNQ) == 0 &&
245 		    (lwp->lwp_mpflags & LWP_MP_ONRUNQ) == 0) {
246 			kl->kl_stat = LSSLEEP;
247 		}
248 	}
249 #ifdef _KERNEL
250 	kl->kl_mpcount = get_mplock_count(lwp->lwp_thread);
251 #else
252 	kl->kl_mpcount = 0;
253 #endif
254 
255 	kl->kl_prio = lwp->lwp_usdata.bsd4.priority;	/* XXX TGEN dangerous assumption */
256 	kl->kl_tdprio = lwp->lwp_thread->td_pri;
257 	kl->kl_rtprio = lwp->lwp_rtprio;
258 
259 	kl->kl_uticks += lwp->lwp_thread->td_uticks;
260 	kl->kl_sticks += lwp->lwp_thread->td_sticks;
261 	kl->kl_iticks += lwp->lwp_thread->td_iticks;
262 	kl->kl_cpticks += lwp->lwp_cpticks;
263 	kl->kl_pctcpu += lwp->lwp_proc->p_stat == SZOMB ? 0 : lwp->lwp_pctcpu;
264 	kl->kl_slptime += lwp->lwp_slptime;
265 	kl->kl_origcpu = lwp->lwp_usdata.bsd4.batch;
266 	kl->kl_estcpu = lwp->lwp_usdata.bsd4.estcpu;
267 	kl->kl_cpuid = lwp->lwp_thread->td_gd->gd_cpuid;
268 
269 	ruadd(&kl->kl_ru, &lwp->lwp_ru);
270 
271 	kl->kl_siglist = lwp->lwp_siglist;
272 	kl->kl_sigmask = lwp->lwp_sigmask;
273 
274 	kl->kl_wchan = (uintptr_t)lwp->lwp_thread->td_wchan;
275 	if (lwp->lwp_thread->td_wmesg) {
276 		strncpy(kl->kl_wmesg, lwp->lwp_thread->td_wmesg, WMESGLEN);
277 		kl->kl_wmesg[WMESGLEN] = 0;
278 	}
279 	strlcpy(kl->kl_comm, lwp->lwp_thread->td_comm, sizeof(kl->kl_comm));
280 }
281 
282 /*
283  * Fill in a struct kinfo_proc for kernel threads (i.e. those without proc).
284  */
285 void
fill_kinfo_proc_kthread(struct thread * td,struct kinfo_proc * kp)286 fill_kinfo_proc_kthread(struct thread *td, struct kinfo_proc *kp)
287 {
288 	bzero(kp, sizeof(*kp));
289 
290 	/*
291 	 * Fill in fake proc information and semi-fake lwp info.
292 	 */
293 	kp->kp_pid = -1;
294 	kp->kp_tdev = NOUDEV;
295 	strncpy(kp->kp_comm, td->td_comm, sizeof(kp->kp_comm) - 1);
296 	kp->kp_comm[sizeof(kp->kp_comm) - 1] = 0;
297 	kp->kp_flags = P_SYSTEM;
298 	if (td != &td->td_gd->gd_idlethread)
299 		kp->kp_stat = SACTIVE;
300 	else
301 		kp->kp_stat = SIDL;
302 	kp->kp_nthreads = 1;
303 	kp->kp_ktaddr = (uintptr_t)td;
304 
305 	kp->kp_lwp.kl_pid = -1;
306 	kp->kp_lwp.kl_tid = -1;
307 	kp->kp_lwp.kl_tdflags = td->td_flags;
308 #ifdef _KERNEL
309 	kp->kp_lwp.kl_mpcount = get_mplock_count(td);
310 #else
311 	kp->kp_lwp.kl_mpcount = 0;
312 #endif
313 
314 	kp->kp_lwp.kl_tdprio = td->td_pri;
315 	kp->kp_lwp.kl_rtprio.type = RTP_PRIO_THREAD;
316 	kp->kp_lwp.kl_rtprio.prio = td->td_pri;
317 
318 	kp->kp_lwp.kl_uticks = td->td_uticks;
319 	kp->kp_lwp.kl_sticks = td->td_sticks;
320 	kp->kp_lwp.kl_iticks = td->td_iticks;
321 	kp->kp_lwp.kl_cpuid = td->td_gd->gd_cpuid;
322 
323 	kp->kp_lwp.kl_wchan = (uintptr_t)td->td_wchan;
324 	if (td->td_flags & TDF_RUNQ)
325 		kp->kp_lwp.kl_stat = LSRUN;
326 	else
327 		kp->kp_lwp.kl_stat = LSSLEEP;
328 	if (td->td_wmesg) {
329 		strncpy(kp->kp_lwp.kl_wmesg, td->td_wmesg, WMESGLEN);
330 		kp->kp_lwp.kl_wmesg[WMESGLEN] = 0;
331 	}
332 	strlcpy(kp->kp_lwp.kl_comm, td->td_comm, sizeof(kp->kp_lwp.kl_comm));
333 }
334