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