xref: /dragonfly/sys/kern/kern_kinfo.c (revision e98bdfd3)
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 #include <sys/sysref.h>
55 #include <sys/sysref2.h>
56 #else
57 #include <string.h>
58 
59 dev_t dev2udev(cdev_t dev);	/* kvm_proc.c */
60 #endif
61 
62 
63 /*
64  * Fill in a struct kinfo_proc.
65  *
66  * NOTE!  We may be asked to fill in kinfo_proc for a zombied process, and
67  * the process may be in the middle of being deallocated.  Check all pointers
68  * for NULL.
69  *
70  * Caller must hold p->p_token
71  */
72 void
73 fill_kinfo_proc(struct proc *p, struct kinfo_proc *kp)
74 {
75 	struct session *sess;
76 	struct pgrp *pgrp;
77 	struct vmspace *vm;
78 
79 	pgrp = p->p_pgrp;
80 	sess = pgrp ? pgrp->pg_session : NULL;
81 
82 	bzero(kp, sizeof(*kp));
83 
84 	kp->kp_paddr = (uintptr_t)p;
85 	kp->kp_fd = (uintptr_t)p->p_fd;
86 
87 	kp->kp_flags = p->p_flags;
88 	kp->kp_stat = p->p_stat;
89 	kp->kp_lock = p->p_lock;
90 	kp->kp_acflag = p->p_acflag;
91 	kp->kp_traceflag = p->p_traceflag;
92 	kp->kp_siglist = p->p_siglist;
93 	if (p->p_sigacts) {
94 		kp->kp_sigignore = p->p_sigignore;	/* p_sigacts-> */
95 		kp->kp_sigcatch = p->p_sigcatch;	/* p_sigacts-> */
96 		kp->kp_sigflag = p->p_sigacts->ps_flag;
97 	}
98 	kp->kp_start = p->p_start;
99 
100 	strncpy(kp->kp_comm, p->p_comm, sizeof(kp->kp_comm) - 1);
101 	kp->kp_comm[sizeof(kp->kp_comm) - 1] = 0;
102 
103 	if (p->p_ucred) {
104 		kp->kp_uid = p->p_ucred->cr_uid;
105 		kp->kp_ngroups = p->p_ucred->cr_ngroups;
106 		if (p->p_ucred->cr_groups) {
107 			bcopy(p->p_ucred->cr_groups, kp->kp_groups,
108 			      NGROUPS * sizeof(kp->kp_groups[0]));
109 		}
110 		kp->kp_ruid = p->p_ucred->cr_ruid;
111 		kp->kp_svuid = p->p_ucred->cr_svuid;
112 		kp->kp_rgid = p->p_ucred->cr_rgid;
113 		kp->kp_svgid = p->p_ucred->cr_svgid;
114 	}
115 
116 	kp->kp_pid = p->p_pid;
117 	if (p->p_oppid != 0)
118 		kp->kp_ppid = p->p_oppid;
119 	else
120 		kp->kp_ppid = p->p_pptr != NULL ? p->p_pptr->p_pid : -1;
121 	if (pgrp) {
122 		kp->kp_pgid = pgrp->pg_id;
123 		kp->kp_jobc = pgrp->pg_jobc;
124 	}
125 	if (sess) {
126 		kp->kp_sid = sess->s_sid;
127 		bcopy(sess->s_login, kp->kp_login, MAXLOGNAME);
128 		if (sess->s_ttyvp != NULL)
129 			kp->kp_auxflags |= KI_CTTY;
130 		if ((p->p_session != NULL) && SESS_LEADER(p))
131 			kp->kp_auxflags |= KI_SLEADER;
132 	}
133 	if (sess && (p->p_flags & P_CONTROLT) != 0 && sess->s_ttyp != NULL) {
134 		kp->kp_tdev = dev2udev(sess->s_ttyp->t_dev);
135 		if (sess->s_ttyp->t_pgrp != NULL)
136 			kp->kp_tpgid = sess->s_ttyp->t_pgrp->pg_id;
137 		else
138 			kp->kp_tpgid = -1;
139 		if (sess->s_ttyp->t_session != NULL)
140 			kp->kp_tsid = sess->s_ttyp->t_session->s_sid;
141 		else
142 			kp->kp_tsid = -1;
143 	} else {
144 		kp->kp_tdev = NOUDEV;
145 	}
146 	kp->kp_exitstat = p->p_xstat;
147 	kp->kp_nthreads = p->p_nthreads;
148 	kp->kp_nice = p->p_nice;
149 	kp->kp_swtime = p->p_swtime;
150 
151 	if ((vm = p->p_vmspace) != NULL) {
152 		kp->kp_vm_map_size = vm->vm_map.size;
153 		kp->kp_vm_rssize = vmspace_resident_count(vm);
154 #ifdef _KERNEL
155 		/*XXX MP RACES */
156 		/*kp->kp_vm_prssize = vmspace_president_count(vm);*/
157 #endif
158 		kp->kp_vm_swrss = vm->vm_swrss;
159 		kp->kp_vm_tsize = vm->vm_tsize;
160 		kp->kp_vm_dsize = vm->vm_dsize;
161 		kp->kp_vm_ssize = vm->vm_ssize;
162 	}
163 
164 	if (p->p_ucred && jailed(p->p_ucred))
165 		kp->kp_jailid = p->p_ucred->cr_prison->pr_id;
166 
167 	kp->kp_ru = p->p_ru;
168 	kp->kp_cru = p->p_cru;
169 }
170 
171 /*
172  * Fill in a struct kinfo_lwp.
173  */
174 void
175 fill_kinfo_lwp(struct lwp *lwp, struct kinfo_lwp *kl)
176 {
177 	bzero(kl, sizeof(*kl));
178 
179 	kl->kl_pid = lwp->lwp_proc->p_pid;
180 	kl->kl_tid = lwp->lwp_tid;
181 
182 	kl->kl_flags = lwp->lwp_flags;
183 	kl->kl_stat = lwp->lwp_stat;
184 	kl->kl_lock = lwp->lwp_lock;
185 	kl->kl_tdflags = lwp->lwp_thread->td_flags;
186 
187 	/*
188 	 * The process/lwp stat may not reflect whether the process is
189 	 * actually sleeping or not if the related thread was directly
190 	 * descheduled by LWKT.  Adjust the stat if the thread is not
191 	 * runnable and not waiting to be scheduled on a cpu by the
192 	 * user process scheduler.
193 	 */
194 	if (kl->kl_stat == LSRUN) {
195 		if ((kl->kl_tdflags & TDF_RUNQ) == 0 &&
196 		    (lwp->lwp_mpflags & LWP_MP_ONRUNQ) == 0) {
197 			kl->kl_stat = LSSLEEP;
198 		}
199 	}
200 #ifdef _KERNEL
201 	kl->kl_mpcount = get_mplock_count(lwp->lwp_thread);
202 #else
203 	kl->kl_mpcount = 0;
204 #endif
205 
206 	kl->kl_prio = lwp->lwp_usdata.bsd4.priority;	/* XXX TGEN dangerous assumption */
207 	kl->kl_tdprio = lwp->lwp_thread->td_pri;
208 	kl->kl_rtprio = lwp->lwp_rtprio;
209 
210 	kl->kl_uticks = lwp->lwp_thread->td_uticks;
211 	kl->kl_sticks = lwp->lwp_thread->td_sticks;
212 	kl->kl_iticks = lwp->lwp_thread->td_iticks;
213 	kl->kl_cpticks = lwp->lwp_cpticks;
214 	kl->kl_pctcpu = lwp->lwp_proc->p_stat == SZOMB ? 0 : lwp->lwp_pctcpu;
215 	kl->kl_slptime = lwp->lwp_slptime;
216 	kl->kl_origcpu = lwp->lwp_usdata.bsd4.batch;
217 	kl->kl_estcpu = lwp->lwp_usdata.bsd4.estcpu;
218 	kl->kl_cpuid = lwp->lwp_thread->td_gd->gd_cpuid;
219 
220 	kl->kl_ru = lwp->lwp_ru;
221 
222 	kl->kl_siglist = lwp->lwp_siglist;
223 	kl->kl_sigmask = lwp->lwp_sigmask;
224 
225 	kl->kl_wchan = (uintptr_t)lwp->lwp_thread->td_wchan;
226 	if (lwp->lwp_thread->td_wmesg) {
227 		strncpy(kl->kl_wmesg, lwp->lwp_thread->td_wmesg, WMESGLEN);
228 		kl->kl_wmesg[WMESGLEN] = 0;
229 	}
230 	strlcpy(kl->kl_comm, lwp->lwp_thread->td_comm, sizeof(kl->kl_comm));
231 }
232 
233 /*
234  * Fill in a struct kinfo_proc for kernel threads (i.e. those without proc).
235  */
236 void
237 fill_kinfo_proc_kthread(struct thread *td, struct kinfo_proc *kp)
238 {
239 	bzero(kp, sizeof(*kp));
240 
241 	/*
242 	 * Fill in fake proc information and semi-fake lwp info.
243 	 */
244 	kp->kp_pid = -1;
245 	kp->kp_tdev = NOUDEV;
246 	strncpy(kp->kp_comm, td->td_comm, sizeof(kp->kp_comm) - 1);
247 	kp->kp_comm[sizeof(kp->kp_comm) - 1] = 0;
248 	kp->kp_flags = P_SYSTEM;
249 	if (td != &td->td_gd->gd_idlethread)
250 		kp->kp_stat = SACTIVE;
251 	else
252 		kp->kp_stat = SIDL;
253 	kp->kp_nthreads = 1;
254 	kp->kp_ktaddr = (uintptr_t)td;
255 
256 	kp->kp_lwp.kl_pid = -1;
257 	kp->kp_lwp.kl_tid = -1;
258 	kp->kp_lwp.kl_tdflags = td->td_flags;
259 #ifdef _KERNEL
260 	kp->kp_lwp.kl_mpcount = get_mplock_count(td);
261 #else
262 	kp->kp_lwp.kl_mpcount = 0;
263 #endif
264 
265 	kp->kp_lwp.kl_tdprio = td->td_pri;
266 	kp->kp_lwp.kl_rtprio.type = RTP_PRIO_THREAD;
267 	kp->kp_lwp.kl_rtprio.prio = td->td_pri;
268 
269 	kp->kp_lwp.kl_uticks = td->td_uticks;
270 	kp->kp_lwp.kl_sticks = td->td_sticks;
271 	kp->kp_lwp.kl_iticks = td->td_iticks;
272 	kp->kp_lwp.kl_cpuid = td->td_gd->gd_cpuid;
273 
274 	kp->kp_lwp.kl_wchan = (uintptr_t)td->td_wchan;
275 	if (td->td_flags & TDF_RUNQ)
276 		kp->kp_lwp.kl_stat = LSRUN;
277 	else
278 		kp->kp_lwp.kl_stat = LSSLEEP;
279 	if (td->td_wmesg) {
280 		strncpy(kp->kp_lwp.kl_wmesg, td->td_wmesg, WMESGLEN);
281 		kp->kp_lwp.kl_wmesg[WMESGLEN] = 0;
282 	}
283 	strlcpy(kp->kp_lwp.kl_comm, td->td_comm, sizeof(kp->kp_lwp.kl_comm));
284 }
285