Annotation of coherent/d/286_KERNEL/USRSRC/io/msg.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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