Annotation of coherent/b/kernel/io.386/msg.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * System V Compatible Messaging
        !             3:  *
        !             4:  *     This module provides System V compatible messaging operations.
        !             5:  *
        !             6:  *     Author: Allan Cornish.
        !             7:  */
        !             8: 
        !             9: #include <sys/coherent.h>
        !            10: #include <sys/sched.h>
        !            11: #include <sys/types.h>
        !            12: #include <sys/uproc.h>
        !            13: #include <errno.h>
        !            14: #include <sys/stat.h>
        !            15: #include <sys/con.h>
        !            16: #include <sys/seg.h>
        !            17: #include <sys/msg.h>
        !            18: #include <stdlib.h>
        !            19: 
        !            20: #ifndef        EIDRM
        !            21: #define        EIDRM   EDOM
        !            22: #endif
        !            23: 
        !            24: /*
        !            25:  * Extended message queue id data structure.
        !            26:  *     - extended to support System V.3 compatible polls.
        !            27:  */
        !            28: struct xmsqid_ds {
        !            29:        struct msqid_ds msq;
        !            30:        struct event    ipolls;
        !            31:        struct event    opolls;
        !            32: };
        !            33: 
        !            34: /*
        !            35:  *     Message Information
        !            36:  */
        !            37: 
        !            38: struct xmsqid_ds *msqs = 0;    /* Pointer to array of message queues */
        !            39:                                /* (first queue contains free message list) */
        !            40: 
        !            41: struct msg * msgs = 0;         /* Pointer to array of message headers */
        !            42: 
        !            43: #ifdef _I386
        !            44: char *msgsp;
        !            45: #else
        !            46: static SEG * msgsp;
        !            47: #define        msgsel FP_SEL(msgsp->s_faddr)
        !            48: #endif
        !            49: 
        !            50: /*
        !            51:  *     Global Message Parameters
        !            52:  */
        !            53: 
        !            54: unsigned NMSQID = 9;   /* allocated number of message queues */
        !            55: unsigned NMSQB  = 2048;        /* default maximum queue size in bytes */
        !            56: unsigned NMSG = 10;    /* allocated messages: (NMSG * NMSC) < 2^16 */
        !            57: unsigned NMSC = 640;   /* maximum message text size */
        !            58: 
        !            59: 
        !            60: /*
        !            61:  * Message Device Initialization.
        !            62:  *
        !            63:  *     Initialize message ids.
        !            64:  */
        !            65: 
        !            66: msginit()
        !            67: {
        !            68:        register struct xmsqid_ds *qp;
        !            69:        register struct msg *mp;
        !            70:        long wanted;
        !            71:        int i;
        !            72: 
        !            73:        if ( NMSG == 0 )
        !            74:                NMSQID = 0;
        !            75:        if ( NMSC == 0 )
        !            76:                NMSQID = 0;
        !            77:        if ( NMSQID == 0 )
        !            78:                return 0;
        !            79: 
        !            80:        if ( NMSQID > 128 )
        !            81:                NMSQID = 128;
        !            82: 
        !            83:        /*
        !            84:         * Allocate message queues and message headers.
        !            85:         */
        !            86:        wanted = (NMSQID * (long) sizeof(struct xmsqid_ds)) +
        !            87:                (NMSG * (long) sizeof(struct msg));
        !            88:        if (wanted > 16384) {
        !            89:                printf("invalid NMSQID or NMSG kernel variable\n");
        !            90:                NMSQID=0;
        !            91:                return;
        !            92:        }
        !            93: 
        !            94:        /* allocate memory for the headers, msqs points to headers */
        !            95: 
        !            96:        if ( msqs = kalloc( (unsigned) wanted) ) {
        !            97: 
        !            98:                /*
        !            99:                 * Ensure allocated space is cleared.
        !           100:                 */
        !           101: #ifndef _I386
        !           102:                memset( msqs, 0, (unsigned) wanted );
        !           103: #else
        !           104:                kclear(msqs, (size_t) wanted);
        !           105: #endif
        !           106:                /*
        !           107:                 * Message headers are contiguous to message queues.
        !           108:                 */
        !           109:                msgs = (struct msg *) (&msqs[NMSQID]); /* msgs points to
        !           110:                                                        * LAST header.
        !           111:                                                        */
        !           112:                /*
        !           113:                 * Allocate message buffers.
        !           114:                 */
        !           115:                wanted = (long) NMSG * NMSC;
        !           116: 
        !           117:                if ( wanted > 0xFFFFL ) {
        !           118:                        printf("invalid NMSG or NMSC kernel variable\n");
        !           119:                        kfree( msqs );
        !           120:                        NMSQID = 0;
        !           121:                        msqs   = 0;
        !           122:                        return;
        !           123:                }
        !           124: 
        !           125: #ifdef _I386
        !           126:                msgsp = kalloc( (size_t) wanted );
        !           127: #else
        !           128:                msgsp = salloc( (size_t) wanted, SFHIGH|SFNSWP|SFNCLR);
        !           129: #endif
        !           130:                if ( msgsp == 0 ) {
        !           131:                        printf("could not kalloc %u messages\n", NMSG);
        !           132:                        kfree( msqs );
        !           133:                        NMSQID = 0;
        !           134:                        msqs   = 0;
        !           135:                        return;
        !           136:                }
        !           137: 
        !           138:                kclear(msgsp, (size_t) wanted);
        !           139: 
        !           140:                /*
        !           141:                 * Initialize message queues.
        !           142:                 */
        !           143:                for ( qp = msqs, i = 0; i < NMSQID; i++, qp++ ) {
        !           144: 
        !           145:                        qp->msq.msg_perm.seq  = i * 256;
        !           146: 
        !           147:                        qp->ipolls.e_dnext =
        !           148:                        qp->ipolls.e_dlast = &qp->ipolls;
        !           149: 
        !           150:                        qp->opolls.e_dnext =
        !           151:                        qp->opolls.e_dlast = &qp->opolls;
        !           152:                }
        !           153: 
        !           154:                /*
        !           155:                 * Initialize message headers, place on free queue.
        !           156:                 */
        !           157:                for ( qp = msqs, mp = &msgs[NMSG]; --mp >= msgs; ) {
        !           158:                        wanted -= NMSC; /* offset for message text */
        !           159:                        mp->msg_spot  = wanted;
        !           160:                        mp->msg_next  = qp->msq.msg_first;
        !           161:                        qp->msq.msg_first = mp;
        !           162:                }
        !           163:        }
        !           164:        else {
        !           165:                printf("could not kalloc %u message ids\n", NMSQID);
        !           166:                NMSQID = 0;
        !           167:        }
        !           168: 
        !           169: }
        !           170: 
        !           171: 
        !           172: /*
        !           173:  * Msgctl - Message Control Operations.
        !           174:  */
        !           175: 
        !           176: umsgctl( qid, cmd, buf )
        !           177: 
        !           178: int qid;
        !           179: int cmd;
        !           180: struct msqid_ds *buf;
        !           181: 
        !           182: {
        !           183:        register struct xmsqid_ds *qp;
        !           184:        register struct msg *mp;
        !           185:        unsigned n;
        !           186: 
        !           187:        /*
        !           188:         * Validate queue identifier.
        !           189:         */
        !           190:        if ( (qid <= 0) || (qid/256 >= NMSQID) || (msqs == 0) ) {
        !           191:                u.u_error = EINVAL;
        !           192:                return -1;
        !           193:        }
        !           194: 
        !           195:        qp = &msqs[ qid / 256 ];
        !           196: 
        !           197:        /*
        !           198:         * Validate queue existence.
        !           199:         */
        !           200:        if ( (qp == 0) || ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0) ) {
        !           201:                u.u_error = EINVAL;
        !           202:                return -1;
        !           203:        }
        !           204: 
        !           205:        /*
        !           206:         * Validate qid for all commands except for IPC_STAT.
        !           207:         */
        !           208:        if ( (cmd != IPC_STAT) && (qp->msq.msg_perm.seq != qid) ) {
        !           209:                u.u_error = EINVAL;
        !           210:                return -1;
        !           211:        }
        !           212: 
        !           213:        switch ( cmd ) {
        !           214: 
        !           215:        case IPC_STAT:
        !           216:                /*
        !           217:                 * Validate access authority.
        !           218:                 */
        !           219:                if ( (ipcaccess(&qp->msq.msg_perm) & MSG_R) == 0 ) {
        !           220:                        u.u_error = EACCES;
        !           221:                        break;
        !           222:                }
        !           223: 
        !           224:                /*
        !           225:                 * Copy queue info to user.
        !           226:                 */
        !           227:                kucopy( qp, buf, sizeof(struct msqid_ds) );
        !           228: 
        !           229:                /*
        !           230:                 * Include input polls in receive waiting.
        !           231:                 */
        !           232:                if ( (qp->ipolls.e_dnext != NULL)
        !           233:                  && (qp->ipolls.e_dnext != &qp->ipolls) ) {
        !           234:                        putuwd( &buf->msg_perm.mode,
        !           235:                                getuwd( &buf->msg_perm.mode ) | MSG_RWAIT );
        !           236:                }
        !           237: 
        !           238:                /*
        !           239:                 * Include output polls in write waiting.
        !           240:                 */
        !           241:                if ( (qp->opolls.e_dnext != NULL)
        !           242:                  && (qp->opolls.e_dnext != &qp->opolls) ) {
        !           243:                        putuwd( &buf->msg_perm.mode,
        !           244:                                getuwd( &buf->msg_perm.mode ) | MSG_WWAIT );
        !           245:                }
        !           246: 
        !           247:                /*
        !           248:                 * Validate qid.
        !           249:                 * Doing it now lets user get info on message queue.
        !           250:                 */
        !           251:                if ( qp->msq.msg_perm.seq != qid )
        !           252:                        u.u_error = EINVAL;
        !           253:                break;
        !           254: 
        !           255:        case IPC_SET:
        !           256:                /*
        !           257:                 * Validate modify authority.
        !           258:                 */
        !           259:                if ( (u.u_uid != 0) && (u.u_uid != qp->msq.msg_perm.uid) ) {
        !           260:                        u.u_error = EPERM;
        !           261:                        break;
        !           262:                }
        !           263: 
        !           264:                /*
        !           265:                 * Get desired queue size.
        !           266:                 */
        !           267:                n = getuwd( &(buf->msg_qbytes) );
        !           268:                if (u.u_error)
        !           269:                        break;
        !           270: 
        !           271:                /*
        !           272:                 * Only super-user can increase queue size.
        !           273:                 */
        !           274:                if ( (u.u_uid != 0) && (n > qp->msq.msg_qbytes) ) {
        !           275:                        u.u_error = EPERM;
        !           276:                        break;
        !           277:                }
        !           278: 
        !           279:                /*
        !           280:                 * Set queue parameters.
        !           281:                 */
        !           282:                qp->msq.msg_perm.uid   = getuwd( &(buf->msg_perm.uid ) );
        !           283:                qp->msq.msg_perm.gid   = getuwd( &(buf->msg_perm.gid ) );
        !           284:                qp->msq.msg_perm.mode &= ~0777;
        !           285:                qp->msq.msg_perm.mode |= getuwd( &(buf->msg_perm.mode) ) & 0777;
        !           286:                qp->msq.msg_qbytes     = n;
        !           287:                break;
        !           288: 
        !           289:        case IPC_RMID:
        !           290:                /*
        !           291:                 * Validate removal authority.
        !           292:                 */
        !           293:                if ( (u.u_uid != 0) && (u.u_uid != qp->msq.msg_perm.uid) ) {
        !           294:                        u.u_error = EPERM;
        !           295:                        break;
        !           296:                }
        !           297:                /*
        !           298:                 * Free all messages on the queue being removed.
        !           299:                 */
        !           300:                while ( mp = qp->msq.msg_first ) {
        !           301:                        qp->msq.msg_first   = mp->msg_next;
        !           302:                        mp->msg_next        = msqs->msq.msg_first;
        !           303:                        msqs->msq.msg_first = mp;
        !           304:                }
        !           305: 
        !           306:                /*
        !           307:                 * Wakeup processes waiting for free message buffers.
        !           308:                 */
        !           309:                if ( msqs->msq.msg_perm.mode & MSG_RWAIT ) {
        !           310:                        msqs->msq.msg_perm.mode &= ~MSG_RWAIT;
        !           311:                        wakeup( msqs );
        !           312:                }
        !           313:                if ( msqs->ipolls.e_procp )
        !           314:                        pollwake( &msqs->ipolls );
        !           315: 
        !           316:                /*
        !           317:                 * Initialize queue parameters.
        !           318:                 */
        !           319:                qp->msq.msg_last   = 0;
        !           320:                qp->msq.msg_qnum   = 0;
        !           321:                qp->msq.msg_cbytes = 0;
        !           322:                if ( (qp->msq.msg_perm.seq & 0x00FF) == 0x00FF )
        !           323:                        qp->msq.msg_perm.seq &= 0x7F00;
        !           324:                qp->msq.msg_perm.seq++;
        !           325: 
        !           326: 
        !           327:                /*
        !           328:                 * Wakeup processes sleeping on the removed message queue.
        !           329:                 */
        !           330:                if ( qp->msq.msg_perm.mode & (MSG_RWAIT|MSG_WWAIT) )
        !           331:                        wakeup( qp );
        !           332:                if ( qp->ipolls.e_procp )
        !           333:                        pollwake( &qp->ipolls );
        !           334:                if ( qp->opolls.e_procp )
        !           335:                        pollwake( &qp->opolls );
        !           336: 
        !           337:                qp->msq.msg_perm.mode = 0;
        !           338:                break;
        !           339: 
        !           340:        default:
        !           341:                u.u_error = EINVAL;
        !           342:        }
        !           343: 
        !           344:        if ( u.u_error )
        !           345:                return -1;
        !           346: 
        !           347:        return 0;
        !           348: }
        !           349: 
        !           350: /*
        !           351:  * Msgget - Get set of messages
        !           352:  */
        !           353: 
        !           354: umsgget( mykey, msgflg )
        !           355: 
        !           356: key_t mykey;
        !           357: int msgflg;
        !           358: 
        !           359: {
        !           360:        register struct xmsqid_ds *qp;
        !           361:        register struct xmsqid_ds *freeidp = 0;
        !           362:        int rwmode;
        !           363:        
        !           364:        if ( msqs == 0 ) {
        !           365: 
        !           366:                msginit();
        !           367: 
        !           368:                if ( msqs == 0 ) {
        !           369:                        u.u_error = ENOMEM;
        !           370:                        return;
        !           371:                }
        !           372:        }
        !           373: 
        !           374:        /*
        !           375:         * Extract desired access mode from flags.
        !           376:         */
        !           377:        rwmode = msgflg & 0777;
        !           378: 
        !           379:        /*
        !           380:         * Search for desired message queue [also for first free queue].
        !           381:         */
        !           382:        for ( qp = &msqs[NMSQID]; --qp > msqs; ) {
        !           383: 
        !           384:                if ( (qp->msq.msg_perm.mode & IPC_ALLOC) == 0 ) {
        !           385: 
        !           386:                        if ((freeidp == 0) ||
        !           387:                            (freeidp->msq.msg_ctime > qp->msq.msg_ctime))
        !           388:                                freeidp = qp;
        !           389:                        continue;
        !           390:                }
        !           391: 
        !           392:                if (mykey == IPC_PRIVATE)
        !           393:                        continue;
        !           394: 
        !           395:                if ( mykey == qp->msq.msg_perm.key ) {          /* found! */
        !           396: 
        !           397:                        if ( (msgflg & IPC_CREAT) && (msgflg & IPC_EXCL) ) {
        !           398:                                u.u_error = EEXIST;
        !           399:                                return -1;
        !           400:                        }
        !           401: 
        !           402:                        if ( (qp->msq.msg_perm.mode & rwmode) != rwmode ) {
        !           403:                                u.u_error = EACCES;
        !           404:                                return -1;
        !           405:                        }
        !           406: 
        !           407:                        return qp->msq.msg_perm.seq;
        !           408:                }
        !           409:        }
        !           410: 
        !           411:        if ( ! (msgflg & IPC_CREAT) ) {
        !           412:                u.u_error = ENOENT;
        !           413:                return -1;
        !           414:        }
        !           415: 
        !           416:        if ( (qp = freeidp) == 0 ) {
        !           417:                u.u_error = ENOSPC;
        !           418:                return -1;
        !           419:        }
        !           420: 
        !           421:        qp->msq.msg_first  = 0;
        !           422:        qp->msq.msg_last   = 0;
        !           423:        qp->msq.msg_cbytes = 0;
        !           424:        qp->msq.msg_qnum   = 0;
        !           425:        qp->msq.msg_qbytes = NMSQB;
        !           426:        qp->msq.msg_lspid  = 0;
        !           427:        qp->msq.msg_lrpid  = 0;
        !           428:        qp->msq.msg_stime  = 0;
        !           429:        qp->msq.msg_rtime  = 0;
        !           430:        qp->msq.msg_ctime  = timer.t_time;
        !           431: 
        !           432:        qp->msq.msg_perm.cuid = qp->msq.msg_perm.uid = u.u_uid;
        !           433:        qp->msq.msg_perm.cgid = qp->msq.msg_perm.gid = u.u_gid;
        !           434:        qp->msq.msg_perm.mode = rwmode | IPC_ALLOC;
        !           435:        qp->msq.msg_perm.key  = mykey;
        !           436: 
        !           437:        return qp->msq.msg_perm.seq;
        !           438: }
        !           439: 
        !           440: /*
        !           441:  * Send a Message
        !           442:  */
        !           443: 
        !           444: umsgsnd( qid, bufp, msgsz, msgflg )
        !           445: int qid;
        !           446: struct msgbuf *bufp;
        !           447: int msgsz, msgflg;
        !           448: 
        !           449: {
        !           450:        register struct xmsqid_ds * qp;
        !           451:        register struct msg      * mp;
        !           452: 
        !           453:        /*
        !           454:         * Validate queue identifier.
        !           455:         */
        !           456: 
        !           457: 
        !           458:        if ((qid <= 0) || (qid/256 >= NMSQID) || (msgsz > NMSC) || (msqs==0)) {
        !           459:                u.u_error = EINVAL;
        !           460:                return -1;
        !           461:        }
        !           462: 
        !           463:        qp = &msqs[ qid / 256 ];
        !           464: 
        !           465:        /*
        !           466:         * Validate queue existence.
        !           467:         */
        !           468:        if ( (qp->msq.msg_perm.seq != qid)
        !           469:          || ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0) ) {
        !           470:                u.u_error = EINVAL;
        !           471:                return -1;
        !           472:        }
        !           473: 
        !           474:        if ((ipcaccess(&qp->msq.msg_perm) & MSG_W) == 0){ /* can't send mesg */
        !           475:                u.u_error = EACCES;
        !           476:                return -1;
        !           477:        }
        !           478: 
        !           479:        /*
        !           480:         * Wait for a free message buffer
        !           481:         */
        !           482: 
        !           483:        while ( (msqs->msq.msg_first == 0)
        !           484:             || (qp->msq.msg_qbytes <= qp->msq.msg_cbytes)) {
        !           485: 
        !           486:                if ( msgflg & IPC_NOWAIT ) {
        !           487:                        u.u_error = EAGAIN;
        !           488:                        return -1;
        !           489:                }
        !           490: 
        !           491:                if (qp->msq.msg_qbytes <= qp->msq.msg_cbytes) {
        !           492:                        qp->msq.msg_perm.mode |= MSG_WWAIT;
        !           493:                        sleep( qp, CVTTOUT, IVTTOUT, SVTTOUT );
        !           494:                }
        !           495:                else {
        !           496:                        msqs->msq.msg_perm.mode |= MSG_RWAIT;
        !           497:                        sleep( msqs, CVTTOUT, IVTTOUT, SVTTOUT );
        !           498:                }
        !           499: 
        !           500:                /*
        !           501:                 * Abort if a signal was received
        !           502:                 */
        !           503:                if (SELF->p_ssig && nondsig() ) {
        !           504:                        u.u_error = EINTR;
        !           505:                        return -1;
        !           506:                }
        !           507: 
        !           508:                /*
        !           509:                 * Abort if the message queue was removed.
        !           510:                 */
        !           511:                if ( qid != qp->msq.msg_perm.seq ) {
        !           512:                        u.u_error = EIDRM;
        !           513:                        return -1;
        !           514:                }
        !           515:        }
        !           516: 
        !           517:        /*
        !           518:         * Use first message on free message queue
        !           519:         */
        !           520:        mp = msqs->msq.msg_first;
        !           521:        mp->msg_ts = msgsz;
        !           522: 
        !           523:        /*
        !           524:         * Transfer the message type and text.
        !           525:         */
        !           526: 
        !           527:        ukcopy( &(bufp->mtype), &(mp->msg_type), sizeof(mp->msg_type) );
        !           528: #ifdef _I386
        !           529:        if ( ukcopy( &bufp->mtext[0],(msgsp + mp->msg_spot), msgsz ) != msgsz )
        !           530: #else
        !           531:        if ( ufcopy( &bufp->mtext[0],mp->msg_spot, msgsel,  msgsz ) != msgsz )
        !           532: #endif
        !           533:                        u.u_error = EFAULT;
        !           534: 
        !           535:        /*
        !           536:         * Abort if address fault occured during transfer.
        !           537:         */
        !           538:        if ( u.u_error )
        !           539:                return -1;
        !           540: 
        !           541:        /*
        !           542:         * Move the message to the desired queue.
        !           543:         */
        !           544: 
        !           545: 
        !           546:        msqs->msq.msg_first = mp->msg_next;
        !           547:        mp->msg_next = 0;
        !           548: 
        !           549:        if ( qp->msq.msg_last )
        !           550:                qp->msq.msg_last->msg_next = mp;
        !           551:        else
        !           552:                qp->msq.msg_first = mp;
        !           553:        qp->msq.msg_last = mp;
        !           554: 
        !           555:        /*
        !           556:         * Update queue statistics.
        !           557:         */
        !           558: 
        !           559:        qp->msq.msg_cbytes += msgsz;
        !           560:        qp->msq.msg_qnum++;
        !           561:        qp->msq.msg_lspid = SELF->p_pid;
        !           562:        qp->msq.msg_stime = timer.t_time;
        !           563: 
        !           564:        /*
        !           565:         * Wake processes waiting to receive.
        !           566:         */
        !           567: 
        !           568: 
        !           569:        if ( qp->msq.msg_perm.mode & MSG_RWAIT ) {
        !           570:                qp->msq.msg_perm.mode &= ~MSG_RWAIT;
        !           571:                wakeup( qp );
        !           572:        }
        !           573:        if ( qp->ipolls.e_procp )
        !           574:                pollwake( &qp->ipolls );
        !           575: 
        !           576:        return 0;
        !           577: }
        !           578: 
        !           579: /*
        !           580:  * Receive A Message
        !           581:  */
        !           582: 
        !           583: umsgrcv( qid, bufp, msgsz, msgtyp, msgflg )
        !           584: 
        !           585: int qid;
        !           586: struct msgbuf *bufp;
        !           587: int msgsz;
        !           588: long msgtyp;
        !           589: int msgflg;
        !           590: 
        !           591: {
        !           592:        register struct xmsqid_ds *qp;
        !           593:        register struct msg *mp;
        !           594:        register struct msg *prev;
        !           595: 
        !           596: 
        !           597:        /*
        !           598:         * Validate queue identifier.
        !           599:         */
        !           600: 
        !           601:        if ( (qid <= 0) || (qid/256 >= NMSQID) || (msqs == 0) ) {
        !           602:                u.u_error = EINVAL;
        !           603:                return -1;
        !           604:        }
        !           605: 
        !           606:        qp = &msqs[ qid / 256 ];
        !           607: 
        !           608:        /*
        !           609:         * Validate queue existence.
        !           610:         */
        !           611:        if ( (qp->msq.msg_perm.seq != qid)
        !           612:          || ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0) ) {
        !           613:                u.u_error = EINVAL;
        !           614:                return -1;
        !           615:        }
        !           616: 
        !           617:        /*
        !           618:         * Permission denied
        !           619:         */
        !           620:        if ( (ipcaccess(&qp->msq.msg_perm) & MSG_R) == 0 ) {
        !           621:                u.u_error = EACCES;
        !           622:                return -1;
        !           623:        }
        !           624: 
        !           625:        /*
        !           626:         * Wait for message
        !           627:         */
        !           628:        for (;;) {
        !           629: 
        !           630:                mp   = qp->msq.msg_first;
        !           631:                prev = 0;
        !           632: 
        !           633:                /*
        !           634:                 * Find mesg of type <= abs(msgtyp)
        !           635:                 */
        !           636: 
        !           637:                if ( msgtyp < 0 ) {
        !           638: 
        !           639:                        struct msg *xp, *xprev;
        !           640:                        
        !           641:                        xp     = 0;
        !           642:                        xprev  = 0;
        !           643:                        msgtyp = -msgtyp;
        !           644: 
        !           645:                        for ( ; mp != 0 ; prev = mp, mp = mp->msg_next ) {
        !           646: 
        !           647:                                if (mp->msg_type > msgtyp)
        !           648:                                        continue;
        !           649: 
        !           650:                                if ((xp==0) || (mp->msg_type < xp->msg_type)) {
        !           651:                                        xp    = mp;
        !           652:                                        xprev = prev;
        !           653:                                }
        !           654:                        }
        !           655:                        mp     = xp;
        !           656:                        prev   = xprev;
        !           657:                        msgtyp = -msgtyp;
        !           658:                }
        !           659: 
        !           660:                /*
        !           661:                 * Find message of type == msgtyp
        !           662:                 */
        !           663:                else if ( msgtyp > 0 ) {
        !           664: 
        !           665:                        while ( (mp != 0) && (mp->msg_type != msgtyp) ) {
        !           666:                                prev = mp;
        !           667:                                mp = mp->msg_next;
        !           668:                        }
        !           669:                }
        !           670: 
        !           671:                /*
        !           672:                 * Else take first message
        !           673:                 */
        !           674: 
        !           675:                if ( mp )
        !           676:                        break;
        !           677: 
        !           678:                /*
        !           679:                 * Can't wait to receive mesg
        !           680:                 */
        !           681:                if ( msgflg & IPC_NOWAIT ) {
        !           682:                        u.u_error = EAGAIN;
        !           683:                        return -1;
        !           684:                }
        !           685: 
        !           686:                qp->msq.msg_perm.mode |= MSG_RWAIT;
        !           687:                sleep( qp, CVTTOUT, IVTTOUT, SVTTOUT );
        !           688: 
        !           689:                /*
        !           690:                 * Signal received
        !           691:                 */
        !           692:                if ( SELF->p_ssig && nondsig() ) {
        !           693:                        u.u_error = EINTR;
        !           694:                        return -1;
        !           695:                }
        !           696: 
        !           697:                /*
        !           698:                 * Not same q anymore
        !           699:                 */
        !           700:                if ( qid != qp->msq.msg_perm.seq ) {
        !           701:                        u.u_error = EIDRM;
        !           702:                        return -1;
        !           703:                }
        !           704:        }
        !           705: 
        !           706:        /*
        !           707:         * Ensure entire message can be transferred, or MSG_NOERROR asserted.
        !           708:         */
        !           709: 
        !           710:        if ( (msgsz < mp->msg_ts) && ((msgflg & MSG_NOERROR) == 0) ) {
        !           711:                u.u_error = E2BIG;
        !           712:                return -1;
        !           713:        }
        !           714: 
        !           715:        /*
        !           716:         * Transfer message data
        !           717:         */
        !           718:        if ( msgsz > mp->msg_ts )
        !           719:                msgsz = mp->msg_ts;
        !           720: 
        !           721:        kucopy( &(mp->msg_type), &(bufp->mtype), sizeof(mp->msg_type) );
        !           722: #ifdef _I386
        !           723:        if (kucopy( (msgsp + mp->msg_spot), &(bufp->mtext[0]), msgsz ) != msgsz)
        !           724: #else
        !           725:        if (fucopy( mp->msg_spot, msgsel, &(bufp->mtext[0]), msgsz ) != msgsz)
        !           726: #endif
        !           727:                u.u_error = EFAULT;
        !           728: 
        !           729:        /*
        !           730:         * Abort if address fault occurred during transfer.
        !           731:         */
        !           732:        if ( u.u_error )
        !           733:                return -1;
        !           734: 
        !           735:        /*
        !           736:         * Remove message from queue
        !           737:         */
        !           738:        if ( prev )
        !           739:                prev->msg_next = mp->msg_next;
        !           740:        else
        !           741:                qp->msq.msg_first = mp->msg_next;
        !           742: 
        !           743:        if ( qp->msq.msg_last == mp )
        !           744:                qp->msq.msg_last = prev;
        !           745: 
        !           746: 
        !           747:        /*
        !           748:         * Update queue statistics
        !           749:         */
        !           750:        qp->msq.msg_cbytes -= mp->msg_ts;
        !           751:        qp->msq.msg_qnum--;
        !           752:        qp->msq.msg_lrpid = SELF->p_pid;
        !           753:        qp->msq.msg_rtime = timer.t_time;
        !           754: 
        !           755:        /*
        !           756:         * Wakeup processes waiting to send.
        !           757:         */
        !           758: 
        !           759:        if (qp->msq.msg_perm.mode & MSG_WWAIT) {
        !           760:                qp->msq.msg_perm.mode &= ~MSG_WWAIT;
        !           761:                wakeup( qp );
        !           762:        }
        !           763:        if ( qp->opolls.e_procp )
        !           764:                pollwake( &qp->opolls );
        !           765: 
        !           766: 
        !           767:        /*
        !           768:         * Place message buffer on free message queue
        !           769:         */
        !           770:        qp = msqs;
        !           771:        mp->msg_next = qp->msq.msg_first;
        !           772:        qp->msq.msg_first = mp;
        !           773: 
        !           774:        /*
        !           775:         * Wakeup processes waiting for empty message buffer
        !           776:         */
        !           777:        if ( qp->msq.msg_perm.mode & MSG_RWAIT ) {
        !           778:                qp->msq.msg_perm.mode &= ~MSG_RWAIT;
        !           779:                wakeup( qp );
        !           780:        }
        !           781:        if ( msqs->ipolls.e_procp )
        !           782:                pollwake( &msqs->ipolls );
        !           783: 
        !           784: 
        !           785:        return msgsz;
        !           786: }
        !           787: 
        !           788: /*
        !           789:  * Msgpoll - Message Queue Polling.
        !           790:  */
        !           791: msgpoll( qid, ev, msec )
        !           792: int qid;
        !           793: int ev;
        !           794: int msec;
        !           795: {
        !           796:        register struct xmsqid_ds * qp;
        !           797: 
        !           798:        /*
        !           799:         * Validate queue identifier.
        !           800:         */
        !           801:        if ( (qid <= 0) || (qid/256 >= NMSQID) || (msqs == 0) )
        !           802:                return POLLNVAL;
        !           803: 
        !           804:        qp = &msqs[ qid / 256 ];
        !           805: 
        !           806:        /*
        !           807:         * Validate queue existence.
        !           808:         */
        !           809:        if ( ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0)
        !           810:          || (qp->msq.msg_perm.seq != qid) )
        !           811:                return POLLHUP;
        !           812: 
        !           813:        /*
        !           814:         * Priority polls not supported.
        !           815:         */
        !           816:        ev &= ~POLLPRI;
        !           817: 
        !           818:        /*
        !           819:         * Input poll.
        !           820:         */
        !           821:        if ( ev & POLLIN ) {
        !           822: 
        !           823:                /*
        !           824:                 * No messages on queue.
        !           825:                 */
        !           826:                if ( qp->msq.msg_qnum == 0 ) {
        !           827:                        /*
        !           828:                         * Enable input monitor.
        !           829:                         */
        !           830:                        if ( msec != 0 )
        !           831:                                pollopen( &qp->ipolls );
        !           832:                        ev &= ~POLLIN;
        !           833:                }
        !           834: 
        !           835:                /*
        !           836:                 * Prevent output monitor.
        !           837:                 */
        !           838:                else
        !           839:                        msec = 0;
        !           840:        }
        !           841: 
        !           842:        /*
        !           843:         * Output poll.
        !           844:         */
        !           845:        if ( ev & POLLOUT ) {
        !           846: 
        !           847:                /*
        !           848:                 * Queue full.
        !           849:                 */
        !           850:                if ( qp->msq.msg_cbytes >= qp->msq.msg_qbytes ) {
        !           851:                        if ( msec != 0 )
        !           852:                                pollopen( &qp->opolls );
        !           853:                        ev &= ~POLLOUT;
        !           854:                }
        !           855: 
        !           856:                /*
        !           857:                 * No free message buffers.
        !           858:                 */
        !           859:                else if ( msqs->msq.msg_first == NULL ) {
        !           860:                        if ( msec != 0 )
        !           861:                                pollopen( &msqs->ipolls );
        !           862:                        ev &= ~POLLOUT;
        !           863:                }
        !           864:        }
        !           865: 
        !           866:        return ev;
        !           867: }

unix.superglobalmegacorp.com

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