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*39064Smarc * @(#)kern_proc.c 7.7 (Berkeley) 09/06/89 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" 37*39064Smarc #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 /* 4525385Skarels * Clear any pending stops for top and all descendents. 4617540Skarels */ 4725385Skarels spgrp(top) 4817540Skarels struct proc *top; 497497Sroot { 5017540Skarels register struct proc *p; 517497Sroot int f = 0; 527497Sroot 5317540Skarels p = top; 5417540Skarels for (;;) { 5525385Skarels p->p_sig &= 5617540Skarels ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); 577497Sroot f++; 587497Sroot /* 5917540Skarels * If this process has children, descend to them next, 6017540Skarels * otherwise do any siblings, and if done with this level, 6117540Skarels * follow back up the tree (but not past top). 627497Sroot */ 6317540Skarels if (p->p_cptr) 6417540Skarels p = p->p_cptr; 6517540Skarels else if (p == top) 6617540Skarels return (f); 6717540Skarels else if (p->p_osptr) 6817540Skarels p = p->p_osptr; 6917540Skarels else for (;;) { 7017540Skarels p = p->p_pptr; 7117540Skarels if (p == top) 7217540Skarels return (f); 7317540Skarels if (p->p_osptr) { 7417540Skarels p = p->p_osptr; 7517540Skarels break; 7617540Skarels } 7717540Skarels } 787497Sroot } 797497Sroot } 807497Sroot 8136Sbill /* 827497Sroot * Is p an inferior of the current process? 8336Sbill */ 847497Sroot inferior(p) 857816Sroot register struct proc *p; 8636Sbill { 877497Sroot for (; p != u.u_procp; p = p->p_pptr) 887497Sroot if (p->p_ppid == 0) 897497Sroot return (0); 907497Sroot return (1); 9136Sbill } 927816Sroot 937816Sroot struct proc * 947816Sroot pfind(pid) 9535810Smarc register pid; 967816Sroot { 977816Sroot register struct proc *p; 987816Sroot 9935810Smarc for (p = &proc[pidhash[PIDHASH(pid)]] ; 10035810Smarc p != &proc[0]; p = &proc[p->p_idhash]) 1017816Sroot if (p->p_pid == pid) 1027816Sroot return (p); 1037816Sroot return ((struct proc *)0); 1047816Sroot } 10516529Skarels 10616529Skarels /* 10735810Smarc * Locate a process group by number 10835810Smarc */ 10935810Smarc struct pgrp * 11035810Smarc pgfind(pgid) 11135810Smarc register pid_t pgid; 11235810Smarc { 11335810Smarc register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; 11435810Smarc 11535810Smarc for (; pgrp; pgrp = pgrp->pg_hforw) 11635810Smarc if (pgrp->pg_id == pgid) 11735810Smarc return(pgrp); 11835810Smarc return ((struct pgrp *)0); 11935810Smarc } 12035810Smarc 12135810Smarc /* 12235810Smarc * Move p to a new or existing process group (and session) 12335810Smarc */ 12435810Smarc pgmv(p, pgid, mksess) 12535810Smarc register struct proc *p; 12635810Smarc pid_t pgid; 12735810Smarc { 12835810Smarc register struct pgrp *pgrp = pgfind(pgid); 12935810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 13035810Smarc register struct proc *cp; 13137589Smarc struct pgrp *opgrp; 13235810Smarc register n; 13335810Smarc 13435810Smarc if (pgrp && mksess) /* firewalls */ 13537589Smarc panic("pgmv: setsid into non-empty pgrp"); 13635810Smarc if (SESS_LEADER(p)) 13737589Smarc panic("pgmv: session leader attempted setpgrp"); 13837589Smarc if (pgrp == NULL) { 13935810Smarc /* 14035810Smarc * new process group 14135810Smarc */ 14235810Smarc if (p->p_pid != pgid) 14337589Smarc panic("pgmv: new pgrp and pid != pgid"); 14435810Smarc MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 14535810Smarc M_WAITOK); 14635810Smarc if (mksess) { 14735810Smarc register struct session *sess; 14835810Smarc /* 14935810Smarc * new session 15035810Smarc */ 15135810Smarc MALLOC(sess, struct session *, sizeof(struct session), 15235810Smarc M_SESSION, M_WAITOK); 15335810Smarc sess->s_leader = p; 15435810Smarc sess->s_count = 1; 15535810Smarc pgrp->pg_session = sess; 15635810Smarc if (p != u.u_procp) 15735810Smarc panic("pgmv: mksession and p != u.u_procp"); 15837589Smarc u.u_ttyp = NULL; 15935810Smarc u.u_ttyd = 0; 16035810Smarc } else { 16135810Smarc pgrp->pg_session = p->p_session; 16235810Smarc pgrp->pg_session->s_count++; 16335810Smarc } 16435810Smarc pgrp->pg_id = pgid; 16535810Smarc pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)]; 16635810Smarc pgrphash[n] = pgrp; 16735810Smarc pgrp->pg_jobc = 0; 16835810Smarc pgrp->pg_mem = 0; 16935810Smarc } 17035810Smarc /* 17135810Smarc * adjust eligibility of affected pgrps to participate in job control 17235810Smarc */ 17335810Smarc if (PGRP_JOBC(p)) 17435810Smarc p->p_pgrp->pg_jobc--; 17535810Smarc for (cp = p->p_cptr; cp; cp = cp->p_osptr) 17635810Smarc if (PGRP_JOBC(cp)) 17735810Smarc cp->p_pgrp->pg_jobc--; 17835810Smarc /* 17935810Smarc * unlink p from old process group 18035810Smarc */ 18135810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 18235810Smarc if (*pp == p) { 18335810Smarc *pp = p->p_pgrpnxt; 18435810Smarc goto done; 18535810Smarc } 18637589Smarc panic("pgmv: can't find p on old pgrp"); 18735810Smarc done: 18835810Smarc /* 18935810Smarc * link into new one 19035810Smarc */ 19135810Smarc p->p_pgrpnxt = pgrp->pg_mem; 19235810Smarc pgrp->pg_mem = p; 19337589Smarc opgrp = p->p_pgrp; 19435810Smarc p->p_pgrp = pgrp; 19535810Smarc /* 19635810Smarc * adjust eligibility of affected pgrps to participate in job control 19735810Smarc */ 19835810Smarc if (PGRP_JOBC(p)) 19935810Smarc p->p_pgrp->pg_jobc++; 20035810Smarc for (cp = p->p_cptr; cp; cp = cp->p_osptr) 20135810Smarc if (PGRP_JOBC(cp)) 20235810Smarc cp->p_pgrp->pg_jobc++; 20335810Smarc /* 20435810Smarc * old pgrp empty? 20535810Smarc */ 20637589Smarc if (!opgrp->pg_mem) 20737589Smarc pgdelete(opgrp); 20835810Smarc } 20935810Smarc 21035810Smarc /* 21135810Smarc * remove process from process group 21235810Smarc */ 21335810Smarc pgrm(p) 21435810Smarc register struct proc *p; 21535810Smarc { 21635810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 21735810Smarc 21835810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 21935810Smarc if (*pp == p) { 22035810Smarc *pp = p->p_pgrpnxt; 22135810Smarc goto done; 22235810Smarc } 22337589Smarc panic("pgrm: can't find p in pgrp"); 22435810Smarc done: 22535810Smarc if (!p->p_pgrp->pg_mem) 22635810Smarc pgdelete(p->p_pgrp); 22735810Smarc p->p_pgrp = 0; 22835810Smarc } 22935810Smarc 23035810Smarc /* 23135810Smarc * delete a process group 23235810Smarc */ 23335810Smarc pgdelete(pgrp) 23435810Smarc register struct pgrp *pgrp; 23535810Smarc { 23635810Smarc register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 23735810Smarc 23835810Smarc for (; *pgp; pgp = &(*pgp)->pg_hforw) 23935810Smarc if (*pgp == pgrp) { 24035810Smarc *pgp = pgrp->pg_hforw; 24135810Smarc goto done; 24235810Smarc } 24337589Smarc panic("pgdelete: can't find pgrp on hash chain"); 24435810Smarc done: 24535810Smarc if (--pgrp->pg_session->s_count == 0) 24635810Smarc FREE(pgrp->pg_session, M_SESSION); 24735810Smarc FREE(pgrp, M_PGRP); 24835810Smarc } 24935810Smarc 25035810Smarc /* 25116529Skarels * init the process queues 25216529Skarels */ 25316529Skarels pqinit() 25416529Skarels { 25516529Skarels register struct proc *p; 25616529Skarels 25716529Skarels /* 25816529Skarels * most procs are initially on freequeue 25916529Skarels * nb: we place them there in their "natural" order. 26016529Skarels */ 26116529Skarels 26216529Skarels freeproc = NULL; 26316529Skarels for (p = procNPROC; --p > proc; freeproc = p) 26416529Skarels p->p_nxt = freeproc; 26516529Skarels 26616529Skarels /* 26716529Skarels * but proc[0] is special ... 26816529Skarels */ 26916529Skarels 27016529Skarels allproc = p; 27116529Skarels p->p_nxt = NULL; 27216529Skarels p->p_prev = &allproc; 27316529Skarels 27416529Skarels zombproc = NULL; 27516529Skarels } 27635810Smarc 27737728Smckusick #ifdef debug 27835810Smarc /* DEBUG */ 27935810Smarc pgrpdump() 28035810Smarc { 28135810Smarc register struct pgrp *pgrp; 28235810Smarc register struct proc *p; 28335810Smarc register i; 28435810Smarc 28535810Smarc for (i=0; i<PIDHSZ; i++) { 28635810Smarc if (pgrphash[i]) { 28735810Smarc printf("\tindx %d\n", i); 28835810Smarc for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 28935810Smarc printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 29035810Smarc pgrp, pgrp->pg_id, pgrp->pg_session, 29135810Smarc pgrp->pg_session->s_count, pgrp->pg_mem); 29235810Smarc for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 29335810Smarc printf("\t\tpid %d addr %x pgrp %x\n", 29435810Smarc p->p_pid, p, p->p_pgrp); 29535810Smarc } 29635810Smarc } 29735810Smarc 29835810Smarc } 29935810Smarc } 30035810Smarc } 30137728Smckusick #endif /* debug */ 302