xref: /csrg-svn/sys/kern/uipc_mu_msg.c (revision 7455)
1*7455Skre /*	uipc_mu_msg.c	Melb 4.1	82/07/16	*/
2*7455Skre 
3*7455Skre #ifdef	MUSH
4*7455Skre #include "../h/param.h"
5*7455Skre #include "../h/dir.h"
6*7455Skre #include "../h/user.h"
7*7455Skre #include "../h/proc.h"
8*7455Skre 
9*7455Skre /*
10*7455Skre  * Melbourne Trivial IPC mechanism
11*7455Skre  *
12*7455Skre  *	This is intended solely to serve for the 4.1bsd MUSH implementation
13*7455Skre  *	until a better IPC scheme arrives from somewhere
14*7455Skre  *
15*7455Skre  *	If it happens to be useful for other purposes, OK, but users
16*7455Skre  *	should be prepared to change at short (no) notice.
17*7455Skre  *	This is purposely kept as small as possible, with the expectation
18*7455Skre  *	than anything done using this scheme should be able to be
19*7455Skre  *	done easily in any other, with possibly a little more legwork.
20*7455Skre  *
21*7455Skre  *	NB: we don't go fooling with spl's in here, as it is deliberately
22*7455Skre  *	not intended that interrupt level code will ever call this
23*7455Skre  */
24*7455Skre 
25*7455Skre mu_msg()
26*7455Skre {
27*7455Skre 	register struct proc *p, *pp;
28*7455Skre 	mmsgbuf mb;
29*7455Skre 	register struct a {
30*7455Skre 		msg_type	cmd;
31*7455Skre 		int		wait;	/* bit mask - see mu_msg.h */
32*7455Skre 		mmsgbuf	*	msgp;
33*7455Skre 	} *uap;
34*7455Skre 
35*7455Skre 	uap = (struct a *)u.u_ap;
36*7455Skre 	p = u.u_procp;
37*7455Skre 
38*7455Skre 	for (;;) {	/* only loop if cmd == MSG_SNDW */
39*7455Skre 		switch (uap->cmd) {
40*7455Skre 
41*7455Skre 		case MSG_ENAB:
42*7455Skre 			p->p_msgflgs |= MSGENAB;
43*7455Skre 			return;
44*7455Skre 
45*7455Skre 		case MSG_DISB:
46*7455Skre 			p->p_msgflgs &= ~MSGENAB;
47*7455Skre 				/*
48*7455Skre 				 * Q: what should be done with a pending msg
49*7455Skre 				 * - for now we will just leave it, proc should
50*7455Skre 				 * do a MSG_RECV w/o waiting after MSG_DISB
51*7455Skre 				 */
52*7455Skre 			return;
53*7455Skre 
54*7455Skre 		case MSG_RECV:
55*7455Skre 			while (!p->p_mb.msg_val && (uap->wait & MSG_W_RCV)) {
56*7455Skre 				p->p_msgflgs |= MSGOK;
57*7455Skre 				sleep((caddr_t) &p->p_mb, MSGPRI);
58*7455Skre 			}
59*7455Skre 			if (copyout((caddr_t)&p->p_mb, (caddr_t)uap->msgp,
60*7455Skre 			    sizeof(mmsgbuf)))
61*7455Skre 				u.u_error = EFAULT;
62*7455Skre 			p->p_msgflgs &= ~(MSGOK|MSGWRPLY);
63*7455Skre 			if (p->p_mb.msg_rply)
64*7455Skre 				p->p_msgflgs |= MSGRPLY;
65*7455Skre 			else {
66*7455Skre 				p->p_mb.msg_val = 0;
67*7455Skre 				if (p->p_msgflgs & MSGWAIT) {
68*7455Skre 					p->p_msgflgs &= ~MSGWAIT;
69*7455Skre 					wakeup((caddr_t)&p->p_mb);
70*7455Skre 				}
71*7455Skre 			}
72*7455Skre 			return;
73*7455Skre 
74*7455Skre 		case MSG_SEND:
75*7455Skre 		case MSG_SNDW:
76*7455Skre 		case MSG_RPLY:
77*7455Skre 			if (copyin((caddr_t)uap->msgp, (caddr_t)&mb,
78*7455Skre 			    sizeof(mmsgbuf))) {
79*7455Skre 				u.u_error = EFAULT;
80*7455Skre 				return;
81*7455Skre 			}
82*7455Skre 			if (uap->cmd == MSG_RPLY) {
83*7455Skre 				if (!(p->p_msgflgs & MSGRPLY) ||
84*7455Skre 				    mb.msg_pid != p->p_mb.msg_pid) {
85*7455Skre 					u.u_error = EINVAL;
86*7455Skre 					return;
87*7455Skre 				}
88*7455Skre 				p->p_mb.msg_val = 0;
89*7455Skre 				if (!mb.msg_rply && p->p_msgflgs & MSGWAIT) {
90*7455Skre 					p->p_msgflgs &= ~MSGWAIT;
91*7455Skre 					wakeup((caddr_t)&p->p_mb);
92*7455Skre 				}
93*7455Skre 			} else {
94*7455Skre 				if (p->p_msgflgs & MSGRPLY) {
95*7455Skre 					while (pp = mu_send(&p->p_mb,
96*7455Skre 					    p->p_mb.msg_pid, 0)) {
97*7455Skre 						pp->p_msgflgs |= MSGWAIT;
98*7455Skre 						sleep((caddr_t)&pp->p_mb,
99*7455Skre 						    MSGPRI);
100*7455Skre 					}
101*7455Skre 					u.u_error = 0; /* not err if exited */
102*7455Skre 					p->p_mb.msg_val = 0;
103*7455Skre 					if (!mb.msg_rply &&
104*7455Skre 					    p->p_msgflgs & MSGWAIT) {
105*7455Skre 						p->p_msgflgs &= ~MSGWAIT;
106*7455Skre 						wakeup((caddr_t)&p->p_mb);
107*7455Skre 					}
108*7455Skre 				}
109*7455Skre 			}
110*7455Skre 			p->p_msgflgs &= ~MSGRPLY;
111*7455Skre 			if (mb.msg_rply) {
112*7455Skre 				if (p->p_mb.msg_val) {
113*7455Skre 					u.u_error = ENOSPC;
114*7455Skre 					return;
115*7455Skre 				}
116*7455Skre 				p->p_mb = mb;
117*7455Skre 				p->p_mb.msg_rply = 0;
118*7455Skre 				p->p_mb.msg_val = 0;
119*7455Skre 				p->p_msgflgs |= MSGWRPLY;
120*7455Skre 			}
121*7455Skre 			mb.msg_uid = u.u_uid;
122*7455Skre 			while ((pp = mu_send(&mb, mb.msg_pid, p->p_pid)) &&
123*7455Skre 			    uap->wait & MSG_W_POST) {
124*7455Skre 				pp->p_msgflgs |= MSGWAIT;
125*7455Skre 				sleep((caddr_t)&pp->p_mb, MSGPRI);
126*7455Skre 			}
127*7455Skre 			if (pp)
128*7455Skre 				u.u_error = EBUSY;
129*7455Skre 			if (u.u_error) {
130*7455Skre 				if (mb.msg_rply)
131*7455Skre 					p->p_msgflgs &= ~MSGWRPLY;
132*7455Skre 				return;
133*7455Skre 			}
134*7455Skre 			if (uap->cmd == MSG_SNDW) {
135*7455Skre 				uap->cmd = MSG_RECV;
136*7455Skre 				break;
137*7455Skre 			}
138*7455Skre 			return;
139*7455Skre 
140*7455Skre 		default:
141*7455Skre 			u.u_error = EINVAL;
142*7455Skre 			return;
143*7455Skre 		}
144*7455Skre 	}
145*7455Skre }
146*7455Skre 
147*7455Skre struct proc *
148*7455Skre mu_send(mp, pid, from)
149*7455Skre register mmsgbuf *mp;
150*7455Skre register int pid;
151*7455Skre register int from;
152*7455Skre {
153*7455Skre 	register struct proc *p;
154*7455Skre 
155*7455Skre 	p = pfind(pid);
156*7455Skre 
157*7455Skre 	if (p == NULL || p->p_stat == SZOMB ||
158*7455Skre 	    !(p->p_msgflgs & (MSGOK|MSGENAB|MSGWRPLY))) {
159*7455Skre 		u.u_error = ESRCH;
160*7455Skre 		return((struct proc *)0);
161*7455Skre 	}
162*7455Skre 
163*7455Skre 	if (p->p_mb.msg_val ||
164*7455Skre 	    from != 0 && p->p_msgflgs&MSGWRPLY && from != p->p_mb.msg_pid)
165*7455Skre 		return(p);
166*7455Skre 
167*7455Skre 	p->p_mb = *mp;
168*7455Skre 	p->p_mb.msg_val = 1;
169*7455Skre 	p->p_mb.msg_pid = from;
170*7455Skre 	if (from == 0)
171*7455Skre 		p->p_mb.msg_rply = 0;
172*7455Skre 	if (p->p_msgflgs & MSGOK)
173*7455Skre 		wakeup((caddr_t)&p->p_mb);
174*7455Skre 	else if (p->p_msgflgs & MSGENAB)
175*7455Skre 		psignal(p, SIGMESG);
176*7455Skre 	return((struct proc *)0);
177*7455Skre }
178*7455Skre 
179*7455Skre msgto(pid, data)
180*7455Skre int pid;
181*7455Skre DATA_T data;
182*7455Skre {
183*7455Skre 	register struct proc *p;
184*7455Skre 	mmsgbuf mb;
185*7455Skre 
186*7455Skre 	mb.msg_uid = 0;		/* all msgs from system are from root */
187*7455Skre 	mb.msg_data = data;
188*7455Skre 	mb.msg_rply = 0;
189*7455Skre 	while (p = mu_send(&mb, pid, u.u_procp->p_pid)) {
190*7455Skre 		p->p_msgflgs |= MSGWAIT;
191*7455Skre 		sleep((caddr_t)&p->p_mb, MSGPRI);
192*7455Skre 	}
193*7455Skre }
194*7455Skre #endif
195