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