123371Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423371Smckusick * 537728Smckusick * Redistribution and use in source and binary forms are permitted 637728Smckusick * provided that the above copyright notice and this paragraph are 737728Smckusick * duplicated in all such forms and that any documentation, 837728Smckusick * advertising materials, and other materials related to such 937728Smckusick * distribution and use acknowledge that the software was developed 1037728Smckusick * by the University of California, Berkeley. The name of the 1137728Smckusick * University may not be used to endorse or promote products derived 1237728Smckusick * from this software without specific prior written permission. 1337728Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437728Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537728Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637728Smckusick * 17*44387Smarc * @(#)kern_proc.c 7.10 (Berkeley) 06/28/90 1823371Smckusick */ 1936Sbill 2017091Sbloom #include "param.h" 2117091Sbloom #include "systm.h" 2217091Sbloom #include "map.h" 2317091Sbloom #include "user.h" 2417091Sbloom #include "kernel.h" 2517091Sbloom #include "proc.h" 2617091Sbloom #include "buf.h" 2717091Sbloom #include "seg.h" 2817091Sbloom #include "acct.h" 2917091Sbloom #include "wait.h" 3017091Sbloom #include "vm.h" 3117091Sbloom #include "text.h" 3217091Sbloom #include "file.h" 3337728Smckusick #include "../ufs/quota.h" 3417091Sbloom #include "uio.h" 3535810Smarc #include "malloc.h" 3617091Sbloom #include "mbuf.h" 3739064Smarc #include "ioctl.h" 3835810Smarc #include "tty.h" 3936Sbill 4037524Smckusick #include "machine/reg.h" 4137524Smckusick #include "machine/pte.h" 4237524Smckusick #include "machine/psl.h" 4337524Smckusick 4417540Skarels /* 457497Sroot * Is p an inferior of the current process? 4636Sbill */ 477497Sroot inferior(p) 487816Sroot register struct proc *p; 4936Sbill { 507497Sroot for (; p != u.u_procp; p = p->p_pptr) 517497Sroot if (p->p_ppid == 0) 527497Sroot return (0); 537497Sroot return (1); 5436Sbill } 557816Sroot 5640709Skarels /* 5740709Skarels * Locate a process by number 5840709Skarels */ 597816Sroot struct proc * 607816Sroot pfind(pid) 6135810Smarc register pid; 627816Sroot { 6340709Skarels register struct proc *p = pidhash[PIDHASH(pid)]; 647816Sroot 6540709Skarels for (; p; p = p->p_hash) 667816Sroot if (p->p_pid == pid) 677816Sroot return (p); 687816Sroot return ((struct proc *)0); 697816Sroot } 7016529Skarels 7116529Skarels /* 7235810Smarc * Locate a process group by number 7335810Smarc */ 7435810Smarc struct pgrp * 7535810Smarc pgfind(pgid) 7635810Smarc register pid_t pgid; 7735810Smarc { 7835810Smarc register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; 7935810Smarc 8035810Smarc for (; pgrp; pgrp = pgrp->pg_hforw) 8135810Smarc if (pgrp->pg_id == pgid) 8240709Skarels return (pgrp); 8335810Smarc return ((struct pgrp *)0); 8435810Smarc } 8535810Smarc 8635810Smarc /* 8735810Smarc * Move p to a new or existing process group (and session) 8835810Smarc */ 8935810Smarc pgmv(p, pgid, mksess) 9035810Smarc register struct proc *p; 9135810Smarc pid_t pgid; 9235810Smarc { 9335810Smarc register struct pgrp *pgrp = pgfind(pgid); 9435810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 9535810Smarc register struct proc *cp; 9637589Smarc struct pgrp *opgrp; 9735810Smarc register n; 9835810Smarc 9939562Smarc #ifdef DIAGNOSTIC 10035810Smarc if (pgrp && mksess) /* firewalls */ 10137589Smarc panic("pgmv: setsid into non-empty pgrp"); 10235810Smarc if (SESS_LEADER(p)) 10337589Smarc panic("pgmv: session leader attempted setpgrp"); 10439562Smarc #endif 10537589Smarc if (pgrp == NULL) { 10635810Smarc /* 10735810Smarc * new process group 10835810Smarc */ 10939562Smarc #ifdef DIAGNOSTIC 11035810Smarc if (p->p_pid != pgid) 11137589Smarc panic("pgmv: new pgrp and pid != pgid"); 11239562Smarc #endif 11335810Smarc MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 11435810Smarc M_WAITOK); 11535810Smarc if (mksess) { 11635810Smarc register struct session *sess; 11735810Smarc /* 11835810Smarc * new session 11935810Smarc */ 12035810Smarc MALLOC(sess, struct session *, sizeof(struct session), 12135810Smarc M_SESSION, M_WAITOK); 12235810Smarc sess->s_leader = p; 12335810Smarc sess->s_count = 1; 12439562Smarc sess->s_ttyvp = NULL; 12539562Smarc sess->s_ttyp = NULL; 12639562Smarc p->p_flag &= ~SCTTY; 12735810Smarc pgrp->pg_session = sess; 12839562Smarc #ifdef DIAGNOSTIC 12935810Smarc if (p != u.u_procp) 13035810Smarc panic("pgmv: mksession and p != u.u_procp"); 13139562Smarc #endif 13235810Smarc } else { 13335810Smarc pgrp->pg_session = p->p_session; 13435810Smarc pgrp->pg_session->s_count++; 13535810Smarc } 13635810Smarc pgrp->pg_id = pgid; 13735810Smarc pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)]; 13835810Smarc pgrphash[n] = pgrp; 13935810Smarc pgrp->pg_jobc = 0; 14039562Smarc pgrp->pg_mem = NULL; 141*44387Smarc } else if (pgrp == p->p_pgrp) 142*44387Smarc return; 14335810Smarc /* 14435810Smarc * adjust eligibility of affected pgrps to participate in job control 14535810Smarc */ 146*44387Smarc fixjobc(p, 0); 14735810Smarc /* 14835810Smarc * unlink p from old process group 14935810Smarc */ 15035810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 15135810Smarc if (*pp == p) { 15235810Smarc *pp = p->p_pgrpnxt; 15335810Smarc goto done; 15435810Smarc } 15537589Smarc panic("pgmv: can't find p on old pgrp"); 15635810Smarc done: 15735810Smarc /* 15835810Smarc * link into new one 15935810Smarc */ 16035810Smarc p->p_pgrpnxt = pgrp->pg_mem; 16135810Smarc pgrp->pg_mem = p; 16237589Smarc opgrp = p->p_pgrp; 16335810Smarc p->p_pgrp = pgrp; 16435810Smarc /* 16535810Smarc * adjust eligibility of affected pgrps to participate in job control 16635810Smarc */ 167*44387Smarc fixjobc(p, 1); 16835810Smarc /* 169*44387Smarc * delete old if empty 17035810Smarc */ 17137589Smarc if (!opgrp->pg_mem) 17237589Smarc pgdelete(opgrp); 17335810Smarc } 17435810Smarc 17535810Smarc /* 17635810Smarc * remove process from process group 17735810Smarc */ 17835810Smarc pgrm(p) 17935810Smarc register struct proc *p; 18035810Smarc { 18135810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 18235810Smarc 18335810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 18435810Smarc if (*pp == p) { 18535810Smarc *pp = p->p_pgrpnxt; 18635810Smarc goto done; 18735810Smarc } 18837589Smarc panic("pgrm: can't find p in pgrp"); 18935810Smarc done: 19035810Smarc if (!p->p_pgrp->pg_mem) 19135810Smarc pgdelete(p->p_pgrp); 19235810Smarc p->p_pgrp = 0; 19335810Smarc } 19435810Smarc 19535810Smarc /* 19635810Smarc * delete a process group 19735810Smarc */ 19835810Smarc pgdelete(pgrp) 19935810Smarc register struct pgrp *pgrp; 20035810Smarc { 20135810Smarc register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 20235810Smarc 20339562Smarc if (pgrp->pg_session->s_ttyp != NULL && 20439562Smarc pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 20539562Smarc pgrp->pg_session->s_ttyp->t_pgrp = NULL; 20635810Smarc for (; *pgp; pgp = &(*pgp)->pg_hforw) 20735810Smarc if (*pgp == pgrp) { 20835810Smarc *pgp = pgrp->pg_hforw; 20935810Smarc goto done; 21035810Smarc } 21137589Smarc panic("pgdelete: can't find pgrp on hash chain"); 21235810Smarc done: 21335810Smarc if (--pgrp->pg_session->s_count == 0) 21435810Smarc FREE(pgrp->pg_session, M_SESSION); 21535810Smarc FREE(pgrp, M_PGRP); 21635810Smarc } 21735810Smarc 21835810Smarc /* 219*44387Smarc * Adjust pgrp jobc counter. 220*44387Smarc * flag == 0 => p is leaving current state. 221*44387Smarc * flag == 1 => p is entering current state. 222*44387Smarc */ 223*44387Smarc fixjobc(p, flag) 224*44387Smarc register struct proc *p; 225*44387Smarc register flag; 226*44387Smarc { 227*44387Smarc register struct pgrp *mypgrp = p->p_pgrp, *hispgrp; 228*44387Smarc register struct session *mysession = mypgrp->pg_session; 229*44387Smarc register struct proc *qp; 230*44387Smarc 231*44387Smarc if ((hispgrp = p->p_pptr->p_pgrp) != mypgrp && 232*44387Smarc hispgrp->pg_session == mysession) 233*44387Smarc if (flag) 234*44387Smarc mypgrp->pg_jobc++; 235*44387Smarc else if (--mypgrp->pg_jobc == 0) { 236*44387Smarc int deliver = 0; 237*44387Smarc 238*44387Smarc sigstopped: 239*44387Smarc for (qp = mypgrp->pg_mem; qp != NULL; 240*44387Smarc qp = qp->p_pgrpnxt) 241*44387Smarc if (deliver) { 242*44387Smarc psignal(qp, SIGHUP); 243*44387Smarc psignal(qp, SIGCONT); 244*44387Smarc } else if (qp->p_stat == SSTOP) { 245*44387Smarc deliver++; 246*44387Smarc goto sigstopped; 247*44387Smarc } 248*44387Smarc } 249*44387Smarc 250*44387Smarc for (p = p->p_cptr; p != NULL; p = p->p_osptr) 251*44387Smarc if ((hispgrp = p->p_pgrp) != mypgrp && 252*44387Smarc hispgrp->pg_session == mysession && 253*44387Smarc p->p_stat != SZOMB) 254*44387Smarc if (flag) 255*44387Smarc hispgrp->pg_jobc++; 256*44387Smarc else if (--hispgrp->pg_jobc == 0) { 257*44387Smarc int deliver = 0; 258*44387Smarc 259*44387Smarc sigstopped2: 260*44387Smarc for (qp = hispgrp->pg_mem; qp != NULL; 261*44387Smarc qp = qp->p_pgrpnxt) 262*44387Smarc if (deliver) { 263*44387Smarc psignal(qp, SIGHUP); 264*44387Smarc psignal(qp, SIGCONT); 265*44387Smarc } else if (qp->p_stat == SSTOP) { 266*44387Smarc deliver++; 267*44387Smarc goto sigstopped2; 268*44387Smarc } 269*44387Smarc } 270*44387Smarc } 271*44387Smarc 272*44387Smarc /* 27316529Skarels * init the process queues 27416529Skarels */ 27516529Skarels pqinit() 27616529Skarels { 27716529Skarels register struct proc *p; 27816529Skarels 27916529Skarels /* 28016529Skarels * most procs are initially on freequeue 28116529Skarels * nb: we place them there in their "natural" order. 28216529Skarels */ 28316529Skarels 28416529Skarels freeproc = NULL; 28516529Skarels for (p = procNPROC; --p > proc; freeproc = p) 28616529Skarels p->p_nxt = freeproc; 28716529Skarels 28816529Skarels /* 28916529Skarels * but proc[0] is special ... 29016529Skarels */ 29116529Skarels 29216529Skarels allproc = p; 29316529Skarels p->p_nxt = NULL; 29416529Skarels p->p_prev = &allproc; 29516529Skarels 29616529Skarels zombproc = NULL; 29716529Skarels } 29835810Smarc 29937728Smckusick #ifdef debug 30035810Smarc /* DEBUG */ 30135810Smarc pgrpdump() 30235810Smarc { 30335810Smarc register struct pgrp *pgrp; 30435810Smarc register struct proc *p; 30535810Smarc register i; 30635810Smarc 30735810Smarc for (i=0; i<PIDHSZ; i++) { 30835810Smarc if (pgrphash[i]) { 30935810Smarc printf("\tindx %d\n", i); 31035810Smarc for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 31135810Smarc printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 31235810Smarc pgrp, pgrp->pg_id, pgrp->pg_session, 31335810Smarc pgrp->pg_session->s_count, pgrp->pg_mem); 31435810Smarc for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 31535810Smarc printf("\t\tpid %d addr %x pgrp %x\n", 31635810Smarc p->p_pid, p, p->p_pgrp); 31735810Smarc } 31835810Smarc } 31935810Smarc 32035810Smarc } 32135810Smarc } 32235810Smarc } 32337728Smckusick #endif /* debug */ 324