Annotation of coherent/d/286_KERNEL/USRSRC/io/msg.c, revision 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.