1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)kern_proc.c 7.3 (Berkeley) 10/18/88 7 */ 8 9 #include "../machine/reg.h" 10 #include "../machine/pte.h" 11 #include "../machine/psl.h" 12 13 #include "param.h" 14 #include "systm.h" 15 #include "map.h" 16 #include "dir.h" 17 #include "user.h" 18 #include "kernel.h" 19 #include "proc.h" 20 #include "buf.h" 21 #include "seg.h" 22 #include "acct.h" 23 #include "wait.h" 24 #include "vm.h" 25 #include "text.h" 26 #include "file.h" 27 #include "quota.h" 28 #include "uio.h" 29 #include "malloc.h" 30 #include "mbuf.h" 31 #include "tty.h" 32 33 /* 34 * Clear any pending stops for top and all descendents. 35 */ 36 spgrp(top) 37 struct proc *top; 38 { 39 register struct proc *p; 40 int f = 0; 41 42 p = top; 43 for (;;) { 44 p->p_sig &= 45 ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); 46 f++; 47 /* 48 * If this process has children, descend to them next, 49 * otherwise do any siblings, and if done with this level, 50 * follow back up the tree (but not past top). 51 */ 52 if (p->p_cptr) 53 p = p->p_cptr; 54 else if (p == top) 55 return (f); 56 else if (p->p_osptr) 57 p = p->p_osptr; 58 else for (;;) { 59 p = p->p_pptr; 60 if (p == top) 61 return (f); 62 if (p->p_osptr) { 63 p = p->p_osptr; 64 break; 65 } 66 } 67 } 68 } 69 70 /* 71 * Is p an inferior of the current process? 72 */ 73 inferior(p) 74 register struct proc *p; 75 { 76 for (; p != u.u_procp; p = p->p_pptr) 77 if (p->p_ppid == 0) 78 return (0); 79 return (1); 80 } 81 82 struct proc * 83 pfind(pid) 84 register pid; 85 { 86 register struct proc *p; 87 88 for (p = &proc[pidhash[PIDHASH(pid)]] ; 89 p != &proc[0]; p = &proc[p->p_idhash]) 90 if (p->p_pid == pid) 91 return (p); 92 return ((struct proc *)0); 93 } 94 95 /* 96 * Locate a process group by number 97 */ 98 struct pgrp * 99 pgfind(pgid) 100 register pid_t pgid; 101 { 102 register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; 103 104 for (; pgrp; pgrp = pgrp->pg_hforw) 105 if (pgrp->pg_id == pgid) 106 return(pgrp); 107 return ((struct pgrp *)0); 108 } 109 110 /* 111 * Move p to a new or existing process group (and session) 112 */ 113 pgmv(p, pgid, mksess) 114 register struct proc *p; 115 pid_t pgid; 116 { 117 register struct pgrp *pgrp = pgfind(pgid); 118 register struct proc **pp = &p->p_pgrp->pg_mem; 119 register struct proc *cp; 120 register n; 121 122 if (pgrp && mksess) /* firewalls */ 123 panic("pgmv: setsid into non-empty pgrp %d\n", pgid); 124 if (SESS_LEADER(p)) 125 panic("pgmv: session leader attempted setpgrp\n"); 126 if (!pgrp) { 127 /* 128 * new process group 129 */ 130 if (p->p_pid != pgid) 131 panic("pgmv: new pgrp and pid != pgid\n"); 132 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 133 M_WAITOK); 134 if (mksess) { 135 register struct session *sess; 136 /* 137 * new session 138 */ 139 MALLOC(sess, struct session *, sizeof(struct session), 140 M_SESSION, M_WAITOK); 141 sess->s_leader = p; 142 sess->s_count = 1; 143 pgrp->pg_session = sess; 144 if (p != u.u_procp) 145 panic("pgmv: mksession and p != u.u_procp"); 146 u.u_ttyp = 0; 147 u.u_ttyd = 0; 148 } else { 149 pgrp->pg_session = p->p_session; 150 pgrp->pg_session->s_count++; 151 } 152 pgrp->pg_id = pgid; 153 pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)]; 154 pgrphash[n] = pgrp; 155 pgrp->pg_jobc = 0; 156 pgrp->pg_mem = 0; 157 } 158 /* 159 * adjust eligibility of affected pgrps to participate in job control 160 */ 161 if (PGRP_JOBC(p)) 162 p->p_pgrp->pg_jobc--; 163 for (cp = p->p_cptr; cp; cp = cp->p_osptr) 164 if (PGRP_JOBC(cp)) 165 cp->p_pgrp->pg_jobc--; 166 /* 167 * unlink p from old process group 168 */ 169 for (; *pp; pp = &(*pp)->p_pgrpnxt) 170 if (*pp == p) { 171 *pp = p->p_pgrpnxt; 172 goto done; 173 } 174 panic("pgmv: can't find p on old pgrp\n"); 175 done: 176 /* 177 * link into new one 178 */ 179 p->p_pgrpnxt = pgrp->pg_mem; 180 pgrp->pg_mem = p; 181 p->p_pgrp = pgrp; 182 /* 183 * adjust eligibility of affected pgrps to participate in job control 184 */ 185 if (PGRP_JOBC(p)) 186 p->p_pgrp->pg_jobc++; 187 for (cp = p->p_cptr; cp; cp = cp->p_osptr) 188 if (PGRP_JOBC(cp)) 189 cp->p_pgrp->pg_jobc++; 190 /* 191 * old pgrp empty? 192 */ 193 if (!p->p_pgrp->pg_mem) 194 pgdelete(p->p_pgrp); 195 } 196 197 /* 198 * remove process from process group 199 */ 200 pgrm(p) 201 register struct proc *p; 202 { 203 register struct proc **pp = &p->p_pgrp->pg_mem; 204 register struct proc *cp; 205 206 for (; *pp; pp = &(*pp)->p_pgrpnxt) 207 if (*pp == p) { 208 *pp = p->p_pgrpnxt; 209 goto done; 210 } 211 panic("pgrm: can't find p in pgrp\n"); 212 done: 213 if (!p->p_pgrp->pg_mem) 214 pgdelete(p->p_pgrp); 215 p->p_pgrp = 0; 216 } 217 218 /* 219 * delete a process group 220 */ 221 pgdelete(pgrp) 222 register struct pgrp *pgrp; 223 { 224 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 225 226 for (; *pgp; pgp = &(*pgp)->pg_hforw) 227 if (*pgp == pgrp) { 228 *pgp = pgrp->pg_hforw; 229 goto done; 230 } 231 panic("pgdelete: can't find pgrp on hash chain\n"); 232 done: 233 if (--pgrp->pg_session->s_count == 0) 234 FREE(pgrp->pg_session, M_SESSION); 235 FREE(pgrp, M_PGRP); 236 } 237 238 /* 239 * init the process queues 240 */ 241 pqinit() 242 { 243 register struct proc *p; 244 245 /* 246 * most procs are initially on freequeue 247 * nb: we place them there in their "natural" order. 248 */ 249 250 freeproc = NULL; 251 for (p = procNPROC; --p > proc; freeproc = p) 252 p->p_nxt = freeproc; 253 254 /* 255 * but proc[0] is special ... 256 */ 257 258 allproc = p; 259 p->p_nxt = NULL; 260 p->p_prev = &allproc; 261 262 zombproc = NULL; 263 } 264 265 /* DEBUG */ 266 pgrpdump() 267 { 268 register struct pgrp *pgrp; 269 register struct proc *p; 270 register i; 271 272 for (i=0; i<PIDHSZ; i++) { 273 if (pgrphash[i]) { 274 printf("\tindx %d\n", i); 275 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 276 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 277 pgrp, pgrp->pg_id, pgrp->pg_session, 278 pgrp->pg_session->s_count, pgrp->pg_mem); 279 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 280 printf("\t\tpid %d addr %x pgrp %x\n", 281 p->p_pid, p, p->p_pgrp); 282 } 283 } 284 285 } 286 } 287 } 288