Annotation of coherent/b/kernel/io.386/msg.c, revision 1.1.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.