Annotation of coherent/d/PS2_KERNEL/io.286/msg.c, revision 1.1

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

unix.superglobalmegacorp.com

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