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