Annotation of coherent/b/STREAMS/coh.386/proc.c, revision 1.1.1.1

1.1       root        1: /* $Header: /src386/STREAMS/coh.386/RCS/proc.c,v 2.3 93/08/09 13:35:59 bin Exp Locker: bin $ */
                      2: /* (lgl-
                      3:  *     The information contained herein is a trade secret of Mark Williams
                      4:  *     Company, and  is confidential information.  It is provided  under a
                      5:  *     license agreement,  and may be  copied or disclosed  only under the
                      6:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
                      7:  *     material without the express written authorization of Mark Williams
                      8:  *     Company or persuant to the license agreement is unlawful.
                      9:  *
                     10:  *     COHERENT Version 3.x, 4.x
                     11:  *     Copyright (c) 1982, 1993.
                     12:  *     An unpublished work by Mark Williams Company, Chicago.
                     13:  *     All rights reserved.
                     14:  -lgl) */
                     15: /*
                     16:  * Process handling and scheduling.
                     17:  *
                     18:  * $Log:       proc.c,v $
                     19:  * Revision 2.3  93/08/09  13:35:59  bin
                     20:  * Kernel 82 changes
                     21:  * 
                     22:  * Revision 2.2  93/07/26  15:53:52  nigel
                     23:  * Nigel's R80
                     24:  * 
                     25:  */
                     26: 
                     27: #include <common/_wait.h>
                     28: #include <kernel/_sleep.h>
                     29: #include <kernel/ker_data.h>
                     30: #include <kernel/sigproc.h>
                     31: #include <sys/wait.h>
                     32: #include <stddef.h>
                     33: 
                     34: #include <sys/coherent.h>
                     35: #include <sys/acct.h>
                     36: #include <sys/errno.h>
                     37: #include <sys/inode.h>
                     38: #include <sys/ptrace.h>
                     39: #include <sys/sched.h>
                     40: #include <signal.h>
                     41: #include <sys/stat.h>
                     42: 
                     43: /*
                     44:  * Initialization.
                     45:  * Set up the hash table queues.
                     46:  */
                     47: pcsinit()
                     48: {
                     49:        register PROC *pp;
                     50:        register PLINK *lp;
                     51: 
                     52:        /*
                     53:         * Explicitly initialize everything in the first process. We use the
                     54:         * kernel initialize routine with SELF set to NULL so that the first
                     55:         * process gets started out with default values for fields that are
                     56:         * normally inherited.
                     57:         */
                     58: 
                     59:        pp = & procq;
                     60:        procq.p_nforw = pp;
                     61:        procq.p_nback = pp;
                     62:        procq.p_lforw = pp;
                     63:        procq.p_lback = pp;
                     64: 
                     65:        /* Segments are initialized in mchinit() and eveinit(). */
                     66:        /* procq is static, so p_shmsr[] initializes to nulls.  */
                     67: 
                     68:        PROC_INIT (& procq);
                     69: 
                     70:        for (lp = linkq ; lp < linkq + NHPLINK ; lp ++) {
                     71:                lp->p_lforw = lp;
                     72:                lp->p_lback = lp;
                     73:        }
                     74: 
                     75:        /*
                     76:         * After we have set things up, we can have a current process.
                     77:         */
                     78: 
                     79:        SELF = pp;
                     80: }
                     81: 
                     82: /*
                     83:  * Initiate a process.
                     84:  */
                     85: 
                     86: static PROC *
                     87: process ()
                     88: {
                     89:        register PROC *pp1;
                     90:        register PROC *pp;
                     91: 
                     92:        if ((pp = kalloc (sizeof (PROC))) == NULL)
                     93:                return NULL;
                     94: 
                     95:        PROC_INIT (pp);
                     96: 
                     97:        lock (pnxgate);
                     98: next:
                     99: 
                    100:        /*
                    101:         * Pick the next process id.
                    102:         */
                    103:        if (++ cpid >= NPID)
                    104:                cpid = 2;
                    105:        pp->p_pid = cpid;
                    106: 
                    107: 
                    108:        /*
                    109:         * Make sure that process id is not in use.
                    110:         */
                    111: 
                    112:        pp1 = & procq;
                    113:        while ((pp1 = pp1->p_nforw) != & procq) {
                    114:                if (pp1->p_pid < pp->p_pid)
                    115:                        break;
                    116:                if (pp1->p_pid == pp->p_pid)
                    117:                        goto next;
                    118:        }
                    119: 
                    120:        /*
                    121:         * We've got a valid pid, so let's put this process into
                    122:         * the process table.
                    123:         */
                    124: 
                    125:        pp->p_nback = pp1->p_nback;
                    126:        pp1->p_nback->p_nforw = pp;
                    127:        pp->p_nforw = pp1;
                    128:        pp1->p_nback = pp;
                    129:        unlock (pnxgate);
                    130:        return pp;
                    131: }
                    132: 
                    133: /*
                    134:  * Remove a process from the next queue and release and space.
                    135:  */
                    136: relproc(pp)
                    137: register PROC *pp;
                    138: {
                    139:        register SEG * sp;
                    140: 
                    141:        /*
                    142:         * Child process still has a user-area.
                    143:         */
                    144:        if (sp = pp->p_segp[SIUSERP]) {
                    145: 
                    146:                /*
                    147:                 * Detach user-area from child process.
                    148:                 */
                    149:                pp->p_segp[SIUSERP] = NULL;
                    150: 
                    151:                /*
                    152:                 * Child process is swapped out.
                    153:                 */
                    154:                if (pp->p_flags & PFSWAP)
                    155:                        sp->s_lrefc++;
                    156: 
                    157:                /*
                    158:                 * Release child's user-area.
                    159:                 */
                    160:                sfree(sp);
                    161:        }
                    162: 
                    163:        /*
                    164:         * Remove process from doubly-linked list of all processes.
                    165:         * Release space allocated for proc structure.
                    166:         */
                    167:        lock(pnxgate);
                    168:        pp->p_nback->p_nforw = pp->p_nforw;
                    169:        pp->p_nforw->p_nback = pp->p_nback;
                    170:        unlock(pnxgate);
                    171:        kfree(pp);
                    172: }
                    173: 
                    174: /*
                    175:  * Create a clone of ourselves.
                    176:  *     N.B. - consave(&mcon) returns twice; anything not initialized
                    177:  *     in automatic storage before the call to segadup() will not be
                    178:  *     initialized when the second return from consave() commences.
                    179:  */
                    180: pfork()
                    181: {
                    182:        register PROC *cpp;
                    183:        register PROC *pp;
                    184:        register int s;
                    185:        MCON mcon;
                    186: 
                    187:        if ((cpp = process ()) == NULL) {
                    188:                SET_U_ERROR( EAGAIN, "no more process table entries" );
                    189:                return -1;
                    190:        }
                    191: 
                    192:        s = sphi();     /* put current interrupt level into s before segadup */
                    193:        spl(s);
                    194: 
                    195:        /*
                    196:         * As stated above, no auto variable may be changed between calls
                    197:         * to segadup() and consave().
                    198:         */
                    199: 
                    200:        if (segadup(cpp) == 0) {
                    201:                SET_U_ERROR( EAGAIN, "can not duplicate segments" );
                    202:                relproc(cpp);
                    203:                return -1;
                    204:        }
                    205: 
                    206:        shmDup(cpp);    /* copy shared memory info & update ref counts */
                    207: 
                    208:        if (u.u_rdir)
                    209:                u.u_rdir->i_refc ++;
                    210:        if (u.u_cdir)
                    211:                u.u_cdir->i_refc ++;
                    212:        fdadupl ();
                    213: 
                    214:        sphi ();                /* s = sphi() was done before segadup() */
                    215:        consave (& mcon);
                    216:        spl (s);
                    217: 
                    218:        /*
                    219:         * Parent process.
                    220:         */
                    221: 
                    222:        if ((pp = SELF) != cpp) {
                    223:                segfinm (cpp->p_segp [SIUSERP]);
                    224:                dmaout (sizeof (mcon),
                    225:                        MAPIO (cpp->p_segp [SIUSERP]->s_vmem,
                    226:                               U_OFFSET + offsetof (struct uproc, u_syscon)),
                    227:                        (char *) & mcon);
                    228:                s = sphi ();
                    229:                setrun (cpp);
                    230:                spl (s);
                    231: 
                    232:                u.u_rval2 = 0;
                    233:                return cpp->p_pid;
                    234:        } else {
                    235:                /*
                    236:                 * Child process.
                    237:                 */
                    238: 
                    239:                u.u_btime = timer.t_time;
                    240:                u.u_flag = AFORK;
                    241: 
                    242: #ifdef UPROC_VERSION
                    243:                u.u_version = UPROC_VERSION;
                    244: #endif /* UPROC_VERSION */
                    245:                u.u_sleep [0] = '\0'; /* We are not sleeping to start with.  */
                    246:                sproto (0);
                    247:                segload ();
                    248:                u.u_rval2 = SELF->p_ppid;
                    249:                return 0;
                    250:        }
                    251: }
                    252: 
                    253: /*
                    254:  * Die.
                    255:  */
                    256: pexit(s)
                    257: {
                    258:        register PROC *pp1;
                    259:        register PROC *pp;
                    260:        register SEG  *sp;
                    261:        register int n;
                    262:        PROC          * parent = NULL;
                    263: 
                    264:        pp = SELF;
                    265:        T_PIGGY( 0x1, printf("%s:pexit(%x)", u.u_comm, s));
                    266: 
                    267:        ndpEndProc ();
                    268: 
                    269:        /*
                    270:         * Cancel alarm and poll timers [if any].
                    271:         */
                    272:        timeout(&pp->p_alrmtim, 0, NULL, 0);
                    273:        timeout(&pp->p_polltim, 0, NULL, 0);
                    274: 
                    275:        /*
                    276:         * Write out accounting directory and close all files associated with
                    277:         * this process.
                    278:         */
                    279:        setacct();
                    280:        if (u.u_rdir)
                    281:                ldetach(u.u_rdir);
                    282:        if (u.u_cdir)
                    283:                ldetach(u.u_cdir);
                    284:        fdaclose();
                    285: 
                    286:        /*
                    287:         * Free all segments in reverse order, except for user-area.
                    288:         */
                    289:        for (n = NUSEG; --n > 0;) {
                    290:                if (sp = pp->p_segp[n]) {
                    291:                        pp->p_segp[n] = NULL;
                    292:                        sfree(sp);
                    293:                }
                    294:        }
                    295: 
                    296:        /* Detach remaining shared memory segments. */
                    297:        shmAllDt();
                    298: 
                    299:        /* Adjust(undo) all semaphores. */
                    300:        semAllAdjust(pp);
                    301: 
                    302:        /*
                    303:         * Wakeup our parent.  If we have any children, init will become the
                    304:         * new parent.  If there are any children we are tracing who are
                    305:         * waiting for us, we wake them up.
                    306:         */
                    307:        pp1 = &procq;
                    308: 
                    309:        /* pp1 runs through the list of all processes */
                    310:        while ((pp1=pp1->p_nforw) != &procq) {
                    311: 
                    312:                /* if pp1 points to parent of the current process...*/
                    313:                if (pp1->p_pid == pp->p_ppid) {
                    314:                        parent = pp1;   /* Remember our parent.  */
                    315:                        if (ASLEEP(pp1) && pp1->p_event==(char *)pp1)
                    316:                                wakeup((char *)pp1);
                    317:                }
                    318: 
                    319:                /* if pp1 points to child of the current process...*/
                    320:                if (pp1->p_ppid == pp->p_pid) {
                    321:                        pp1->p_ppid = 1;
                    322:                        if (pp1->p_state == PSDEAD)
                    323:                                wakeup((char *)eprocp);
                    324:                        if (pp1->p_flags&PFTRAC)
                    325:                                wakeup((char *)&pts.pt_req);
                    326:                }
                    327:        }
                    328: 
                    329:        /*
                    330:         * Mark us as dead and give up the processor forever.
                    331:         */
                    332:        pp->p_exit = s;
                    333:        pp->p_state = PSDEAD;
                    334: 
                    335:        /*
                    336:         * If this is a process group leader, inform all members of the group
                    337:         * of the recent death with a HUP signal.
                    338:         */
                    339:        if (pp->p_group == pp->p_pid)
                    340:                ukill(-pp->p_pid, SIGHUP);
                    341: 
                    342:        /*
                    343:         * If the parent is ignoring SIGCLD, 
                    344:         * remove the zombie right away.
                    345:         */
                    346: 
                    347:        if (parent == NULL)
                    348:                panic ("%d (@ %x) has no parent!\n", SELF->p_pid, SELF);
                    349: 
                    350:        if ((proc_signal_misc (parent) & __SF_NOCLDWAIT) != 0) {
                    351:                /*
                    352:                 * The parent has requested that no zombie processes be
                    353:                 * created out of childen.
                    354:                 */
                    355: 
                    356:                parent->p_cutime += pp->p_utime + pp->p_cutime;
                    357:                parent->p_cstime += pp->p_stime + pp->p_cstime;
                    358:                relproc (pp);
                    359:        } else {
                    360:                /*
                    361:                 * Send parent a notification of our demise.
                    362:                 */
                    363:                __siginfo_t     sigchld;
                    364: 
                    365:                sigchld.__si_signo = SIGCHLD;
                    366:                sigchld.__si_errno = 0;
                    367:                if (__WIFEXITED (s)) {
                    368:                        sigchld.__si_code = __CLD_EXITED;
                    369:                        sigchld.__si_status = __WEXITSTATUS (s);
                    370:                } else {
                    371:                        sigchld.__si_code = __WCOREDUMP (s) ? __CLD_DUMPED :
                    372:                                                              __CLD_KILLED;
                    373:                        sigchld.__si_status = __WTERMSIG (s);
                    374:                }
                    375:                sigchld.__si_pid = SELF->p_pid;
                    376:                proc_send_signal (parent, & sigchld);
                    377:        }
                    378: 
                    379:        dispatch();
                    380: }
                    381: 
                    382: /*
                    383:  * x_sleep()
                    384:  *
                    385:  * Surrender CPU while awaiting some event or resource.
                    386:  *
                    387:  * Arguments:
                    388:  *     event:          key value; so wakeup() can find this sleep
                    389:  *     schedPri:       prilo/primed/prihi/pritape/pritty/pridisk/prinet
                    390:  *                     just copied into proc struct for scheduler to use.
                    391:  *                     (see sys/v_types.h)
                    392:  *     sleepPri:       slpriNoSig      - signals may not interrupt sleep
                    393:  *                     slpriSigLjmp    - signals cause longjmp (EINTR)
                    394:  *                     slpriSigCatch   - signals are caught
                    395:  *                     (see sys/sched.h)
                    396:  *     reason:         up to 10 chars of text for ps command "event"
                    397:  *
                    398:  * Return values:
                    399:  *     PROCESS_NORMAL_WAKE     wakeup received
                    400:  *     PROCESS_SIGNALLED       signal (other than SIGSTOP/SIGCONT) received
                    401:  *     PROCESS_CONTINUED       SIGSTOP/SIGCONT (unimplemented now)
                    402:  *
                    403:  * If longjmp occurs, won't return from x_sleep!
                    404:  */
                    405: 
                    406: __sleep_t
                    407: x_sleep(event, schedPri, sleepPri, reason)
                    408: char * event;
                    409: int schedPri;
                    410: int sleepPri;
                    411: char * reason;
                    412: {
                    413:        int i;
                    414:        register PROC *bp;
                    415:        register PROC *fp;
                    416:        register PROC *pp;
                    417:        register int s;
                    418: 
                    419:        /*
                    420:         * The descriptive string may be at most 10 characters long.
                    421:         * It will only be NUL terminated if it has 9 or fewer characters.
                    422:         */
                    423:        for (i = 0; i < U_SLEEP_LEN; ++i) {
                    424:                if ('\0' == (u.u_sleep[i] = reason[i])) {
                    425:                        break;
                    426:                }
                    427:        }
                    428: 
                    429:        pp = SELF;
                    430: 
                    431:        /*
                    432:         * Get ready to go to sleep and do so.
                    433:         */
                    434:        s = sphi();
                    435:        pp->p_state = (sleepPri == slpriNoSig) ? PSSLEEP : PSSLSIG;
                    436:        pp->p_schedPri = schedPri;
                    437:        pp->p_event = event;
                    438:        fp = &linkq[hash(event)];
                    439:        bp = fp->p_lback;
                    440:        pp->p_lforw = fp;
                    441:        fp->p_lback = pp;
                    442:        pp->p_lback = bp;
                    443:        bp->p_lforw = pp;
                    444:        spl(s);
                    445: 
                    446:        /* Here is sleep if signals may *not* interrupt. */
                    447:        if (sleepPri == slpriNoSig) {
                    448:                dispatch ();
                    449:                u.u_sleep [0] = '\0';
                    450:                return PROCESS_NORMAL_WAKE;
                    451:        }
                    452: 
                    453:        /* Here is sleep if signals *may* interrupt. */
                    454:        /* Don't sleep at all if there is already a signal pending. */
                    455: 
                    456:        if (curr_signal_pending () == 0) {
                    457:                dispatch ();
                    458:                u.u_sleep [0] = '\0';
                    459:                if (curr_signal_pending () == 0)
                    460:                        return PROCESS_NORMAL_WAKE;
                    461:        }
                    462: 
                    463:        /* The process has been interrupted from sleep by a signal. */
                    464: 
                    465:        if (sleepPri == slpriSigCatch)
                    466:                return PROCESS_SIGNALLED;
                    467: 
                    468:        /* Do longjmp to beginning of system call. */
                    469:        T_HAL(8, printf("[%d]Ljmps ", SELF->p_pid));
                    470:        sphi();
                    471:        envrest(&u.u_sigenv);
                    472: }
                    473: 
                    474: /*
                    475:  * Defer function to wake up all processes sleeping on the event `e'.
                    476:  */
                    477: wakeup(e)
                    478: char *e;
                    479: {
                    480:        void dwakeup();
                    481: 
                    482: #ifdef TRACER
                    483:        /*
                    484:         * In diagnostic kernel, keep return addr on queue as well.
                    485:         */
                    486:        int *r=(int*)(&e);
                    487:        defer0(dwakeup, e, *(r-1));
                    488: #else
                    489:        defer(dwakeup, e);
                    490: #endif
                    491: }
                    492: 
                    493: /*
                    494:  * Wake up all processes sleeping on "event".
                    495:  */
                    496: void
                    497: dwakeup(event)
                    498: char *event;
                    499: {
                    500:        register PROC *pp;
                    501:        register PROC *pp1;
                    502:        register int s;
                    503: 
                    504:        /*
                    505:         * Identify event queue to check.
                    506:         * Disable interrupts.
                    507:         */
                    508:        pp1 = &linkq[hash(event)];
                    509:        pp = pp1;
                    510:        s = sphi();
                    511: 
                    512:        /*
                    513:         * Traverse doubly-linked circular event-queue.
                    514:         */
                    515:        while ((pp = pp->p_lforw) != pp1) {
                    516: 
                    517:                /*
                    518:                 * Process is waiting on event 'event'.
                    519:                 */
                    520:                if (pp->p_event == event) {
                    521:                        /*
                    522:                         * Remove process from event queue.
                    523:                         * Update process priority.
                    524:                         * Insert process into run queue.
                    525:                         */
                    526:                        pp->p_lback->p_lforw = pp->p_lforw;
                    527:                        pp->p_lforw->p_lback = pp->p_lback;
                    528:                        setrun(pp);
                    529: 
                    530:                        /*
                    531:                         * Enable interrupts.
                    532:                         * Restart search at start of event queue.
                    533:                         * Disable interrupts.
                    534:                         */
                    535:                        spl(s);
                    536:                        pp = pp1;
                    537:                        s = sphi();
                    538:                }
                    539:        }
                    540:        spl(s);
                    541: }
                    542: 
                    543: /*
                    544:  * Select next process for execution, working backward from iprocp.
                    545:  * If it is not the idle process, delete it from the run queue.
                    546:  * If it is not the current process, consave the current process and
                    547:  * conrest the selected process.
                    548:  */
                    549: dispatch()
                    550: {
                    551:        register PROC *pp;
                    552:        register int s;
                    553: 
                    554:        s = sphi();
                    555:        pp = iprocp->p_lback;
                    556:        if (pp != iprocp) {
                    557:                pp->p_lforw->p_lback = pp->p_lback;
                    558:                pp->p_lback->p_lforw = pp->p_lforw;
                    559:        }
                    560:        spl(s);
                    561: 
                    562:        quantum = NCRTICK;
                    563:        disflag = 0;
                    564:        if (pp != SELF) {
                    565:                /*
                    566:                 * Consave() returns twice.
                    567:                 * 1st time is after our context is saved in u.u_syscon,
                    568:                 *      whereupon we should restore other proc's context.
                    569:                 * 2nd time is after our context is restored by another proc.
                    570:                 * Conrest() forces a context switch to a new process.
                    571:                 */
                    572:                s = sphi ();
                    573:                SELF = pp;
                    574:                if (consave (& u.u_syscon) == 0) {
                    575:                        conrest (* pp->p_segp [SIUSERP]->s_vmem,
                    576:                                 & u.u_syscon);
                    577:                }
                    578: 
                    579:                if (SELF->p_pid) {      /* init is special! */
                    580:                        ndpConRest ();
                    581:                        segload ();
                    582:                }
                    583: 
                    584:                spl (s);
                    585:        }
                    586: }
                    587: 
                    588: /*
                    589:  * Add a process to the run queue, just forward of iprocp.
                    590:  * This routine must be called at high priority.
                    591:  */
                    592: setrun(pp)
                    593: register PROC *pp;
                    594: {
                    595:        pp->p_lback = iprocp;
                    596:        pp->p_lforw = iprocp->p_lforw;
                    597:        pp->p_lback->p_lforw = pp;
                    598:        pp->p_lforw->p_lback = pp;
                    599:        pp->p_state = PSRUN;
                    600: }
                    601: 
                    602: /*
                    603:  * Wait for the gate `g' to unlock, and then lock it.
                    604:  */
                    605: lock(g)
                    606: register GATE g;
                    607: {
                    608:        register int s;
                    609: 
                    610:        s = sphi ();
                    611:        while (g->_lock [0]) {
                    612: #ifdef TRACER
                    613:                if (g->_lock [0] != 1)
                    614:                        panic ("Uninitialised gate");
                    615: #endif
                    616:                g->_lock [1] = 1;
                    617:                x_sleep ((char *) g, primed, slpriNoSig, "lock");
                    618:                /* Waiting for a gate to unlock.  */
                    619:        }
                    620:        g->_lock [0] = 1;
                    621:        __GATE_LOCK_COUNT (g);
                    622:        spl (s);
                    623: }
                    624: 
                    625: /*
                    626:  * Unlock the gate `g'.
                    627:  */
                    628: unlock(g)
                    629: register GATE g;
                    630: {
                    631: #ifdef TRACER
                    632:        if (g->_lock [0] == 0)
                    633:                panic ("Gate not locked!");
                    634: #endif
                    635:        g->_lock [0] = 0;
                    636:        if (g->_lock [1]) {
                    637: #ifdef TRACER
                    638:                if (g->_lock [1] != 1)
                    639:                        panic ("Uninitialised gate");
                    640: #endif
                    641:                g->_lock [1] = 0;
                    642:                disflag = 1;
                    643:                wakeup ((char *)g);
                    644:        }
                    645: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.