Annotation of MiNT/src/rendez.c, revision 1.1

1.1     ! root        1: /* 
        !             2: 
        !             3:  * The rendezvous: 
        !             4: 
        !             5:  * a little bit of message passing with a lot of synchronization.
        !             6: 
        !             7:  *
        !             8: 
        !             9:  * Pmsg(mode,mboxid,msgptr);
        !            10: 
        !            11:  * short mode;
        !            12: 
        !            13:  * long mboxid;
        !            14: 
        !            15:  * struct { long msg1, msg2; short pid; } *msgptr;
        !            16: 
        !            17:  *
        !            18: 
        !            19:  * 'mode' bits:
        !            20: 
        !            21:  *   0000      read
        !            22: 
        !            23:  *   0001      write
        !            24: 
        !            25:  *   0002      write, then read from mboxid "PDxx" where xx is my pid.
        !            26: 
        !            27:  *
        !            28: 
        !            29:  *   8000      OR with this bit to make the operation non-blocking.
        !            30: 
        !            31:  *
        !            32: 
        !            33:  * The messages are five words long: two longs and a short, in that order. 
        !            34: 
        !            35:  * The values  of the first two longs are totally up to the processes in
        !            36: 
        !            37:  * question.  The value of the short is the PID of the sender.  On return
        !            38: 
        !            39:  * from writes, the short is the PID of the process that read your message.
        !            40: 
        !            41:  * On return from reads, it's the PID of the writer.
        !            42: 
        !            43:  *
        !            44: 
        !            45:  * If the 0x8000 bit is set in the mode, and there is not a reader/writer
        !            46: 
        !            47:  * for the mboxid already on the WAIT_Q, this call returns -1.
        !            48: 
        !            49:  *
        !            50: 
        !            51:  * In mode 2, the writer is declaring that it wants to wait for a reply to
        !            52: 
        !            53:  * the message.  What happens is that the reader gets put on the ready
        !            54: 
        !            55:  * queue, but the writer is atomically turned into a reader on a mailbox
        !            56: 
        !            57:  * whose mboxid is (0xFFFF0000 .OR. pid). The idea is that this process
        !            58: 
        !            59:  * will sleep until awoken at a later time by the process that read the
        !            60: 
        !            61:  * message.  The process reading the original request is guaranteed not to
        !            62: 
        !            63:  * block when writing the reply.
        !            64: 
        !            65:  *
        !            66: 
        !            67:  * There is no provision for a timeout.
        !            68: 
        !            69: 
        !            70: 
        !            71: The flow is as follows:
        !            72: 
        !            73: 
        !            74: 
        !            75:     if (you're writing)
        !            76: 
        !            77:        if (there's somebody waiting to read)
        !            78: 
        !            79:                                            (SATISFY THE RENDEZVOUS RIGHT AWAY)
        !            80: 
        !            81:            copy msg from your data space into his proc structure
        !            82: 
        !            83:            wake him up
        !            84: 
        !            85:            if (you're doing a write/read)
        !            86: 
        !            87:                                        (TURN AROUND AND BLOCK WAITING TO READ)
        !            88: 
        !            89:                write mode 0 to your proc struct and change your mbid
        !            90: 
        !            91:                goto dosleep
        !            92: 
        !            93:            else
        !            94: 
        !            95:                fill in his PID in your data space
        !            96: 
        !            97:                return 0;
        !            98: 
        !            99:            endif
        !           100: 
        !           101:        else
        !           102: 
        !           103:                                       (YOU HAVE TO BLOCK WAITING FOR A WRITER)
        !           104: 
        !           105:            copy from your data space to your proc structure
        !           106: 
        !           107:            goto dosleep
        !           108: 
        !           109:        endif
        !           110: 
        !           111:     else (you're reading)
        !           112: 
        !           113:        if (there's somebody waiting to write)
        !           114: 
        !           115:                                            (SATISFY THE RENDEZVOUS RIGHT AWAY)
        !           116: 
        !           117:            copy msg from his proc to your data space
        !           118: 
        !           119:            if (he's doing a write/read)
        !           120: 
        !           121:                                         (TURN HIM AROUND WAITING FOR A WRITER)
        !           122: 
        !           123:                change his mode from write/read to read, and his mbid
        !           124: 
        !           125:                leave him asleep
        !           126: 
        !           127:            else
        !           128: 
        !           129:                wake him up
        !           130: 
        !           131:            endif
        !           132: 
        !           133:            return 0;
        !           134: 
        !           135:        else
        !           136: 
        !           137:                                       (YOU HAVE TO BLOCK WAITING FOR A READER)
        !           138: 
        !           139:            write mode 0 to your proc struct
        !           140: 
        !           141:            goto dosleep
        !           142: 
        !           143:        endif
        !           144: 
        !           145:     endif
        !           146: 
        !           147: 
        !           148: 
        !           149: dosleep:
        !           150: 
        !           151:     if (non-blocking mode) return EWOULDBLOCK;
        !           152: 
        !           153:     do {
        !           154: 
        !           155:         sleep(WAIT_Q, WAIT_MB);
        !           156: 
        !           157:     } until (a rendezvous happens);
        !           158: 
        !           159:     (when you wake up...)
        !           160: 
        !           161:     if (you're reading)
        !           162: 
        !           163:        copy from your proc struct to your data space
        !           164: 
        !           165:     else
        !           166: 
        !           167:        copy the writer's PID from your proc struct to your data space
        !           168: 
        !           169:     endif
        !           170: 
        !           171:     return 0;
        !           172: 
        !           173: 
        !           174: 
        !           175:  * The wait_cond we use is WAIT_MB, and the mbid waited for is another
        !           176: 
        !           177:  * field in the proc structure, along with the two longs and a short you
        !           178: 
        !           179:  * need to remember what somebody else wrote to you, and the mode field for
        !           180: 
        !           181:  * what kind of operation you're doing (read, write, write/read).
        !           182: 
        !           183:  *
        !           184: 
        !           185:  * The beauty of this is that mailboxes don't need to be created or
        !           186: 
        !           187:  * destroyed, and the blocking and turnaround are atomic, and it's a way to
        !           188: 
        !           189:  * do rendezvous and interprocess communication without lots of system
        !           190: 
        !           191:  * calls (Pgetpid, Fwrite, Pause, plus synchronization worries about having
        !           192: 
        !           193:  * the reader get the message and Pkill you before you've Paused).
        !           194: 
        !           195:  *
        !           196: 
        !           197:  * Note: Say PID 33 writes in mode 2 to MBXX and it blocks. Then somebody
        !           198: 
        !           199:  * writes to PD33, and blocks because you're not waiting for it.  Then your
        !           200: 
        !           201:  * write is satisfied, so you become a reader on PD33.  We should check to
        !           202: 
        !           203:  * see if there are any writers on PD33 and satisfy that rendezvous! But
        !           204: 
        !           205:  * this could go on forever, and it's easier to stop here.  So you lose:
        !           206: 
        !           207:  * this situation is timing sensitive.  It shouldn't come up anyway.
        !           208: 
        !           209:  */
        !           210: 
        !           211: 
        !           212: 
        !           213: #include "mint.h"
        !           214: 
        !           215: 
        !           216: 
        !           217: long
        !           218: 
        !           219: p_msg(mode, mbid, ptr)
        !           220: 
        !           221:     int mode;
        !           222: 
        !           223:     long mbid;
        !           224: 
        !           225:     char *ptr;
        !           226: 
        !           227: {
        !           228: 
        !           229:     int noblock;
        !           230: 
        !           231:     PROC *p;
        !           232: 
        !           233: 
        !           234: 
        !           235:     TRACE("Pmsg(%d,%lx,%lx)",mode,mbid,ptr);
        !           236: 
        !           237: 
        !           238: 
        !           239:     noblock = (mode & 0x8000);
        !           240: 
        !           241:     mode &= ~0x8000;
        !           242: 
        !           243: 
        !           244: 
        !           245:     if (mode == 0) {
        !           246: 
        !           247:        /* read */
        !           248: 
        !           249:        /* walk the whole process list looking for a writer */
        !           250: 
        !           251:        for (p = proclist; p; p = p->gl_next) {
        !           252: 
        !           253:            if ((p->mb_mode == 1 || p->mb_mode == 2) && p->mb_mbid == mbid) {
        !           254: 
        !           255:                /* this process is trying to write this mbox */
        !           256: 
        !           257: /*             DEBUG("Pmsg read: found a writer (pid %d)",p->pid); */
        !           258: 
        !           259:                goto got_rendezvous;
        !           260: 
        !           261:            }
        !           262: 
        !           263:        }
        !           264: 
        !           265: /*     DEBUG("Pmsg read: no writers"); */
        !           266: 
        !           267:        /* nobody is writing just now */
        !           268: 
        !           269:        goto dosleep;
        !           270: 
        !           271:     }
        !           272: 
        !           273:     else if (mode == 1 || mode == 2) {
        !           274: 
        !           275:        /* write, or write/read */
        !           276: 
        !           277:        /* walk the whole process list looking for a reader */
        !           278: 
        !           279:        for (p = proclist; p; p = p->gl_next) {
        !           280: 
        !           281:            if (p->mb_mode == 0 && p->mb_mbid == mbid) {
        !           282: 
        !           283:                /* this process is reading this mbox */
        !           284: 
        !           285: /*             DEBUG("Pmsg write: found a reader (pid %d)",p->pid); */
        !           286: 
        !           287:                goto got_rendezvous;
        !           288: 
        !           289:            }
        !           290: 
        !           291:        }
        !           292: 
        !           293:        /* nobody is reading just now */
        !           294: 
        !           295:        curproc->mb_long1 = *(long *)ptr;       /* copy the message */
        !           296: 
        !           297:        curproc->mb_long2 = *(long *)(ptr+4);   /* into my proc struct */
        !           298: 
        !           299: /*     DEBUG("Pmsg write: no readers"); */
        !           300: 
        !           301:        goto dosleep;
        !           302: 
        !           303:     }
        !           304: 
        !           305:     else return EINVFN;                        /* invalid mode */
        !           306: 
        !           307: 
        !           308: 
        !           309: /*
        !           310: 
        !           311:  * we get here if we actually have a rendezvous between p and curproc.
        !           312: 
        !           313:  */
        !           314: 
        !           315: 
        !           316: 
        !           317: got_rendezvous:
        !           318: 
        !           319:     if (!mode) {
        !           320: 
        !           321:        /* curproc is reading */
        !           322: 
        !           323:        *(long *)(ptr) = p->mb_long1;           /* copy the message */
        !           324: 
        !           325:        *(long *)(ptr+4) = p->mb_long2;         /* from his proc struct */
        !           326: 
        !           327:        *(short *)(ptr+8) = p->pid;             /* provide the PID */
        !           328: 
        !           329: 
        !           330: 
        !           331:        if (p->mb_mode == 2) {
        !           332: 
        !           333:            /*
        !           334: 
        !           335:             * The blocked write was in mode 2: writer becomes a reader and
        !           336: 
        !           337:             * stays on WAIT_Q waiting on WAIT_MB.
        !           338: 
        !           339:             */
        !           340: 
        !           341: /*         DEBUG("Pmsg: previously-blocked writer becomes reader"); */
        !           342: 
        !           343:            p->mb_mbid = 0xFFFF0000L | p->pid;
        !           344: 
        !           345:            p->mb_mode = 0;
        !           346: 
        !           347:        }
        !           348: 
        !           349:        else {
        !           350: 
        !           351:            /* The blocked write was in mode 1: writer wakes up */
        !           352: 
        !           353: /*         DEBUG("Pmsg: previously-blocked writer put on run queue"); */
        !           354: 
        !           355:            p->mb_writer = curproc->pid;        /* tell writer reader's pid */
        !           356: 
        !           357:            p->mb_mode = -1;                    /* mark rendezvous */
        !           358: 
        !           359:            p->wait_cond = 0;                   /* not necessary? */
        !           360: 
        !           361:            if (p->wait_q != READY_Q) {
        !           362: 
        !           363:                /* wake up the writer if it is sleeping */
        !           364: 
        !           365:                rm_q(p->wait_q,p);
        !           366: 
        !           367:                add_q(READY_Q,p);
        !           368: 
        !           369:            }
        !           370: 
        !           371:        }
        !           372: 
        !           373:        return 0;
        !           374: 
        !           375:     }
        !           376: 
        !           377:     else {
        !           378: 
        !           379:        /* curproc is writing */
        !           380: 
        !           381:        p->mb_writer = curproc->pid;            /* provide the PID */
        !           382: 
        !           383:        p->mb_long1 = *(long *)(ptr);           /* copy the message */
        !           384: 
        !           385:        p->mb_long2 = *(long *)(ptr+4);
        !           386: 
        !           387: /*     DEBUG("Pmsg: previously-blocked reader put on run queue"); */
        !           388: 
        !           389:        p->mb_mode = -1;                        /* mark rendezvous */
        !           390: 
        !           391:        p->wait_cond = 0;                       /* not necessary? */
        !           392: 
        !           393:        if (p->wait_q != READY_Q) {
        !           394: 
        !           395:            /* wake up the reader if it is sleeping */
        !           396: 
        !           397:            rm_q(p->wait_q,p);
        !           398: 
        !           399:            add_q(READY_Q,p);
        !           400: 
        !           401:        }
        !           402: 
        !           403:        if (mode == 2) {
        !           404: 
        !           405:            /* now curproc becomes a reader */
        !           406: 
        !           407: /*         DEBUG("Pmsg: curproc (writer) becomes reader & blocks"); */
        !           408: 
        !           409:            mbid = 0xFFFF0000L | curproc->pid;
        !           410: 
        !           411:            mode = 0;
        !           412: 
        !           413:            goto dosleep;
        !           414: 
        !           415:        }
        !           416: 
        !           417:        else {
        !           418: 
        !           419:            *(short *)(ptr+8) = p->pid;         /* tell reader writer's pid */
        !           420: 
        !           421:            return 0;
        !           422: 
        !           423:        }
        !           424: 
        !           425:     }
        !           426: 
        !           427: 
        !           428: 
        !           429: /*
        !           430: 
        !           431:  * we get here when a read or write should block because there's nobody
        !           432: 
        !           433:  * already waiting at the other end.
        !           434: 
        !           435:  */
        !           436: 
        !           437: 
        !           438: 
        !           439: dosleep: 
        !           440: 
        !           441:        if (noblock) {
        !           442: 
        !           443: /*         DEBUG("Pmsg: non-blocking mode: EWOULDBLOCK"); */
        !           444: 
        !           445:            return -1L;
        !           446: 
        !           447:        }
        !           448: 
        !           449: /*     DEBUG("Pmsg: put curproc to sleep."); */
        !           450: 
        !           451:        curproc->mb_mbid = mbid;        /* and ID waited for */
        !           452: 
        !           453:        curproc->mb_mode = mode;        /* save mode */
        !           454: 
        !           455: 
        !           456: 
        !           457: /*
        !           458: 
        !           459:  * OK: now we sleep until a rendezvous has occured. The loop is because we
        !           460: 
        !           461:  * may be woken up to deal with signals before the rendezvous.  The thing
        !           462: 
        !           463:  * that says the rendezvous actually happened is that mb_mode got changed
        !           464: 
        !           465:  * to -1.
        !           466: 
        !           467:  */
        !           468: 
        !           469:        do {
        !           470: 
        !           471:                sleep(WAIT_Q, WAIT_MB);                 /* block */
        !           472: 
        !           473:        } while (curproc->mb_mode != -1);
        !           474: 
        !           475: /*
        !           476: 
        !           477:        DEBUG("Pmsg: woke up; mode %d cpmode %d writer %d long1 %lx long2 %lx",
        !           478: 
        !           479:                mode,curproc->mb_mode,curproc->mb_writer,
        !           480: 
        !           481:                curproc->mb_long1, curproc->mb_long2);
        !           482: 
        !           483: */
        !           484: 
        !           485: 
        !           486: 
        !           487:        /*
        !           488: 
        !           489:         * When we wake up, we transfer the message from our proc struct
        !           490: 
        !           491:         * into our message pointer space if we were reading, and do
        !           492: 
        !           493:         * nothing if we were writing.  The write/read case is taken care
        !           494: 
        !           495:         * of without waking this process up at all.
        !           496: 
        !           497:         *
        !           498: 
        !           499:         * Check curproc->mode because it may not be the mode we started
        !           500: 
        !           501:         * with any more.
        !           502: 
        !           503:         */
        !           504: 
        !           505:        if (mode == 0) {
        !           506: 
        !           507:            *(long *)(ptr) = curproc->mb_long1;
        !           508: 
        !           509:            *(long *)(ptr+4) = curproc->mb_long2;
        !           510: 
        !           511:        }
        !           512: 
        !           513:        /* in any case, copy the 'writer' field because that's the PID */
        !           514: 
        !           515:        /* of the other side of the rendezvous */
        !           516: 
        !           517:        *(short *)(ptr+8) = curproc->mb_writer;
        !           518: 
        !           519:        return 0;
        !           520: 
        !           521: }
        !           522: 
        !           523: 
        !           524: 
        !           525: /*
        !           526: 
        !           527:  * more mutex: this time a semaphore.
        !           528: 
        !           529:  *
        !           530: 
        !           531:  * long Psemaphore(short mode, long id, long timeout)
        !           532: 
        !           533:  *
        !           534: 
        !           535:  *     MODE    ACTION
        !           536: 
        !           537:  *       0     Create and get a semaphore with the given ID.
        !           538: 
        !           539:  *       1     Destroy.
        !           540: 
        !           541:  *       2     Get (blocks until it's available or destroyed, or timeout).
        !           542: 
        !           543:  *       3     Release.
        !           544: 
        !           545:  *
        !           546: 
        !           547:  * RETURNS
        !           548: 
        !           549:  *
        !           550: 
        !           551:  *     CODE    MEANING
        !           552: 
        !           553:  *       0     OK.  Created/obtained/released/destroyed, depending on mode.
        !           554: 
        !           555:  *     ERROR   You asked for a semaphore that you already own.
        !           556: 
        !           557:  *     ERANGE  That semaphore doesn't exist (modes 1, 2, 3, 4),
        !           558: 
        !           559:  *             or out of slots for new semaphores (0).
        !           560: 
        !           561:  *     EACCDN  That semaphore exists already, so you can't create it (mode 0),
        !           562: 
        !           563:  *             or the semaphore is busy (returned from mode 3 if you lose),
        !           564: 
        !           565:  *             or you don't own it (modes 1 and 4).
        !           566: 
        !           567:  *
        !           568: 
        !           569:  * If you create a semaphore you will also own it, so you have to release
        !           570: 
        !           571:  * it with mode 2 before anybody else can get it.  Semaphore ID's are magic
        !           572: 
        !           573:  * numbers which the creator should make available to the users. You have
        !           574: 
        !           575:  * to own a semaphore to destroy it.  If you block waiting for a semaphore,
        !           576: 
        !           577:  * and then it gets destroyed, you get ERANGE.
        !           578: 
        !           579:  *
        !           580: 
        !           581:  * The timeout argument is ignored except in mode 2.  In that mode, 0 means
        !           582: 
        !           583:  * "return immediately" and, as a special case, -1 means "forever."
        !           584: 
        !           585:  * Since it is in fact an unsigned long number of milliseconds, -2 means
        !           586: 
        !           587:  * 49 hours, but here -1 truly means forever.
        !           588: 
        !           589:  *
        !           590: 
        !           591:  */
        !           592: 
        !           593: 
        !           594: 
        !           595: #define NSEMAPHORES 10
        !           596: 
        !           597: 
        !           598: 
        !           599: typedef struct sema {
        !           600: 
        !           601:     struct sema *next;
        !           602: 
        !           603:     long id;
        !           604: 
        !           605:     short owner;       /* -1 means "available" */
        !           606: 
        !           607: } SEMA;
        !           608: 
        !           609: 
        !           610: 
        !           611: static SEMA *semalist;
        !           612: 
        !           613: 
        !           614: 
        !           615: static void unsemame P_((PROC *));
        !           616: 
        !           617: 
        !           618: 
        !           619: static void
        !           620: 
        !           621: unsemame(p)
        !           622: 
        !           623: PROC *p;
        !           624: 
        !           625: {
        !           626: 
        !           627:     /* take process P off the WAIT_Q and put it on the READY_Q */
        !           628: 
        !           629:     TRACE("semaphore sleep ends for pid %d",p->pid);
        !           630: 
        !           631:     if (p->wait_q == WAIT_Q) {
        !           632: 
        !           633:            rm_q(WAIT_Q,p);
        !           634: 
        !           635:            add_q(READY_Q,p);
        !           636: 
        !           637:     }
        !           638: 
        !           639:     p->wait_cond = 0;
        !           640: 
        !           641: }
        !           642: 
        !           643: 
        !           644: 
        !           645: long
        !           646: 
        !           647: p_semaphore(mode,id,timeout)
        !           648: 
        !           649: int mode;
        !           650: 
        !           651: long id;
        !           652: 
        !           653: long timeout;
        !           654: 
        !           655: {
        !           656: 
        !           657:     SEMA *s, **q;
        !           658: 
        !           659:     TIMEOUT *timeout_ptr = NULL;
        !           660: 
        !           661: 
        !           662: 
        !           663:     TRACE("Psemaphore(%d,%lx)",mode,id);
        !           664: 
        !           665: 
        !           666: 
        !           667:     switch (mode) {
        !           668: 
        !           669:        case 0: {                       /* create */
        !           670: 
        !           671:            for (s = semalist; s; s = s->next) {
        !           672: 
        !           673:                if (s->id == id) {
        !           674: 
        !           675:                    DEBUG("Psemaphore(%d,%lx): already exists",mode,id);
        !           676: 
        !           677:                    return EACCDN;
        !           678: 
        !           679:                }
        !           680: 
        !           681:            }
        !           682: 
        !           683:            /* get a new one */
        !           684: 
        !           685:            if (!(s = (SEMA *)kmalloc(sizeof(SEMA)))) return ENSMEM;
        !           686: 
        !           687:            s->id = id;
        !           688: 
        !           689:            s->owner = curproc->pid;
        !           690: 
        !           691:            s->next = semalist;
        !           692: 
        !           693:            semalist = s;
        !           694: 
        !           695:            return E_OK;
        !           696: 
        !           697:        }
        !           698: 
        !           699:        case 2: {                       /* get */
        !           700: 
        !           701: loop:
        !           702: 
        !           703:            for (s = semalist; s; s = s->next) {
        !           704: 
        !           705:                if (s->id == id) {
        !           706: 
        !           707:                    /* found your semaphore */
        !           708: 
        !           709:                    if (s->owner == curproc->pid) {
        !           710: 
        !           711:                        DEBUG("Psemaphore(%d,%lx): curproc already owns it!",
        !           712: 
        !           713:                                mode,id);
        !           714: 
        !           715:                        return ERROR;
        !           716: 
        !           717:                    }
        !           718: 
        !           719:                    if (s->owner == -1) {
        !           720: 
        !           721:                        /* it's free; you get it */
        !           722: 
        !           723:                        s->owner = curproc->pid;
        !           724: 
        !           725:                        if (timeout_ptr) canceltimeout(timeout_ptr);
        !           726: 
        !           727:                        return 0;
        !           728: 
        !           729:                    }
        !           730: 
        !           731:                    else {
        !           732: 
        !           733:                        /* not free */
        !           734: 
        !           735:                        if (timeout == 0) {
        !           736: 
        !           737:                            /* non-blocking mode */
        !           738: 
        !           739:                            return EACCDN;
        !           740: 
        !           741:                        }
        !           742: 
        !           743:                        else {
        !           744: 
        !           745:                            if (timeout != -1 && !timeout_ptr) {
        !           746: 
        !           747:                                /* schedule a timeout */
        !           748: 
        !           749:                                timeout_ptr = addtimeout(timeout,unsemame);
        !           750: 
        !           751:                            }
        !           752: 
        !           753:                            /* block until it's released, then try again */
        !           754: 
        !           755:                            sleep(WAIT_Q,WAIT_SEMA);
        !           756: 
        !           757:                            if (curproc->wait_cond != WAIT_SEMA) {
        !           758: 
        !           759:                                TRACE("Psemaphore(%d,%lx) timed out",mode,id);
        !           760: 
        !           761:                                return EACCDN;
        !           762: 
        !           763:                            }
        !           764: 
        !           765:                            goto loop;
        !           766: 
        !           767:                        }
        !           768: 
        !           769:                    }
        !           770: 
        !           771:                }
        !           772: 
        !           773:            }
        !           774: 
        !           775:            /* no such semaphore (possibly deleted while we were waiting) */
        !           776: 
        !           777:            if (timeout_ptr) canceltimeout(timeout_ptr);
        !           778: 
        !           779:            DEBUG("Psemaphore(%d,%lx): no such semaphore",mode,id);
        !           780: 
        !           781:            return ERANGE;
        !           782: 
        !           783:        }
        !           784: 
        !           785:        case 3:                         /* release */
        !           786: 
        !           787:        case 1: {                       /* destroy */
        !           788: 
        !           789:            /*
        !           790: 
        !           791:             * Style note: this is a handy way to chain down a linked list.
        !           792: 
        !           793:             * q follows along behind s pointing at the "next" field of the
        !           794: 
        !           795:             * previous list element.  To start, q points to the semalist
        !           796: 
        !           797:             * variable itself.  At all times, then, *q is the place to
        !           798: 
        !           799:             * write s->next when you want to remove an element 's' from
        !           800: 
        !           801:             * the list.
        !           802: 
        !           803:             */
        !           804: 
        !           805:            for (s = *(q = &semalist); s; s = *(q = &s->next)) {
        !           806: 
        !           807:                if (s->id == id) {
        !           808: 
        !           809:                    /* found your semaphore */
        !           810: 
        !           811:                    if (s->owner != curproc->pid) {
        !           812: 
        !           813:                        DEBUG("Psemaphore(%d,%lx): you don't own it",mode,id);
        !           814: 
        !           815:                        return EACCDN;
        !           816: 
        !           817:                    }
        !           818: 
        !           819:                    else {
        !           820: 
        !           821:                        if (mode == 3) s->owner = -1;   /* make it free, or */
        !           822: 
        !           823:                        else *q = s->next;              /* delete from list */
        !           824: 
        !           825: 
        !           826: 
        !           827:                        /* wake up anybody who's waiting for a semaphore */
        !           828: 
        !           829:                        wake(WAIT_Q,WAIT_SEMA);
        !           830: 
        !           831:                        return E_OK;
        !           832: 
        !           833:                    }
        !           834: 
        !           835:                }
        !           836: 
        !           837:            }
        !           838: 
        !           839:            /* no such semaphore */
        !           840: 
        !           841:            DEBUG("Psemaphore(%d,%lx): no such semaphore",mode,id);
        !           842: 
        !           843:            return ERANGE;
        !           844: 
        !           845:        }
        !           846: 
        !           847:        default: {                      /* invalid mode argument */
        !           848: 
        !           849:            DEBUG("Psemaphore(%d,%lx): invalid mode",mode,id);
        !           850: 
        !           851:            return EINVFN;
        !           852: 
        !           853:        }
        !           854: 
        !           855:     }
        !           856: 
        !           857: }
        !           858: 
        !           859: 
        !           860: 
        !           861: /*
        !           862: 
        !           863:  * Release all semaphores owned by the process with process id "pid".
        !           864: 
        !           865:  * The semaphores are only released, not destroyed. This function
        !           866: 
        !           867:  * is called from terminate() in dos_mem.c during process termination.
        !           868: 
        !           869:  */
        !           870: 
        !           871: 
        !           872: 
        !           873: void
        !           874: 
        !           875: free_semaphores(pid)
        !           876: 
        !           877:        int pid;
        !           878: 
        !           879: {
        !           880: 
        !           881:        SEMA *s, **q;
        !           882: 
        !           883:        int didsomething = 0;           /* did any semaphores get freed? */
        !           884: 
        !           885: 
        !           886: 
        !           887:        for (s = *(q = &semalist); s; s = *(q = &s->next)) {
        !           888: 
        !           889:                if (s->owner == pid) {
        !           890: 
        !           891:                        s->owner = -1;          /* mark the semaphore as free */
        !           892: 
        !           893:                        didsomething = 1;
        !           894: 
        !           895:                }
        !           896: 
        !           897:        }
        !           898: 
        !           899:        if (didsomething) {
        !           900: 
        !           901:        /* wake up anybody waiting for a semaphore, in case it's one of
        !           902: 
        !           903:         * the ones we just freed
        !           904: 
        !           905:         */
        !           906: 
        !           907:                wake(WAIT_Q, WAIT_SEMA);
        !           908: 
        !           909:        }
        !           910: 
        !           911: }
        !           912: 

unix.superglobalmegacorp.com

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