123371Smckusick /* 2*37728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3*37728Smckusick * All rights reserved. 423371Smckusick * 5*37728Smckusick * Redistribution and use in source and binary forms are permitted 6*37728Smckusick * provided that the above copyright notice and this paragraph are 7*37728Smckusick * duplicated in all such forms and that any documentation, 8*37728Smckusick * advertising materials, and other materials related to such 9*37728Smckusick * distribution and use acknowledge that the software was developed 10*37728Smckusick * by the University of California, Berkeley. The name of the 11*37728Smckusick * University may not be used to endorse or promote products derived 12*37728Smckusick * from this software without specific prior written permission. 13*37728Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*37728Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*37728Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*37728Smckusick * 17*37728Smckusick * @(#)kern_proc.c 7.6 (Berkeley) 05/09/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" 33*37728Smckusick #include "../ufs/quota.h" 3417091Sbloom #include "uio.h" 3535810Smarc #include "malloc.h" 3617091Sbloom #include "mbuf.h" 3735810Smarc #include "tty.h" 3836Sbill 3937524Smckusick #include "machine/reg.h" 4037524Smckusick #include "machine/pte.h" 4137524Smckusick #include "machine/psl.h" 4237524Smckusick 4317540Skarels /* 4425385Skarels * Clear any pending stops for top and all descendents. 4517540Skarels */ 4625385Skarels spgrp(top) 4717540Skarels struct proc *top; 487497Sroot { 4917540Skarels register struct proc *p; 507497Sroot int f = 0; 517497Sroot 5217540Skarels p = top; 5317540Skarels for (;;) { 5425385Skarels p->p_sig &= 5517540Skarels ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); 567497Sroot f++; 577497Sroot /* 5817540Skarels * If this process has children, descend to them next, 5917540Skarels * otherwise do any siblings, and if done with this level, 6017540Skarels * follow back up the tree (but not past top). 617497Sroot */ 6217540Skarels if (p->p_cptr) 6317540Skarels p = p->p_cptr; 6417540Skarels else if (p == top) 6517540Skarels return (f); 6617540Skarels else if (p->p_osptr) 6717540Skarels p = p->p_osptr; 6817540Skarels else for (;;) { 6917540Skarels p = p->p_pptr; 7017540Skarels if (p == top) 7117540Skarels return (f); 7217540Skarels if (p->p_osptr) { 7317540Skarels p = p->p_osptr; 7417540Skarels break; 7517540Skarels } 7617540Skarels } 777497Sroot } 787497Sroot } 797497Sroot 8036Sbill /* 817497Sroot * Is p an inferior of the current process? 8236Sbill */ 837497Sroot inferior(p) 847816Sroot register struct proc *p; 8536Sbill { 867497Sroot for (; p != u.u_procp; p = p->p_pptr) 877497Sroot if (p->p_ppid == 0) 887497Sroot return (0); 897497Sroot return (1); 9036Sbill } 917816Sroot 927816Sroot struct proc * 937816Sroot pfind(pid) 9435810Smarc register pid; 957816Sroot { 967816Sroot register struct proc *p; 977816Sroot 9835810Smarc for (p = &proc[pidhash[PIDHASH(pid)]] ; 9935810Smarc p != &proc[0]; p = &proc[p->p_idhash]) 1007816Sroot if (p->p_pid == pid) 1017816Sroot return (p); 1027816Sroot return ((struct proc *)0); 1037816Sroot } 10416529Skarels 10516529Skarels /* 10635810Smarc * Locate a process group by number 10735810Smarc */ 10835810Smarc struct pgrp * 10935810Smarc pgfind(pgid) 11035810Smarc register pid_t pgid; 11135810Smarc { 11235810Smarc register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; 11335810Smarc 11435810Smarc for (; pgrp; pgrp = pgrp->pg_hforw) 11535810Smarc if (pgrp->pg_id == pgid) 11635810Smarc return(pgrp); 11735810Smarc return ((struct pgrp *)0); 11835810Smarc } 11935810Smarc 12035810Smarc /* 12135810Smarc * Move p to a new or existing process group (and session) 12235810Smarc */ 12335810Smarc pgmv(p, pgid, mksess) 12435810Smarc register struct proc *p; 12535810Smarc pid_t pgid; 12635810Smarc { 12735810Smarc register struct pgrp *pgrp = pgfind(pgid); 12835810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 12935810Smarc register struct proc *cp; 13037589Smarc struct pgrp *opgrp; 13135810Smarc register n; 13235810Smarc 13335810Smarc if (pgrp && mksess) /* firewalls */ 13437589Smarc panic("pgmv: setsid into non-empty pgrp"); 13535810Smarc if (SESS_LEADER(p)) 13637589Smarc panic("pgmv: session leader attempted setpgrp"); 13737589Smarc if (pgrp == NULL) { 13835810Smarc /* 13935810Smarc * new process group 14035810Smarc */ 14135810Smarc if (p->p_pid != pgid) 14237589Smarc panic("pgmv: new pgrp and pid != pgid"); 14335810Smarc MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 14435810Smarc M_WAITOK); 14535810Smarc if (mksess) { 14635810Smarc register struct session *sess; 14735810Smarc /* 14835810Smarc * new session 14935810Smarc */ 15035810Smarc MALLOC(sess, struct session *, sizeof(struct session), 15135810Smarc M_SESSION, M_WAITOK); 15235810Smarc sess->s_leader = p; 15335810Smarc sess->s_count = 1; 15435810Smarc pgrp->pg_session = sess; 15535810Smarc if (p != u.u_procp) 15635810Smarc panic("pgmv: mksession and p != u.u_procp"); 15737589Smarc u.u_ttyp = NULL; 15835810Smarc u.u_ttyd = 0; 15935810Smarc } else { 16035810Smarc pgrp->pg_session = p->p_session; 16135810Smarc pgrp->pg_session->s_count++; 16235810Smarc } 16335810Smarc pgrp->pg_id = pgid; 16435810Smarc pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)]; 16535810Smarc pgrphash[n] = pgrp; 16635810Smarc pgrp->pg_jobc = 0; 16735810Smarc pgrp->pg_mem = 0; 16835810Smarc } 16935810Smarc /* 17035810Smarc * adjust eligibility of affected pgrps to participate in job control 17135810Smarc */ 17235810Smarc if (PGRP_JOBC(p)) 17335810Smarc p->p_pgrp->pg_jobc--; 17435810Smarc for (cp = p->p_cptr; cp; cp = cp->p_osptr) 17535810Smarc if (PGRP_JOBC(cp)) 17635810Smarc cp->p_pgrp->pg_jobc--; 17735810Smarc /* 17835810Smarc * unlink p from old process group 17935810Smarc */ 18035810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 18135810Smarc if (*pp == p) { 18235810Smarc *pp = p->p_pgrpnxt; 18335810Smarc goto done; 18435810Smarc } 18537589Smarc panic("pgmv: can't find p on old pgrp"); 18635810Smarc done: 18735810Smarc /* 18835810Smarc * link into new one 18935810Smarc */ 19035810Smarc p->p_pgrpnxt = pgrp->pg_mem; 19135810Smarc pgrp->pg_mem = p; 19237589Smarc opgrp = p->p_pgrp; 19335810Smarc p->p_pgrp = pgrp; 19435810Smarc /* 19535810Smarc * adjust eligibility of affected pgrps to participate in job control 19635810Smarc */ 19735810Smarc if (PGRP_JOBC(p)) 19835810Smarc p->p_pgrp->pg_jobc++; 19935810Smarc for (cp = p->p_cptr; cp; cp = cp->p_osptr) 20035810Smarc if (PGRP_JOBC(cp)) 20135810Smarc cp->p_pgrp->pg_jobc++; 20235810Smarc /* 20335810Smarc * old pgrp empty? 20435810Smarc */ 20537589Smarc if (!opgrp->pg_mem) 20637589Smarc pgdelete(opgrp); 20735810Smarc } 20835810Smarc 20935810Smarc /* 21035810Smarc * remove process from process group 21135810Smarc */ 21235810Smarc pgrm(p) 21335810Smarc register struct proc *p; 21435810Smarc { 21535810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 21635810Smarc 21735810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 21835810Smarc if (*pp == p) { 21935810Smarc *pp = p->p_pgrpnxt; 22035810Smarc goto done; 22135810Smarc } 22237589Smarc panic("pgrm: can't find p in pgrp"); 22335810Smarc done: 22435810Smarc if (!p->p_pgrp->pg_mem) 22535810Smarc pgdelete(p->p_pgrp); 22635810Smarc p->p_pgrp = 0; 22735810Smarc } 22835810Smarc 22935810Smarc /* 23035810Smarc * delete a process group 23135810Smarc */ 23235810Smarc pgdelete(pgrp) 23335810Smarc register struct pgrp *pgrp; 23435810Smarc { 23535810Smarc register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 23635810Smarc 23735810Smarc for (; *pgp; pgp = &(*pgp)->pg_hforw) 23835810Smarc if (*pgp == pgrp) { 23935810Smarc *pgp = pgrp->pg_hforw; 24035810Smarc goto done; 24135810Smarc } 24237589Smarc panic("pgdelete: can't find pgrp on hash chain"); 24335810Smarc done: 24435810Smarc if (--pgrp->pg_session->s_count == 0) 24535810Smarc FREE(pgrp->pg_session, M_SESSION); 24635810Smarc FREE(pgrp, M_PGRP); 24735810Smarc } 24835810Smarc 24935810Smarc /* 25016529Skarels * init the process queues 25116529Skarels */ 25216529Skarels pqinit() 25316529Skarels { 25416529Skarels register struct proc *p; 25516529Skarels 25616529Skarels /* 25716529Skarels * most procs are initially on freequeue 25816529Skarels * nb: we place them there in their "natural" order. 25916529Skarels */ 26016529Skarels 26116529Skarels freeproc = NULL; 26216529Skarels for (p = procNPROC; --p > proc; freeproc = p) 26316529Skarels p->p_nxt = freeproc; 26416529Skarels 26516529Skarels /* 26616529Skarels * but proc[0] is special ... 26716529Skarels */ 26816529Skarels 26916529Skarels allproc = p; 27016529Skarels p->p_nxt = NULL; 27116529Skarels p->p_prev = &allproc; 27216529Skarels 27316529Skarels zombproc = NULL; 27416529Skarels } 27535810Smarc 276*37728Smckusick #ifdef debug 27735810Smarc /* DEBUG */ 27835810Smarc pgrpdump() 27935810Smarc { 28035810Smarc register struct pgrp *pgrp; 28135810Smarc register struct proc *p; 28235810Smarc register i; 28335810Smarc 28435810Smarc for (i=0; i<PIDHSZ; i++) { 28535810Smarc if (pgrphash[i]) { 28635810Smarc printf("\tindx %d\n", i); 28735810Smarc for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 28835810Smarc printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 28935810Smarc pgrp, pgrp->pg_id, pgrp->pg_session, 29035810Smarc pgrp->pg_session->s_count, pgrp->pg_mem); 29135810Smarc for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 29235810Smarc printf("\t\tpid %d addr %x pgrp %x\n", 29335810Smarc p->p_pid, p, p->p_pgrp); 29435810Smarc } 29535810Smarc } 29635810Smarc 29735810Smarc } 29835810Smarc } 29935810Smarc } 300*37728Smckusick #endif /* debug */ 301