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

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: 
1.1.1.2 ! root      217: long ARGS_ON_STACK
1.1       root      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: 
1.1.1.2 ! root      235:     TRACE(("Pmsg(%d,%lx,%lx)",mode,mbid,ptr));
1.1       root      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:                goto got_rendezvous;
                    258: 
                    259:            }
                    260: 
                    261:        }
                    262: 
                    263:        /* nobody is writing just now */
                    264: 
                    265:        goto dosleep;
                    266: 
                    267:     }
                    268: 
                    269:     else if (mode == 1 || mode == 2) {
                    270: 
                    271:        /* write, or write/read */
                    272: 
                    273:        /* walk the whole process list looking for a reader */
                    274: 
                    275:        for (p = proclist; p; p = p->gl_next) {
                    276: 
                    277:            if (p->mb_mode == 0 && p->mb_mbid == mbid) {
                    278: 
                    279:                /* this process is reading this mbox */
                    280: 
                    281:                goto got_rendezvous;
                    282: 
                    283:            }
                    284: 
                    285:        }
                    286: 
                    287:        /* nobody is reading just now */
                    288: 
                    289:        curproc->mb_long1 = *(long *)ptr;       /* copy the message */
                    290: 
                    291:        curproc->mb_long2 = *(long *)(ptr+4);   /* into my proc struct */
                    292: 
                    293:        goto dosleep;
                    294: 
                    295:     }
                    296: 
                    297:     else return EINVFN;                        /* invalid mode */
                    298: 
                    299: 
                    300: 
                    301: /*
                    302: 
                    303:  * we get here if we actually have a rendezvous between p and curproc.
                    304: 
                    305:  */
                    306: 
                    307: 
                    308: 
                    309: got_rendezvous:
                    310: 
                    311:     if (!mode) {
                    312: 
                    313:        /* curproc is reading */
                    314: 
                    315:        *(long *)(ptr) = p->mb_long1;           /* copy the message */
                    316: 
                    317:        *(long *)(ptr+4) = p->mb_long2;         /* from his proc struct */
                    318: 
                    319:        *(short *)(ptr+8) = p->pid;             /* provide the PID */
                    320: 
                    321: 
                    322: 
                    323:        if (p->mb_mode == 2) {
                    324: 
                    325:            /*
                    326: 
                    327:             * The blocked write was in mode 2: writer becomes a reader and
                    328: 
                    329:             * stays on WAIT_Q waiting on WAIT_MB.
                    330: 
                    331:             */
                    332: 
                    333:            p->mb_mbid = 0xFFFF0000L | p->pid;
                    334: 
                    335:            p->mb_mode = 0;
                    336: 
                    337:        }
                    338: 
                    339:        else {
                    340: 
                    341:            /* The blocked write was in mode 1: writer wakes up */
                    342: 
                    343:            p->mb_writer = curproc->pid;        /* tell writer reader's pid */
                    344: 
                    345:            p->mb_mode = -1;                    /* mark rendezvous */
                    346: 
                    347:            p->wait_cond = 0;                   /* not necessary? */
                    348: 
                    349:            if (p->wait_q != READY_Q) {
                    350: 
                    351:                /* wake up the writer if it is sleeping */
                    352: 
                    353:                rm_q(p->wait_q,p);
                    354: 
                    355:                add_q(READY_Q,p);
                    356: 
                    357:            }
                    358: 
                    359:        }
                    360: 
                    361:        return 0;
                    362: 
                    363:     }
                    364: 
                    365:     else {
                    366: 
                    367:        /* curproc is writing */
                    368: 
                    369:        p->mb_writer = curproc->pid;            /* provide the PID */
                    370: 
                    371:        p->mb_long1 = *(long *)(ptr);           /* copy the message */
                    372: 
                    373:        p->mb_long2 = *(long *)(ptr+4);
                    374: 
                    375:        p->mb_mode = -1;                        /* mark rendezvous */
                    376: 
                    377:        p->wait_cond = 0;                       /* not necessary? */
                    378: 
                    379:        if (p->wait_q != READY_Q) {
                    380: 
                    381:            /* wake up the reader if it is sleeping */
                    382: 
                    383:            rm_q(p->wait_q,p);
                    384: 
                    385:            add_q(READY_Q,p);
                    386: 
                    387:        }
                    388: 
                    389:        if (mode == 2) {
                    390: 
                    391:            /* now curproc becomes a reader */
                    392: 
                    393:            mbid = 0xFFFF0000L | curproc->pid;
                    394: 
                    395:            mode = 0;
                    396: 
                    397:            goto dosleep;
                    398: 
                    399:        }
                    400: 
                    401:        else {
                    402: 
                    403:            *(short *)(ptr+8) = p->pid;         /* tell reader writer's pid */
                    404: 
                    405:            return 0;
                    406: 
                    407:        }
                    408: 
                    409:     }
                    410: 
                    411: 
                    412: 
                    413: /*
                    414: 
                    415:  * we get here when a read or write should block because there's nobody
                    416: 
                    417:  * already waiting at the other end.
                    418: 
                    419:  */
                    420: 
                    421: 
                    422: 
                    423: dosleep: 
                    424: 
                    425:        if (noblock) {
                    426: 
                    427:            return -1L;
                    428: 
                    429:        }
                    430: 
                    431:        curproc->mb_mbid = mbid;        /* and ID waited for */
                    432: 
                    433:        curproc->mb_mode = mode;        /* save mode */
                    434: 
                    435: 
                    436: 
                    437: /*
                    438: 
                    439:  * OK: now we sleep until a rendezvous has occured. The loop is because we
                    440: 
                    441:  * may be woken up to deal with signals before the rendezvous.  The thing
                    442: 
                    443:  * that says the rendezvous actually happened is that mb_mode got changed
                    444: 
                    445:  * to -1.
                    446: 
                    447:  */
                    448: 
                    449:        do {
                    450: 
                    451:                sleep(WAIT_Q, WAIT_MB);                 /* block */
                    452: 
                    453:        } while (curproc->mb_mode != -1);
                    454: 
                    455: 
                    456: 
                    457:        /*
                    458: 
                    459:         * When we wake up, we transfer the message from our proc struct
                    460: 
                    461:         * into our message pointer space if we were reading, and do
                    462: 
                    463:         * nothing if we were writing.  The write/read case is taken care
                    464: 
                    465:         * of without waking this process up at all.
                    466: 
                    467:         *
                    468: 
                    469:         * Check curproc->mode because it may not be the mode we started
                    470: 
                    471:         * with any more.
                    472: 
                    473:         */
                    474: 
                    475:        if (mode == 0) {
                    476: 
                    477:            *(long *)(ptr) = curproc->mb_long1;
                    478: 
                    479:            *(long *)(ptr+4) = curproc->mb_long2;
                    480: 
                    481:        }
                    482: 
                    483:        /* in any case, copy the 'writer' field because that's the PID */
                    484: 
                    485:        /* of the other side of the rendezvous */
                    486: 
                    487:        *(short *)(ptr+8) = curproc->mb_writer;
                    488: 
                    489:        return 0;
                    490: 
                    491: }
                    492: 
                    493: 
                    494: 
                    495: /*
                    496: 
                    497:  * more mutex: this time a semaphore.
                    498: 
                    499:  *
                    500: 
                    501:  * long Psemaphore(short mode, long id, long timeout)
                    502: 
                    503:  *
                    504: 
                    505:  *     MODE    ACTION
                    506: 
                    507:  *       0     Create and get a semaphore with the given ID.
                    508: 
                    509:  *       1     Destroy.
                    510: 
                    511:  *       2     Get (blocks until it's available or destroyed, or timeout).
                    512: 
                    513:  *       3     Release.
                    514: 
                    515:  *
                    516: 
                    517:  * RETURNS
                    518: 
                    519:  *
                    520: 
                    521:  *     CODE    MEANING
                    522: 
                    523:  *       0     OK.  Created/obtained/released/destroyed, depending on mode.
                    524: 
                    525:  *     ERROR   You asked for a semaphore that you already own.
                    526: 
                    527:  *     ERANGE  That semaphore doesn't exist (modes 1, 2, 3, 4),
                    528: 
                    529:  *             or out of slots for new semaphores (0).
                    530: 
                    531:  *     EACCDN  That semaphore exists already, so you can't create it (mode 0),
                    532: 
                    533:  *             or the semaphore is busy (returned from mode 3 if you lose),
                    534: 
                    535:  *             or you don't own it (modes 1 and 4).
                    536: 
                    537:  *
                    538: 
                    539:  * If you create a semaphore you will also own it, so you have to release
                    540: 
                    541:  * it with mode 2 before anybody else can get it.  Semaphore ID's are magic
                    542: 
                    543:  * numbers which the creator should make available to the users. You have
                    544: 
                    545:  * to own a semaphore to destroy it.  If you block waiting for a semaphore,
                    546: 
                    547:  * and then it gets destroyed, you get ERANGE.
                    548: 
                    549:  *
                    550: 
                    551:  * The timeout argument is ignored except in mode 2.  In that mode, 0 means
                    552: 
                    553:  * "return immediately" and, as a special case, -1 means "forever."
                    554: 
                    555:  * Since it is in fact an unsigned long number of milliseconds, -2 means
                    556: 
                    557:  * 49 hours, but here -1 truly means forever.
                    558: 
                    559:  *
                    560: 
                    561:  */
                    562: 
                    563: 
                    564: 
                    565: #define NSEMAPHORES 10
                    566: 
                    567: 
                    568: 
                    569: typedef struct sema {
                    570: 
                    571:     struct sema *next;
                    572: 
                    573:     long id;
                    574: 
                    575:     short owner;       /* -1 means "available" */
                    576: 
                    577: } SEMA;
                    578: 
                    579: 
                    580: 
                    581: static SEMA *semalist;
                    582: 
                    583: 
                    584: 
                    585: static void unsemame P_((PROC *));
                    586: 
                    587: 
                    588: 
                    589: static void
                    590: 
                    591: unsemame(p)
                    592: 
                    593: PROC *p;
                    594: 
                    595: {
                    596: 
                    597:     /* take process P off the WAIT_Q and put it on the READY_Q */
                    598: 
1.1.1.2 ! root      599:     TRACE(("semaphore sleep ends for pid %d",p->pid));
1.1       root      600: 
                    601:     if (p->wait_q == WAIT_Q) {
                    602: 
                    603:            rm_q(WAIT_Q,p);
                    604: 
                    605:            add_q(READY_Q,p);
                    606: 
                    607:     }
                    608: 
                    609:     p->wait_cond = 0;
                    610: 
                    611: }
                    612: 
                    613: 
                    614: 
1.1.1.2 ! root      615: long ARGS_ON_STACK
1.1       root      616: 
                    617: p_semaphore(mode,id,timeout)
                    618: 
                    619: int mode;
                    620: 
                    621: long id;
                    622: 
                    623: long timeout;
                    624: 
                    625: {
                    626: 
                    627:     SEMA *s, **q;
                    628: 
                    629:     TIMEOUT *timeout_ptr = NULL;
                    630: 
                    631: 
                    632: 
1.1.1.2 ! root      633:     TRACE(("Psemaphore(%d,%lx)",mode,id));
1.1       root      634: 
                    635: 
                    636: 
                    637:     switch (mode) {
                    638: 
                    639:        case 0: {                       /* create */
                    640: 
                    641:            for (s = semalist; s; s = s->next) {
                    642: 
                    643:                if (s->id == id) {
                    644: 
1.1.1.2 ! root      645:                    DEBUG(("Psemaphore(%d,%lx): already exists",mode,id));
1.1       root      646: 
                    647:                    return EACCDN;
                    648: 
                    649:                }
                    650: 
                    651:            }
                    652: 
                    653:            /* get a new one */
                    654: 
1.1.1.2 ! root      655:            if ((s = (SEMA *)kmalloc(sizeof(SEMA))) == 0)
        !           656: 
        !           657:                return ENSMEM;
1.1       root      658: 
                    659:            s->id = id;
                    660: 
                    661:            s->owner = curproc->pid;
                    662: 
                    663:            s->next = semalist;
                    664: 
                    665:            semalist = s;
                    666: 
                    667:            return E_OK;
                    668: 
                    669:        }
                    670: 
                    671:        case 2: {                       /* get */
                    672: 
                    673: loop:
                    674: 
                    675:            for (s = semalist; s; s = s->next) {
                    676: 
                    677:                if (s->id == id) {
                    678: 
                    679:                    /* found your semaphore */
                    680: 
                    681:                    if (s->owner == curproc->pid) {
                    682: 
1.1.1.2 ! root      683:                        DEBUG(("Psemaphore(%d,%lx): curproc already owns it!",
1.1       root      684: 
1.1.1.2 ! root      685:                                mode,id));
1.1       root      686: 
                    687:                        return ERROR;
                    688: 
                    689:                    }
                    690: 
                    691:                    if (s->owner == -1) {
                    692: 
                    693:                        /* it's free; you get it */
                    694: 
                    695:                        s->owner = curproc->pid;
                    696: 
                    697:                        if (timeout_ptr) canceltimeout(timeout_ptr);
                    698: 
                    699:                        return 0;
                    700: 
                    701:                    }
                    702: 
                    703:                    else {
                    704: 
                    705:                        /* not free */
                    706: 
                    707:                        if (timeout == 0) {
                    708: 
                    709:                            /* non-blocking mode */
                    710: 
                    711:                            return EACCDN;
                    712: 
                    713:                        }
                    714: 
                    715:                        else {
                    716: 
                    717:                            if (timeout != -1 && !timeout_ptr) {
                    718: 
                    719:                                /* schedule a timeout */
                    720: 
                    721:                                timeout_ptr = addtimeout(timeout,unsemame);
                    722: 
                    723:                            }
                    724: 
                    725:                            /* block until it's released, then try again */
                    726: 
                    727:                            sleep(WAIT_Q,WAIT_SEMA);
                    728: 
                    729:                            if (curproc->wait_cond != WAIT_SEMA) {
                    730: 
1.1.1.2 ! root      731:                                TRACE(("Psemaphore(%d,%lx) timed out",mode,id));
1.1       root      732: 
                    733:                                return EACCDN;
                    734: 
                    735:                            }
                    736: 
                    737:                            goto loop;
                    738: 
                    739:                        }
                    740: 
                    741:                    }
                    742: 
                    743:                }
                    744: 
                    745:            }
                    746: 
                    747:            /* no such semaphore (possibly deleted while we were waiting) */
                    748: 
                    749:            if (timeout_ptr) canceltimeout(timeout_ptr);
                    750: 
1.1.1.2 ! root      751:            DEBUG(("Psemaphore(%d,%lx): no such semaphore",mode,id));
1.1       root      752: 
                    753:            return ERANGE;
                    754: 
                    755:        }
                    756: 
                    757:        case 3:                         /* release */
                    758: 
                    759:        case 1: {                       /* destroy */
                    760: 
                    761:            /*
                    762: 
                    763:             * Style note: this is a handy way to chain down a linked list.
                    764: 
                    765:             * q follows along behind s pointing at the "next" field of the
                    766: 
                    767:             * previous list element.  To start, q points to the semalist
                    768: 
                    769:             * variable itself.  At all times, then, *q is the place to
                    770: 
                    771:             * write s->next when you want to remove an element 's' from
                    772: 
                    773:             * the list.
                    774: 
                    775:             */
                    776: 
                    777:            for (s = *(q = &semalist); s; s = *(q = &s->next)) {
                    778: 
                    779:                if (s->id == id) {
                    780: 
                    781:                    /* found your semaphore */
                    782: 
                    783:                    if (s->owner != curproc->pid) {
                    784: 
1.1.1.2 ! root      785:                        DEBUG(("Psemaphore(%d,%lx): you don't own it",mode,id));
1.1       root      786: 
                    787:                        return EACCDN;
                    788: 
                    789:                    }
                    790: 
                    791:                    else {
                    792: 
                    793:                        if (mode == 3) s->owner = -1;   /* make it free, or */
                    794: 
                    795:                        else *q = s->next;              /* delete from list */
                    796: 
                    797: 
                    798: 
                    799:                        /* wake up anybody who's waiting for a semaphore */
                    800: 
                    801:                        wake(WAIT_Q,WAIT_SEMA);
                    802: 
                    803:                        return E_OK;
                    804: 
                    805:                    }
                    806: 
                    807:                }
                    808: 
                    809:            }
                    810: 
                    811:            /* no such semaphore */
                    812: 
1.1.1.2 ! root      813:            DEBUG(("Psemaphore(%d,%lx): no such semaphore",mode,id));
1.1       root      814: 
                    815:            return ERANGE;
                    816: 
                    817:        }
                    818: 
                    819:        default: {                      /* invalid mode argument */
                    820: 
1.1.1.2 ! root      821:            DEBUG(("Psemaphore(%d,%lx): invalid mode",mode,id));
1.1       root      822: 
                    823:            return EINVFN;
                    824: 
                    825:        }
                    826: 
                    827:     }
                    828: 
                    829: }
                    830: 
                    831: 
                    832: 
                    833: /*
                    834: 
                    835:  * Release all semaphores owned by the process with process id "pid".
                    836: 
                    837:  * The semaphores are only released, not destroyed. This function
                    838: 
                    839:  * is called from terminate() in dos_mem.c during process termination.
                    840: 
                    841:  */
                    842: 
                    843: 
                    844: 
                    845: void
                    846: 
                    847: free_semaphores(pid)
                    848: 
                    849:        int pid;
                    850: 
                    851: {
                    852: 
1.1.1.2 ! root      853:        SEMA *s;
1.1       root      854: 
                    855:        int didsomething = 0;           /* did any semaphores get freed? */
                    856: 
                    857: 
                    858: 
1.1.1.2 ! root      859:        for (s = semalist; s; s = s->next) {
1.1       root      860: 
                    861:                if (s->owner == pid) {
                    862: 
                    863:                        s->owner = -1;          /* mark the semaphore as free */
                    864: 
                    865:                        didsomething = 1;
                    866: 
                    867:                }
                    868: 
                    869:        }
                    870: 
                    871:        if (didsomething) {
                    872: 
                    873:        /* wake up anybody waiting for a semaphore, in case it's one of
                    874: 
                    875:         * the ones we just freed
                    876: 
                    877:         */
                    878: 
                    879:                wake(WAIT_Q, WAIT_SEMA);
                    880: 
                    881:        }
                    882: 
                    883: }
                    884: 

unix.superglobalmegacorp.com

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