123371Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423371Smckusick * 5*44438Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*44438Sbostic * @(#)kern_proc.c 7.11 (Berkeley) 06/28/90 823371Smckusick */ 936Sbill 1017091Sbloom #include "param.h" 1117091Sbloom #include "systm.h" 1217091Sbloom #include "map.h" 1317091Sbloom #include "user.h" 1417091Sbloom #include "kernel.h" 1517091Sbloom #include "proc.h" 1617091Sbloom #include "buf.h" 1717091Sbloom #include "seg.h" 1817091Sbloom #include "acct.h" 1917091Sbloom #include "wait.h" 2017091Sbloom #include "vm.h" 2117091Sbloom #include "text.h" 2217091Sbloom #include "file.h" 2337728Smckusick #include "../ufs/quota.h" 2417091Sbloom #include "uio.h" 2535810Smarc #include "malloc.h" 2617091Sbloom #include "mbuf.h" 2739064Smarc #include "ioctl.h" 2835810Smarc #include "tty.h" 2936Sbill 3037524Smckusick #include "machine/reg.h" 3137524Smckusick #include "machine/pte.h" 3237524Smckusick #include "machine/psl.h" 3337524Smckusick 3417540Skarels /* 357497Sroot * Is p an inferior of the current process? 3636Sbill */ 377497Sroot inferior(p) 387816Sroot register struct proc *p; 3936Sbill { 407497Sroot for (; p != u.u_procp; p = p->p_pptr) 417497Sroot if (p->p_ppid == 0) 427497Sroot return (0); 437497Sroot return (1); 4436Sbill } 457816Sroot 4640709Skarels /* 4740709Skarels * Locate a process by number 4840709Skarels */ 497816Sroot struct proc * 507816Sroot pfind(pid) 5135810Smarc register pid; 527816Sroot { 5340709Skarels register struct proc *p = pidhash[PIDHASH(pid)]; 547816Sroot 5540709Skarels for (; p; p = p->p_hash) 567816Sroot if (p->p_pid == pid) 577816Sroot return (p); 587816Sroot return ((struct proc *)0); 597816Sroot } 6016529Skarels 6116529Skarels /* 6235810Smarc * Locate a process group by number 6335810Smarc */ 6435810Smarc struct pgrp * 6535810Smarc pgfind(pgid) 6635810Smarc register pid_t pgid; 6735810Smarc { 6835810Smarc register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; 6935810Smarc 7035810Smarc for (; pgrp; pgrp = pgrp->pg_hforw) 7135810Smarc if (pgrp->pg_id == pgid) 7240709Skarels return (pgrp); 7335810Smarc return ((struct pgrp *)0); 7435810Smarc } 7535810Smarc 7635810Smarc /* 7735810Smarc * Move p to a new or existing process group (and session) 7835810Smarc */ 7935810Smarc pgmv(p, pgid, mksess) 8035810Smarc register struct proc *p; 8135810Smarc pid_t pgid; 8235810Smarc { 8335810Smarc register struct pgrp *pgrp = pgfind(pgid); 8435810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 8535810Smarc register struct proc *cp; 8637589Smarc struct pgrp *opgrp; 8735810Smarc register n; 8835810Smarc 8939562Smarc #ifdef DIAGNOSTIC 9035810Smarc if (pgrp && mksess) /* firewalls */ 9137589Smarc panic("pgmv: setsid into non-empty pgrp"); 9235810Smarc if (SESS_LEADER(p)) 9337589Smarc panic("pgmv: session leader attempted setpgrp"); 9439562Smarc #endif 9537589Smarc if (pgrp == NULL) { 9635810Smarc /* 9735810Smarc * new process group 9835810Smarc */ 9939562Smarc #ifdef DIAGNOSTIC 10035810Smarc if (p->p_pid != pgid) 10137589Smarc panic("pgmv: new pgrp and pid != pgid"); 10239562Smarc #endif 10335810Smarc MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 10435810Smarc M_WAITOK); 10535810Smarc if (mksess) { 10635810Smarc register struct session *sess; 10735810Smarc /* 10835810Smarc * new session 10935810Smarc */ 11035810Smarc MALLOC(sess, struct session *, sizeof(struct session), 11135810Smarc M_SESSION, M_WAITOK); 11235810Smarc sess->s_leader = p; 11335810Smarc sess->s_count = 1; 11439562Smarc sess->s_ttyvp = NULL; 11539562Smarc sess->s_ttyp = NULL; 11639562Smarc p->p_flag &= ~SCTTY; 11735810Smarc pgrp->pg_session = sess; 11839562Smarc #ifdef DIAGNOSTIC 11935810Smarc if (p != u.u_procp) 12035810Smarc panic("pgmv: mksession and p != u.u_procp"); 12139562Smarc #endif 12235810Smarc } else { 12335810Smarc pgrp->pg_session = p->p_session; 12435810Smarc pgrp->pg_session->s_count++; 12535810Smarc } 12635810Smarc pgrp->pg_id = pgid; 12735810Smarc pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)]; 12835810Smarc pgrphash[n] = pgrp; 12935810Smarc pgrp->pg_jobc = 0; 13039562Smarc pgrp->pg_mem = NULL; 13144387Smarc } else if (pgrp == p->p_pgrp) 13244387Smarc return; 13335810Smarc /* 13435810Smarc * adjust eligibility of affected pgrps to participate in job control 13535810Smarc */ 13644387Smarc fixjobc(p, 0); 13735810Smarc /* 13835810Smarc * unlink p from old process group 13935810Smarc */ 14035810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 14135810Smarc if (*pp == p) { 14235810Smarc *pp = p->p_pgrpnxt; 14335810Smarc goto done; 14435810Smarc } 14537589Smarc panic("pgmv: can't find p on old pgrp"); 14635810Smarc done: 14735810Smarc /* 14835810Smarc * link into new one 14935810Smarc */ 15035810Smarc p->p_pgrpnxt = pgrp->pg_mem; 15135810Smarc pgrp->pg_mem = p; 15237589Smarc opgrp = p->p_pgrp; 15335810Smarc p->p_pgrp = pgrp; 15435810Smarc /* 15535810Smarc * adjust eligibility of affected pgrps to participate in job control 15635810Smarc */ 15744387Smarc fixjobc(p, 1); 15835810Smarc /* 15944387Smarc * delete old if empty 16035810Smarc */ 16137589Smarc if (!opgrp->pg_mem) 16237589Smarc pgdelete(opgrp); 16335810Smarc } 16435810Smarc 16535810Smarc /* 16635810Smarc * remove process from process group 16735810Smarc */ 16835810Smarc pgrm(p) 16935810Smarc register struct proc *p; 17035810Smarc { 17135810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 17235810Smarc 17335810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 17435810Smarc if (*pp == p) { 17535810Smarc *pp = p->p_pgrpnxt; 17635810Smarc goto done; 17735810Smarc } 17837589Smarc panic("pgrm: can't find p in pgrp"); 17935810Smarc done: 18035810Smarc if (!p->p_pgrp->pg_mem) 18135810Smarc pgdelete(p->p_pgrp); 18235810Smarc p->p_pgrp = 0; 18335810Smarc } 18435810Smarc 18535810Smarc /* 18635810Smarc * delete a process group 18735810Smarc */ 18835810Smarc pgdelete(pgrp) 18935810Smarc register struct pgrp *pgrp; 19035810Smarc { 19135810Smarc register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 19235810Smarc 19339562Smarc if (pgrp->pg_session->s_ttyp != NULL && 19439562Smarc pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 19539562Smarc pgrp->pg_session->s_ttyp->t_pgrp = NULL; 19635810Smarc for (; *pgp; pgp = &(*pgp)->pg_hforw) 19735810Smarc if (*pgp == pgrp) { 19835810Smarc *pgp = pgrp->pg_hforw; 19935810Smarc goto done; 20035810Smarc } 20137589Smarc panic("pgdelete: can't find pgrp on hash chain"); 20235810Smarc done: 20335810Smarc if (--pgrp->pg_session->s_count == 0) 20435810Smarc FREE(pgrp->pg_session, M_SESSION); 20535810Smarc FREE(pgrp, M_PGRP); 20635810Smarc } 20735810Smarc 20835810Smarc /* 20944387Smarc * Adjust pgrp jobc counter. 21044387Smarc * flag == 0 => p is leaving current state. 21144387Smarc * flag == 1 => p is entering current state. 21244387Smarc */ 21344387Smarc fixjobc(p, flag) 21444387Smarc register struct proc *p; 21544387Smarc register flag; 21644387Smarc { 21744387Smarc register struct pgrp *mypgrp = p->p_pgrp, *hispgrp; 21844387Smarc register struct session *mysession = mypgrp->pg_session; 21944387Smarc register struct proc *qp; 22044387Smarc 22144387Smarc if ((hispgrp = p->p_pptr->p_pgrp) != mypgrp && 22244387Smarc hispgrp->pg_session == mysession) 22344387Smarc if (flag) 22444387Smarc mypgrp->pg_jobc++; 22544387Smarc else if (--mypgrp->pg_jobc == 0) { 22644387Smarc int deliver = 0; 22744387Smarc 22844387Smarc sigstopped: 22944387Smarc for (qp = mypgrp->pg_mem; qp != NULL; 23044387Smarc qp = qp->p_pgrpnxt) 23144387Smarc if (deliver) { 23244387Smarc psignal(qp, SIGHUP); 23344387Smarc psignal(qp, SIGCONT); 23444387Smarc } else if (qp->p_stat == SSTOP) { 23544387Smarc deliver++; 23644387Smarc goto sigstopped; 23744387Smarc } 23844387Smarc } 23944387Smarc 24044387Smarc for (p = p->p_cptr; p != NULL; p = p->p_osptr) 24144387Smarc if ((hispgrp = p->p_pgrp) != mypgrp && 24244387Smarc hispgrp->pg_session == mysession && 24344387Smarc p->p_stat != SZOMB) 24444387Smarc if (flag) 24544387Smarc hispgrp->pg_jobc++; 24644387Smarc else if (--hispgrp->pg_jobc == 0) { 24744387Smarc int deliver = 0; 24844387Smarc 24944387Smarc sigstopped2: 25044387Smarc for (qp = hispgrp->pg_mem; qp != NULL; 25144387Smarc qp = qp->p_pgrpnxt) 25244387Smarc if (deliver) { 25344387Smarc psignal(qp, SIGHUP); 25444387Smarc psignal(qp, SIGCONT); 25544387Smarc } else if (qp->p_stat == SSTOP) { 25644387Smarc deliver++; 25744387Smarc goto sigstopped2; 25844387Smarc } 25944387Smarc } 26044387Smarc } 26144387Smarc 26244387Smarc /* 26316529Skarels * init the process queues 26416529Skarels */ 26516529Skarels pqinit() 26616529Skarels { 26716529Skarels register struct proc *p; 26816529Skarels 26916529Skarels /* 27016529Skarels * most procs are initially on freequeue 27116529Skarels * nb: we place them there in their "natural" order. 27216529Skarels */ 27316529Skarels 27416529Skarels freeproc = NULL; 27516529Skarels for (p = procNPROC; --p > proc; freeproc = p) 27616529Skarels p->p_nxt = freeproc; 27716529Skarels 27816529Skarels /* 27916529Skarels * but proc[0] is special ... 28016529Skarels */ 28116529Skarels 28216529Skarels allproc = p; 28316529Skarels p->p_nxt = NULL; 28416529Skarels p->p_prev = &allproc; 28516529Skarels 28616529Skarels zombproc = NULL; 28716529Skarels } 28835810Smarc 28937728Smckusick #ifdef debug 29035810Smarc /* DEBUG */ 29135810Smarc pgrpdump() 29235810Smarc { 29335810Smarc register struct pgrp *pgrp; 29435810Smarc register struct proc *p; 29535810Smarc register i; 29635810Smarc 29735810Smarc for (i=0; i<PIDHSZ; i++) { 29835810Smarc if (pgrphash[i]) { 29935810Smarc printf("\tindx %d\n", i); 30035810Smarc for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 30135810Smarc printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 30235810Smarc pgrp, pgrp->pg_id, pgrp->pg_session, 30335810Smarc pgrp->pg_session->s_count, pgrp->pg_mem); 30435810Smarc for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 30535810Smarc printf("\t\tpid %d addr %x pgrp %x\n", 30635810Smarc p->p_pid, p, p->p_pgrp); 30735810Smarc } 30835810Smarc } 30935810Smarc 31035810Smarc } 31135810Smarc } 31235810Smarc } 31337728Smckusick #endif /* debug */ 314