Annotation of coherent/b/kernel/io.386/msg386.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * System V Compatible Messaging
        !             3:  *
        !             4:  * This module provides System V compatible messaging operations.
        !             5:  */
        !             6: #include <sys/coherent.h>
        !             7: #include <sys/sched.h>
        !             8: #include <sys/types.h>
        !             9: #include <sys/uproc.h>
        !            10: #include <errno.h>
        !            11: #include <sys/stat.h>
        !            12: #include <sys/con.h>
        !            13: #include <sys/seg.h>
        !            14: #include <sys/msg.h>
        !            15: 
        !            16: /*
        !            17:  * Global Message Parameters. We want them to be patchable.
        !            18:  */
        !            19: unsigned NMSQID = 50;  /* maximum number of message queues */
        !            20: unsigned NMSQB  = 4096;        /* default maximum queue size in bytes */
        !            21: unsigned NMSG = 40;    /* maximum number of messages per queue */
        !            22: unsigned NMSC = 2048;  /* message text size */
        !            23: 
        !            24: #ifdef TRACER
        !            25: int    dballoc = 0;    /* For debug only */
        !            26: int    dbfree = 0;
        !            27: #endif
        !            28: 
        !            29: /* Message Information */
        !            30: struct msqid_ds *msqs = NULL;  /* Array of message queues */
        !            31: GATE           *msg_gate;      /* Message gates */
        !            32: char           **msg_map;      /* Memory map */
        !            33: 
        !            34: /* 
        !            35:  * Msgctl - Message Control Operations.
        !            36:  */
        !            37: umsgctl(qid, cmd, buf)
        !            38: int qid;
        !            39: int cmd;
        !            40: struct msqid_ds *buf;
        !            41: {
        !            42:        register struct msqid_ds        *qp;    /* message queues */
        !            43:        register struct msg             *mp;    /* single message queue */
        !            44:        unsigned short                  n;      /* temporary variable */
        !            45: 
        !            46:        /* Validate qid */
        !            47:        if (qid < 0)  {
        !            48:                u.u_error = EINVAL;
        !            49:                return -1;
        !            50:        }
        !            51:        qp = &msqs[qid % NMSQID];
        !            52: 
        !            53:        /* Validate queue existence.*/
        !            54:        if (qp->msg_perm.seq != qid || (qp->msg_perm.mode & IPC_ALLOC) == 0) {
        !            55:                u.u_error = EINVAL;
        !            56:                return -1;
        !            57:        }
        !            58: 
        !            59:        switch (cmd) {
        !            60:        case IPC_STAT:
        !            61:                /* Validate access authority. */
        !            62:                if ((ipcaccess(&qp->msg_perm) & MSG_R) == 0) {
        !            63:                        u.u_error = EACCES;
        !            64:                        break;
        !            65:                }
        !            66: 
        !            67:                 /* Copy queue info to user buffer */
        !            68:                kucopy(qp, buf, sizeof(struct msqid_ds));
        !            69:                break;
        !            70:        case IPC_SET:
        !            71:                 /* Validate modify authority. */
        !            72:                if ((u.u_uid != 0) && (u.u_uid != qp->msg_perm.uid)) {
        !            73:                        u.u_error = EPERM;
        !            74:                        break;
        !            75:                }
        !            76: 
        !            77:                /*
        !            78:                 * Get desired queue size.
        !            79:                 */
        !            80:                n = getusd(&(buf->msg_qbytes));
        !            81:                if (u.u_error)
        !            82:                        break;
        !            83: 
        !            84:                /*
        !            85:                 * Only super-user can increase queue size.
        !            86:                 */
        !            87:                if ((u.u_uid != 0) && (n > qp->msg_qbytes)) {
        !            88:                        u.u_error = EPERM;
        !            89:                        break;
        !            90:                }
        !            91: 
        !            92:                /*
        !            93:                 * Set queue parameters.
        !            94:                 */
        !            95:                qp->msg_perm.uid = getusd(&(buf->msg_perm.uid));
        !            96:                qp->msg_perm.gid = getusd(&(buf->msg_perm.gid));
        !            97:                qp->msg_perm.mode &= ~0777;
        !            98:                qp->msg_perm.mode |= getusd(&(buf->msg_perm.mode)) & 0777;
        !            99:                /* We may want to change the max size of a single message too.
        !           100:                 * It is not obvious how to do it. There is no
        !           101:                 * description in SVID. So it is possible that at some point
        !           102:                 * the size of the single message happens to be greater than
        !           103:                 * the size of message queue ;-(
        !           104:                 */
        !           105:                qp->msg_qbytes = NMSQB = n;
        !           106:                break;
        !           107: 
        !           108:        case IPC_RMID:
        !           109:                 /* Validate removal authority. */
        !           110:                if ((u.u_uid != 0) && (u.u_uid != qp->msg_perm.uid)) {
        !           111:                        u.u_error = EPERM;
        !           112:                        break;
        !           113:                }
        !           114:                /* Free all messages on the queue being removed. */
        !           115:                while (mp = qp->msg_first) {
        !           116:                        qp->msg_first = mp->msg_next;
        !           117:                        T_MSGQ(0x01, dballoc -= sizeof(struct msg));
        !           118:                        msgfree(mp);
        !           119:                }
        !           120:                T_MSGQ(0x01, printf("F%d", dballoc));
        !           121: 
        !           122:                /* Reset queue parameters. */
        !           123:                qp->msg_last = NULL;
        !           124:                qp->msg_qnum = 0;
        !           125:                qp->msg_cbytes = 0;
        !           126:                qp->msg_perm.mode = 0;
        !           127:                /* Set last change time */
        !           128:                qp->msg_ctime  = timer.t_time; 
        !           129:                /* We have to pick up a new unique sequence number.
        !           130:                 * There is a "wrap around bug". But, it is BCS.
        !           131:                 */
        !           132:                qp->msg_perm.seq += (unsigned short) 50;
        !           133:                break;
        !           134:        default:
        !           135:                u.u_error = EINVAL;
        !           136:        }
        !           137: 
        !           138:        if (u.u_error)
        !           139:                return -1;
        !           140: 
        !           141:        return 0;
        !           142: }
        !           143: 
        !           144: /*
        !           145:  * Msgget - Get set of messages
        !           146:  */
        !           147: umsgget(mykey, msgflg)
        !           148: key_t mykey;
        !           149: int msgflg;
        !           150: {
        !           151:        register struct msqid_ds *qp;           
        !           152:        register struct msqid_ds *freeidp = NULL;       
        !           153:        int rwmode;
        !           154:        
        !           155:        /* Init message queues on the first msgget */
        !           156:        if (msqs == NULL)
        !           157:                if (msginit()) {
        !           158:                        u.u_error = ENOSPC;
        !           159:                        return -1;
        !           160:                }
        !           161:        /* Extract desired access mode from flags. */
        !           162:        rwmode = msgflg & 0777; /* 0666 ??? */
        !           163:        T_MSGQ(0x02, printf("U%o", rwmode));
        !           164:        /* Search for desired message queue [also for first free queue]. */
        !           165:        for (qp = msqs; qp < msqs + NMSQID; qp++) {
        !           166:                /* Look for an older free queue */
        !           167:                if (!(qp->msg_perm.mode & IPC_ALLOC)) {
        !           168:                        if (freeidp == NULL 
        !           169:                                        || freeidp->msg_ctime > qp->msg_ctime)
        !           170:                                freeidp = qp;
        !           171:                        continue;
        !           172:                }
        !           173:                if (mykey == IPC_PRIVATE) {     /* creat a new queue */
        !           174:                        if (msgflg & IPC_EXCL)  /* unique new queue */
        !           175:                                if (mykey == qp->msg_perm.key) {
        !           176:                                        u.u_error = EEXIST;/* We cannot creat */
        !           177:                                        return -1;         /* exclusive queue */
        !           178:                                }
        !           179:                        continue;
        !           180:                }
        !           181:                if (qp->msg_perm.key != mykey)  
        !           182:                        continue;
        !           183:                if (mykey == qp->msg_perm.key) {        /* found! */
        !           184:                        if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) {
        !           185:                                u.u_error = EEXIST;     /* We cannot creat */
        !           186:                                return -1;              /* exclusive queue */
        !           187:                        }
        !           188:                        /* PERMISSIONS */
        !           189:                        /* For super-user or if mode is 0 */
        !           190:                        if (u.u_uid == 0 || !rwmode) 
        !           191:                                return qp->msg_perm.seq;
        !           192:                        /* For owner or creator */
        !           193:                        T_MSGQ(0x02, printf("Q%o", qp->msg_perm.mode));
        !           194:                        if (u.u_uid == qp->msg_perm.uid 
        !           195:                                                || u.u_uid == qp->msg_perm.cuid)
        !           196:                                if (
        !           197:                                  ((rwmode & 0600)<=(qp->msg_perm.mode & 0600))
        !           198:                                  &&((rwmode & 060)<=(qp->msg_perm.mode & 060))
        !           199:                                  &&((rwmode & 06)<=(qp->msg_perm.mode & 06)))
        !           200:                                        return qp->msg_perm.seq;
        !           201:                                else {
        !           202:                                        u.u_error = EACCES;
        !           203:                                        return -1;
        !           204:                                }
        !           205:                        /* For group */         
        !           206:                        if (u.u_gid == qp->msg_perm.gid 
        !           207:                                                || u.u_gid == qp->msg_perm.cgid)
        !           208:                                if (((rwmode & 0660)<=(qp->msg_perm.mode & 060))
        !           209:                                   &&((rwmode & 06)<=(qp->msg_perm.mode & 06)))
        !           210:                                        return qp->msg_perm.seq;
        !           211:                                else {
        !           212:                                        u.u_error = EACCES;
        !           213:                                        return -1;
        !           214:                                }
        !           215:                        /* For the rest of the world */
        !           216:                        if ((rwmode & 0666) <= (qp->msg_perm.mode & 06))
        !           217:                                return qp->msg_perm.seq;
        !           218:                        else {
        !           219:                                u.u_error = EACCES;
        !           220:                                return -1;
        !           221:                        }
        !           222:                }
        !           223:        }
        !           224: 
        !           225:        /* Creat a new queue */
        !           226:        if (!(msgflg & IPC_CREAT)) {
        !           227:                u.u_error = ENOENT;
        !           228:                return -1;
        !           229:        }
        !           230:        if ((qp = freeidp) == NULL) {
        !           231:                u.u_error = ENOSPC;
        !           232:                return -1;
        !           233:        }
        !           234:        /* Set new queue */
        !           235:        qp->msg_ctime  = timer.t_time; 
        !           236:        qp->msg_perm.cuid = qp->msg_perm.uid = u.u_uid;
        !           237:        qp->msg_perm.cgid = qp->msg_perm.gid = u.u_gid;
        !           238:        qp->msg_perm.mode = rwmode | IPC_ALLOC;
        !           239:        qp->msg_qnum = qp->msg_lspid = qp->msg_lrpid = qp->msg_stime 
        !           240:                = qp->msg_rtime = 0;
        !           241:        qp->msg_perm.key  = mykey;
        !           242: 
        !           243:        return qp->msg_perm.seq;
        !           244: }
        !           245: 
        !           246: /*
        !           247:  * Allocate space for the message queues and gates.
        !           248:  * Initialize message queue headers
        !           249:  * Return -1 on error.
        !           250:  */
        !           251: msginit()
        !           252: {
        !           253:        struct msqid_ds *qp;
        !           254:        
        !           255:        T_MSGQ(0x01, printf("A%d",dballoc += sizeof(struct msqid_ds) * NMSQID));
        !           256: 
        !           257:        /* Allocate space for message headers */
        !           258:        if ((msqs = 
        !           259:          (struct msqid_ds *) kalloc(sizeof(struct msqid_ds) * NMSQID)) == NULL)
        !           260:                return -1;
        !           261: 
        !           262:        T_MSGQ(0x01, printf("A%d", dballoc += sizeof(GATE) * NMSQID));
        !           263: 
        !           264:        /* Allocate space for message gates */
        !           265:        if ((msg_gate = (GATE *) kalloc(sizeof(GATE) * NMSQID)) == NULL) {
        !           266:                kfree(msqs);
        !           267:                msqs = NULL;
        !           268:                return -1;
        !           269:        }
        !           270: 
        !           271:        T_MSGQ(0x01, printf("A%d", dballoc += sizeof(char *) * NMSQID * NMSG));
        !           272: 
        !           273:        /* Allocate space for the message map */
        !           274:        if ((msg_map = kalloc(sizeof(char *) * NMSQID * NMSG)) == NULL) {
        !           275:                kfree(msqs);
        !           276:                msqs = NULL;
        !           277:                kfree(msg_gate);
        !           278:                return -1;
        !           279:        }
        !           280:        /* Clear gate and map areas */
        !           281:        kclear(msg_gate, sizeof(GATE) * NMSQID);
        !           282:        kclear(msg_map, sizeof(char *) * NMSQID * NMSG);
        !           283:        /* Set initial queue values */
        !           284:        for (qp = msqs; qp < msqs + NMSQID; qp++) {
        !           285:                qp->msg_first  = NULL;  /* First and last pointers to   */
        !           286:                qp->msg_last   = NULL;  /* message queue                */
        !           287:                qp->msg_cbytes = 0;     /* Number of bytes in queue     */
        !           288:                qp->msg_qnum   = 0;     /* Number of messages in queue  */
        !           289:                qp->msg_qbytes = NMSQB; /* Max size of a queue          */
        !           290:                qp->msg_lspid  = 0;     /* Pid of last msgsnd           */
        !           291:                qp->msg_lrpid  = 0;     /* Pid of last msgrcv           */
        !           292:                qp->msg_stime  = 0;     /* Last msgsnd time             */
        !           293:                qp->msg_rtime  = 0;     /* Last msgrcv time             */
        !           294:                qp->msg_ctime  = timer.t_time; /* Last change time      */
        !           295:                qp->msg_perm.seq = qp - msqs;
        !           296:                qp->msg_perm.mode = 0;
        !           297:        }
        !           298:        return 0;
        !           299: }
        !           300: 
        !           301: /* 
        !           302:  * Remove the message. Clear message text and header. Reset values in 
        !           303:  * message map.
        !           304:  */
        !           305: msgfree(mp)
        !           306: struct msg     *mp;    /* Message header to be remove */
        !           307: {
        !           308: 
        !           309:        kfree(msg_map[mp->msg_spot]);
        !           310:        msg_map[mp->msg_spot] = NULL;
        !           311:        kfree(mp);
        !           312:        T_MSGQ(0x01, printf("F%d", dballoc-=(mp->msg_ts + sizeof(struct msg))));
        !           313: }
        !           314: 
        !           315: /*
        !           316:  * Send a Message
        !           317:  */
        !           318: umsgsnd(qid, bufp, msgsz, msgflg)
        !           319: int    qid;            /* queue id */
        !           320: struct         msgbuf *bufp;   /* message buffer */
        !           321: int    msgsz,          /* message size */
        !           322:        msgflg;         /* flags */
        !           323: {
        !           324:        register struct msqid_ds        *qp;    /* message queue */
        !           325:        register struct msg             *mp,    /* message struct */ 
        !           326:                                        *tmp;
        !           327:        int                             q_num;  /* number of a queue */
        !           328:        int                             i_spot; /* # of empty entry in map */
        !           329: 
        !           330:        /* Validate queue identifier. */
        !           331:        for (qp = msqs; qp < msqs + NMSQID; qp++) 
        !           332:                if (qp->msg_perm.seq == qid)    /* found */
        !           333:                        break;
        !           334: 
        !           335:        q_num = qp - msqs;              
        !           336:        /* qid is not a valid qid identifier */
        !           337:        if (q_num >= NMSQID) {
        !           338:                u.u_error = EINVAL;
        !           339:                return -1;
        !           340:        }
        !           341: 
        !           342:        if (!(ipcaccess(&qp->msg_perm) & MSG_W)) { /* can't send mesg */
        !           343:                u.u_error = EACCES;
        !           344:                return -1;
        !           345:        }
        !           346: 
        !           347:        /* Check if message has a valid message type and size.
        !           348:         * The comparisson with NMSQB was done because user could
        !           349:         * reduce this value.
        !           350:         */
        !           351:        if (bufp->mtype < 1 || msgsz < 0 || msgsz > NMSC || msgsz > NMSQB) {
        !           352:                u.u_error = EACCES;
        !           353:                return -1;
        !           354:        }
        !           355:        
        !           356:        /* Now we have a valid message. Check if we can send it. */
        !           357:        lock(msg_gate[q_num]);  /* Lock it to avoid race condition */
        !           358:        while (qp->msg_qnum >= NMSG || 
        !           359:                        qp->msg_qbytes < (qp->msg_cbytes + msgsz)) {
        !           360:                if (msgflg & IPC_NOWAIT) {
        !           361:                        u.u_error = EAGAIN;
        !           362:                        unlock(msg_gate[q_num]);
        !           363:                        return -1;
        !           364:                }
        !           365:                /* We have to wait here */
        !           366:                qp->msg_perm.mode |= MSG_WWAIT;
        !           367:                unlock(msg_gate[q_num]);
        !           368:                x_sleep(qp, pritty, slpriSigCatch, "umsgsnd");
        !           369: 
        !           370:                /* Abort if a signal was received */
        !           371:                if (SELF->p_ssig && nondsig()) {
        !           372:                        u.u_error = EINTR;
        !           373:                        return -1;
        !           374:                }
        !           375: 
        !           376:                /* Abort if the message queue was removed. */
        !           377:                if (qid != qp->msg_perm.seq) {
        !           378:                        u.u_error = EINVAL;
        !           379:                        return -1;
        !           380:                }
        !           381:                lock(msg_gate[q_num]);
        !           382:        }
        !           383: 
        !           384:        /* Find empty entry in message map */
        !           385:        for (i_spot = 0; i_spot < NMSQID * NMSG; i_spot++)
        !           386:                if (msg_map[i_spot] == NULL)
        !           387:                        break;
        !           388:        /* It cannot happen when we do not have empty entry in map,
        !           389:         * but let check it.
        !           390:         */
        !           391:        if (i_spot >= NMSQID * NMSG) {
        !           392:                u.u_error = ENOSPC;
        !           393:                return -1;
        !           394:        }
        !           395: 
        !           396:        T_MSGQ(0x01, printf("A%d", dballoc += sizeof(struct msg)));
        !           397: 
        !           398:        /* Get space for the message header */
        !           399:        if ((mp = kalloc(sizeof(struct msg))) == NULL) {
        !           400:                unlock(msg_gate[q_num]);
        !           401:                u.u_error = ENOSPC;
        !           402:                return -1;
        !           403:        }
        !           404: 
        !           405:        T_MSGQ(0x01, printf("A%d", dballoc += msgsz));
        !           406: 
        !           407:        /* Alloc space for the message text */
        !           408:        if ((msg_map[i_spot] = kalloc(msgsz)) == NULL) {
        !           409:                kfree(mp);
        !           410:                unlock(msg_gate[q_num]);
        !           411:                u.u_error = ENOSPC;
        !           412:                return -1;
        !           413:        }
        !           414: 
        !           415:        mp->msg_next = NULL;
        !           416:        mp->msg_ts = msgsz;
        !           417:        /* The map address is a number of msg_map array element */
        !           418:        mp->msg_spot = i_spot;
        !           419: 
        !           420:        /* Transfer the message type and text.*/
        !           421:        if (ukcopy(&(bufp->mtype), &(mp->msg_type), sizeof(mp->msg_type)) !=
        !           422:                                                sizeof(mp->msg_type))
        !           423:                u.u_error = EFAULT;
        !           424:        if (ukcopy(&bufp->mtext[0], msg_map[i_spot], msgsz) != msgsz)
        !           425:                u.u_error = EFAULT;
        !           426:        if (u.u_error) {
        !           427:                msgfree(mp);
        !           428:                unlock(msg_gate[q_num]);
        !           429:                return -1;
        !           430:        }
        !           431: 
        !           432:        /* Move the message to the desired queue. */
        !           433:        if (qp->msg_first == NULL) /* This is the first message per queue */
        !           434:                qp->msg_first = qp->msg_last = mp;
        !           435:        else {  /* There are messages */
        !           436:                /* Find last message in gueue */
        !           437:                for (tmp = qp->msg_first; ; tmp = tmp->msg_next)
        !           438:                        if (tmp->msg_next == NULL)
        !           439:                                break;
        !           440:                qp->msg_last = tmp->msg_next = mp;
        !           441:        }
        !           442:        mp->msg_next = NULL;
        !           443: 
        !           444:        /* Update queue statistics. */
        !           445:        qp->msg_cbytes += msgsz;
        !           446:        qp->msg_qnum++;
        !           447:        qp->msg_lspid = SELF->p_pid;
        !           448:        qp->msg_stime = timer.t_time;
        !           449: 
        !           450:        /* Unlock queue and wake processes waiting to receive. */
        !           451:        unlock(msg_gate[q_num]);
        !           452:        if (qp->msg_perm.mode & MSG_RWAIT) {
        !           453:                qp->msg_perm.mode &= ~MSG_RWAIT;
        !           454:                wakeup(qp);
        !           455:        }
        !           456:        return 0;
        !           457: }
        !           458: 
        !           459: /*
        !           460:  * Receive a Message
        !           461:  */
        !           462: umsgrcv(qid, bufp, msgsz, msgtyp, msgflg)
        !           463: int            qid;    /* Message queue id     */
        !           464: struct msgbuf  *bufp;  /* Message buffer       */
        !           465: int            msgsz;  /* Message text size    */
        !           466: long           msgtyp; /* Message type         */
        !           467: int            msgflg; /* Message flag         */
        !           468: {
        !           469:        register struct msqid_ds        *qp;    /* queue headers        */
        !           470:        register struct msg             *mp,    /* message headers      */
        !           471:                                        *prev;
        !           472:        int                             q_num;  /* queue number         */
        !           473:        int                             i_spot;
        !           474: 
        !           475:        /* Validate queue identifier. */
        !           476:        if (qid < 0 || msqs == NULL) {
        !           477:                u.u_error = EINVAL;
        !           478:                return -1;
        !           479:        }
        !           480:        q_num = qid % NMSQID;
        !           481:        qp = &msqs[q_num];
        !           482: 
        !           483:        /* Validate queue existence.*/
        !           484:        if (qp->msg_perm.seq != qid || (qp->msg_perm.mode & IPC_ALLOC) == 0) {
        !           485:                u.u_error = EINVAL;
        !           486:                return -1;
        !           487:        }
        !           488: 
        !           489:        /* Permission denied */
        !           490:        if ((ipcaccess(&qp->msg_perm) & MSG_R) == 0) {
        !           491:                u.u_error = EACCES;
        !           492:                return -1;
        !           493:        }
        !           494: 
        !           495:        /* Wait for message */
        !           496:        lock(msg_gate[q_num]);
        !           497:        for (;;) {
        !           498:                prev = NULL;
        !           499:                mp = qp->msg_first;
        !           500:                /* Find mesg of type <= abs(msgtyp) */
        !           501:                if (msgtyp < 0) {
        !           502:                        struct msg *qmin;       /* Message with lowest mtype */
        !           503:                        struct msg *xprev;      /* Previous message */
        !           504:                        
        !           505:                        qmin = NULL;
        !           506:                        xprev = prev;
        !           507:                        msgtyp = -msgtyp;
        !           508: 
        !           509:                        for (; mp != NULL; prev = mp, mp = mp->msg_next) {
        !           510:                                if (mp->msg_type > msgtyp)
        !           511:                                        continue;
        !           512:                                if (qmin == NULL 
        !           513:                                           || mp->msg_type < qmin->msg_type) {
        !           514:                                        xprev = prev;
        !           515:                                        qmin = mp;
        !           516:                                }
        !           517:                        }
        !           518:                        prev = xprev;
        !           519:                        mp  = qmin;
        !           520:                        msgtyp = -msgtyp;
        !           521:                } else if (msgtyp > 0) { /* Find message of type == msgtyp */
        !           522:                        while (mp != NULL && mp->msg_type != msgtyp) {
        !           523:                                prev = mp;
        !           524:                                mp = mp->msg_next;
        !           525:                        }
        !           526:                } else  /* Else take first message */
        !           527:                        mp = qp->msg_first;
        !           528: 
        !           529:                if (mp != NULL) /* Found */
        !           530:                        break;
        !           531:        
        !           532:                /* Can't wait to receive mesg */
        !           533:                if (msgflg & IPC_NOWAIT) {
        !           534:                        u.u_error = EAGAIN;
        !           535:                        unlock(msg_gate[q_num]);
        !           536:                        return -1;
        !           537:                }
        !           538: 
        !           539:                /* We can go sleep now */
        !           540:                qp->msg_perm.mode |= MSG_RWAIT;
        !           541:                unlock(msg_gate[q_num]);
        !           542:                x_sleep(qp, pritty, slpriSigCatch, "umsgrcv");
        !           543: 
        !           544:                /* Signal received */
        !           545:                if (SELF->p_ssig && nondsig()) {
        !           546:                        u.u_error = EINTR;
        !           547:                        return -1;
        !           548:                }
        !           549: 
        !           550:                /* Not same q anymore */
        !           551:                if (qid != qp->msg_perm.seq) {
        !           552:                        u.u_error = EINVAL;
        !           553:                        return -1;
        !           554:                }
        !           555:                lock(msg_gate[q_num]);
        !           556:        }
        !           557: 
        !           558:        /* Ensure entire message can be transferred, or MSG_NOERROR asserted.*/
        !           559:        if (msgsz < mp->msg_ts && (msgflg & MSG_NOERROR) == 0) {
        !           560:                unlock(msg_gate[q_num]);
        !           561:                u.u_error = E2BIG;
        !           562:                return -1;
        !           563:        }
        !           564: 
        !           565:        /* Transfer message data */
        !           566:        if (msgsz > mp->msg_ts)
        !           567:                msgsz = mp->msg_ts;
        !           568: 
        !           569:        kucopy(&(mp->msg_type), &(bufp->mtype), sizeof(mp->msg_type));
        !           570: 
        !           571:        i_spot = mp->msg_spot;
        !           572:        if (kucopy(msg_map[i_spot], bufp->mtext, msgsz) != msgsz)
        !           573:                u.u_error = EFAULT;
        !           574: 
        !           575:        /* Abort if address fault occurred during transfer. */
        !           576:        if (u.u_error) {
        !           577:                unlock(msg_gate[q_num]);
        !           578:                return -1;
        !           579:        }
        !           580:        /* Remove message from queue */
        !           581:        if (prev != NULL)
        !           582:                prev->msg_next = mp->msg_next;
        !           583:        else
        !           584:                qp->msg_first = mp->msg_next;
        !           585: 
        !           586:        if (qp->msg_last == mp)
        !           587:                qp->msg_last = prev;
        !           588: 
        !           589: 
        !           590:        /* Update queue statistics */
        !           591:        qp->msg_cbytes -= mp->msg_ts;
        !           592:        qp->msg_qnum--;
        !           593:        qp->msg_lrpid = SELF->p_pid;
        !           594:        qp->msg_rtime = timer.t_time;
        !           595: 
        !           596:        /* free message */
        !           597:        msgfree(mp);
        !           598: 
        !           599:        unlock(msg_gate[q_num]);
        !           600:        /* Wakeup processes waiting to send. */
        !           601:        if (qp->msg_perm.mode & MSG_WWAIT) {
        !           602:                qp->msg_perm.mode &= ~MSG_WWAIT;
        !           603:                wakeup(qp);
        !           604:        }
        !           605:        return msgsz;
        !           606: }
        !           607: 

unix.superglobalmegacorp.com

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