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