Annotation of coherent/b/kernel/io.386/msg386.c, revision 1.1.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.