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