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 #ifdef _KERNEL 153 /*sysref_get(&vm->vm_sysref);*/ 154 /*lwkt_gettoken(&vm->vm_map.token);*/ 155 #endif 156 kp->kp_vm_map_size = vm->vm_map.size; 157 kp->kp_vm_rssize = vmspace_resident_count(vm); 158 #ifdef _KERNEL 159 /*XXX MP RACES */ 160 /*kp->kp_vm_prssize = vmspace_president_count(vm);*/ 161 #endif 162 kp->kp_vm_swrss = vm->vm_swrss; 163 kp->kp_vm_tsize = vm->vm_tsize; 164 kp->kp_vm_dsize = vm->vm_dsize; 165 kp->kp_vm_ssize = vm->vm_ssize; 166 #ifdef _KERNEL 167 /*lwkt_reltoken(&vm->vm_map.token);*/ 168 /*sysref_put(&vm->vm_sysref);*/ 169 #endif 170 } 171 172 if (p->p_ucred && jailed(p->p_ucred)) 173 kp->kp_jailid = p->p_ucred->cr_prison->pr_id; 174 175 kp->kp_ru = p->p_ru; 176 kp->kp_cru = p->p_cru; 177 } 178 179 /* 180 * Fill in a struct kinfo_lwp. 181 */ 182 void 183 fill_kinfo_lwp(struct lwp *lwp, struct kinfo_lwp *kl) 184 { 185 bzero(kl, sizeof(*kl)); 186 187 kl->kl_pid = lwp->lwp_proc->p_pid; 188 kl->kl_tid = lwp->lwp_tid; 189 190 kl->kl_flags = lwp->lwp_flags; 191 kl->kl_stat = lwp->lwp_stat; 192 kl->kl_lock = lwp->lwp_lock; 193 kl->kl_tdflags = lwp->lwp_thread->td_flags; 194 195 /* 196 * The process/lwp stat may not reflect whether the process is 197 * actually sleeping or not if the related thread was directly 198 * descheduled by LWKT. Adjust the stat if the thread is not 199 * runnable and not waiting to be scheduled on a cpu by the 200 * user process scheduler. 201 */ 202 if (kl->kl_stat == LSRUN) { 203 if ((kl->kl_tdflags & TDF_RUNQ) == 0 && 204 (lwp->lwp_mpflags & LWP_MP_ONRUNQ) == 0) { 205 kl->kl_stat = LSSLEEP; 206 } 207 } 208 #ifdef _KERNEL 209 kl->kl_mpcount = get_mplock_count(lwp->lwp_thread); 210 #else 211 kl->kl_mpcount = 0; 212 #endif 213 214 kl->kl_prio = lwp->lwp_usdata.bsd4.priority; /* XXX TGEN dangerous assumption */ 215 kl->kl_tdprio = lwp->lwp_thread->td_pri; 216 kl->kl_rtprio = lwp->lwp_rtprio; 217 218 kl->kl_uticks = lwp->lwp_thread->td_uticks; 219 kl->kl_sticks = lwp->lwp_thread->td_sticks; 220 kl->kl_iticks = lwp->lwp_thread->td_iticks; 221 kl->kl_cpticks = lwp->lwp_cpticks; 222 kl->kl_pctcpu = lwp->lwp_pctcpu; 223 kl->kl_slptime = lwp->lwp_slptime; 224 kl->kl_origcpu = lwp->lwp_usdata.bsd4.batch; 225 kl->kl_estcpu = lwp->lwp_usdata.bsd4.estcpu; 226 kl->kl_cpuid = lwp->lwp_thread->td_gd->gd_cpuid; 227 228 kl->kl_ru = lwp->lwp_ru; 229 230 kl->kl_siglist = lwp->lwp_siglist; 231 kl->kl_sigmask = lwp->lwp_sigmask; 232 233 kl->kl_wchan = (uintptr_t)lwp->lwp_thread->td_wchan; 234 if (lwp->lwp_thread->td_wmesg) { 235 strncpy(kl->kl_wmesg, lwp->lwp_thread->td_wmesg, WMESGLEN); 236 kl->kl_wmesg[WMESGLEN] = 0; 237 } 238 } 239 240 /* 241 * Fill in a struct kinfo_proc for kernel threads (i.e. those without proc). 242 */ 243 void 244 fill_kinfo_proc_kthread(struct thread *td, struct kinfo_proc *kp) 245 { 246 bzero(kp, sizeof(*kp)); 247 248 /* 249 * Fill in fake proc information and semi-fake lwp info. 250 */ 251 kp->kp_pid = -1; 252 kp->kp_tdev = NOUDEV; 253 strncpy(kp->kp_comm, td->td_comm, sizeof(kp->kp_comm) - 1); 254 kp->kp_comm[sizeof(kp->kp_comm) - 1] = 0; 255 kp->kp_flags = P_SYSTEM; 256 kp->kp_stat = SACTIVE; 257 258 kp->kp_lwp.kl_pid = -1; 259 kp->kp_lwp.kl_tid = -1; 260 kp->kp_lwp.kl_tdflags = td->td_flags; 261 #ifdef _KERNEL 262 kp->kp_lwp.kl_mpcount = get_mplock_count(td); 263 #else 264 kp->kp_lwp.kl_mpcount = 0; 265 #endif 266 267 kp->kp_lwp.kl_tdprio = td->td_pri; 268 kp->kp_lwp.kl_rtprio.type = RTP_PRIO_THREAD; 269 kp->kp_lwp.kl_rtprio.prio = td->td_pri; 270 271 kp->kp_lwp.kl_uticks = td->td_uticks; 272 kp->kp_lwp.kl_sticks = td->td_sticks; 273 kp->kp_lwp.kl_iticks = td->td_iticks; 274 kp->kp_lwp.kl_cpuid = td->td_gd->gd_cpuid; 275 276 kp->kp_lwp.kl_wchan = (uintptr_t)td->td_wchan; 277 if (td->td_flags & TDF_RUNQ) 278 kp->kp_lwp.kl_stat = LSRUN; 279 else 280 kp->kp_lwp.kl_stat = LSSLEEP; 281 if (td->td_wmesg) { 282 strncpy(kp->kp_lwp.kl_wmesg, td->td_wmesg, WMESGLEN); 283 kp->kp_lwp.kl_wmesg[WMESGLEN] = 0; 284 } 285 } 286