xref: /csrg-svn/sys/kern/uipc_mu_msg.c (revision 9168)
1*9168Ssam /*	uipc_mu_msg.c	Melb 4.2	82/11/13	*/
27455Skre 
37455Skre #ifdef	MUSH
47455Skre #include "../h/param.h"
57455Skre #include "../h/dir.h"
67455Skre #include "../h/user.h"
77455Skre #include "../h/proc.h"
87455Skre 
97455Skre /*
107455Skre  * Melbourne Trivial IPC mechanism
117455Skre  *
127455Skre  *	This is intended solely to serve for the 4.1bsd MUSH implementation
137455Skre  *	until a better IPC scheme arrives from somewhere
147455Skre  *
157455Skre  *	If it happens to be useful for other purposes, OK, but users
167455Skre  *	should be prepared to change at short (no) notice.
177455Skre  *	This is purposely kept as small as possible, with the expectation
187455Skre  *	than anything done using this scheme should be able to be
197455Skre  *	done easily in any other, with possibly a little more legwork.
207455Skre  *
217455Skre  *	NB: we don't go fooling with spl's in here, as it is deliberately
227455Skre  *	not intended that interrupt level code will ever call this
237455Skre  */
247455Skre 
257455Skre mu_msg()
267455Skre {
277455Skre 	register struct proc *p, *pp;
287455Skre 	mmsgbuf mb;
297455Skre 	register struct a {
307455Skre 		msg_type	cmd;
317455Skre 		int		wait;	/* bit mask - see mu_msg.h */
327455Skre 		mmsgbuf	*	msgp;
337455Skre 	} *uap;
347455Skre 
357455Skre 	uap = (struct a *)u.u_ap;
367455Skre 	p = u.u_procp;
377455Skre 
387455Skre 	for (;;) {	/* only loop if cmd == MSG_SNDW */
397455Skre 		switch (uap->cmd) {
407455Skre 
417455Skre 		case MSG_ENAB:
427455Skre 			p->p_msgflgs |= MSGENAB;
437455Skre 			return;
447455Skre 
457455Skre 		case MSG_DISB:
467455Skre 			p->p_msgflgs &= ~MSGENAB;
477455Skre 				/*
487455Skre 				 * Q: what should be done with a pending msg
497455Skre 				 * - for now we will just leave it, proc should
507455Skre 				 * do a MSG_RECV w/o waiting after MSG_DISB
517455Skre 				 */
527455Skre 			return;
537455Skre 
547455Skre 		case MSG_RECV:
557455Skre 			while (!p->p_mb.msg_val && (uap->wait & MSG_W_RCV)) {
567455Skre 				p->p_msgflgs |= MSGOK;
577455Skre 				sleep((caddr_t) &p->p_mb, MSGPRI);
587455Skre 			}
597455Skre 			if (copyout((caddr_t)&p->p_mb, (caddr_t)uap->msgp,
607455Skre 			    sizeof(mmsgbuf)))
617455Skre 				u.u_error = EFAULT;
627455Skre 			p->p_msgflgs &= ~(MSGOK|MSGWRPLY);
637455Skre 			if (p->p_mb.msg_rply)
647455Skre 				p->p_msgflgs |= MSGRPLY;
657455Skre 			else {
667455Skre 				p->p_mb.msg_val = 0;
677455Skre 				if (p->p_msgflgs & MSGWAIT) {
687455Skre 					p->p_msgflgs &= ~MSGWAIT;
697455Skre 					wakeup((caddr_t)&p->p_mb);
707455Skre 				}
717455Skre 			}
727455Skre 			return;
737455Skre 
747455Skre 		case MSG_SEND:
757455Skre 		case MSG_SNDW:
767455Skre 		case MSG_RPLY:
777455Skre 			if (copyin((caddr_t)uap->msgp, (caddr_t)&mb,
787455Skre 			    sizeof(mmsgbuf))) {
797455Skre 				u.u_error = EFAULT;
807455Skre 				return;
817455Skre 			}
827455Skre 			if (uap->cmd == MSG_RPLY) {
837455Skre 				if (!(p->p_msgflgs & MSGRPLY) ||
847455Skre 				    mb.msg_pid != p->p_mb.msg_pid) {
857455Skre 					u.u_error = EINVAL;
867455Skre 					return;
877455Skre 				}
887455Skre 				p->p_mb.msg_val = 0;
897455Skre 				if (!mb.msg_rply && p->p_msgflgs & MSGWAIT) {
907455Skre 					p->p_msgflgs &= ~MSGWAIT;
917455Skre 					wakeup((caddr_t)&p->p_mb);
927455Skre 				}
937455Skre 			} else {
947455Skre 				if (p->p_msgflgs & MSGRPLY) {
957455Skre 					while (pp = mu_send(&p->p_mb,
96*9168Ssam 					    (int)p->p_mb.msg_pid, 0)) {
977455Skre 						pp->p_msgflgs |= MSGWAIT;
987455Skre 						sleep((caddr_t)&pp->p_mb,
997455Skre 						    MSGPRI);
1007455Skre 					}
1017455Skre 					u.u_error = 0; /* not err if exited */
1027455Skre 					p->p_mb.msg_val = 0;
1037455Skre 					if (!mb.msg_rply &&
1047455Skre 					    p->p_msgflgs & MSGWAIT) {
1057455Skre 						p->p_msgflgs &= ~MSGWAIT;
1067455Skre 						wakeup((caddr_t)&p->p_mb);
1077455Skre 					}
1087455Skre 				}
1097455Skre 			}
1107455Skre 			p->p_msgflgs &= ~MSGRPLY;
1117455Skre 			if (mb.msg_rply) {
1127455Skre 				if (p->p_mb.msg_val) {
1137455Skre 					u.u_error = ENOSPC;
1147455Skre 					return;
1157455Skre 				}
1167455Skre 				p->p_mb = mb;
1177455Skre 				p->p_mb.msg_rply = 0;
1187455Skre 				p->p_mb.msg_val = 0;
1197455Skre 				p->p_msgflgs |= MSGWRPLY;
1207455Skre 			}
1217455Skre 			mb.msg_uid = u.u_uid;
122*9168Ssam 			while ((pp = mu_send(&mb, (int)mb.msg_pid, p->p_pid)) &&
1237455Skre 			    uap->wait & MSG_W_POST) {
1247455Skre 				pp->p_msgflgs |= MSGWAIT;
1257455Skre 				sleep((caddr_t)&pp->p_mb, MSGPRI);
1267455Skre 			}
1277455Skre 			if (pp)
1287455Skre 				u.u_error = EBUSY;
1297455Skre 			if (u.u_error) {
1307455Skre 				if (mb.msg_rply)
1317455Skre 					p->p_msgflgs &= ~MSGWRPLY;
1327455Skre 				return;
1337455Skre 			}
1347455Skre 			if (uap->cmd == MSG_SNDW) {
1357455Skre 				uap->cmd = MSG_RECV;
1367455Skre 				break;
1377455Skre 			}
1387455Skre 			return;
1397455Skre 
1407455Skre 		default:
1417455Skre 			u.u_error = EINVAL;
1427455Skre 			return;
1437455Skre 		}
1447455Skre 	}
1457455Skre }
1467455Skre 
1477455Skre struct proc *
1487455Skre mu_send(mp, pid, from)
149*9168Ssam 	register mmsgbuf *mp;
150*9168Ssam 	register int pid, from;
1517455Skre {
1527455Skre 	register struct proc *p;
1537455Skre 
1547455Skre 	p = pfind(pid);
1557455Skre 
1567455Skre 	if (p == NULL || p->p_stat == SZOMB ||
1577455Skre 	    !(p->p_msgflgs & (MSGOK|MSGENAB|MSGWRPLY))) {
1587455Skre 		u.u_error = ESRCH;
1597455Skre 		return((struct proc *)0);
1607455Skre 	}
1617455Skre 
1627455Skre 	if (p->p_mb.msg_val ||
1637455Skre 	    from != 0 && p->p_msgflgs&MSGWRPLY && from != p->p_mb.msg_pid)
1647455Skre 		return(p);
1657455Skre 
1667455Skre 	p->p_mb = *mp;
1677455Skre 	p->p_mb.msg_val = 1;
1687455Skre 	p->p_mb.msg_pid = from;
1697455Skre 	if (from == 0)
1707455Skre 		p->p_mb.msg_rply = 0;
1717455Skre 	if (p->p_msgflgs & MSGOK)
1727455Skre 		wakeup((caddr_t)&p->p_mb);
1737455Skre 	else if (p->p_msgflgs & MSGENAB)
1747455Skre 		psignal(p, SIGMESG);
1757455Skre 	return((struct proc *)0);
1767455Skre }
1777455Skre 
1787455Skre msgto(pid, data)
1797455Skre int pid;
1807455Skre DATA_T data;
1817455Skre {
1827455Skre 	register struct proc *p;
1837455Skre 	mmsgbuf mb;
1847455Skre 
1857455Skre 	mb.msg_uid = 0;		/* all msgs from system are from root */
1867455Skre 	mb.msg_data = data;
1877455Skre 	mb.msg_rply = 0;
1887455Skre 	while (p = mu_send(&mb, pid, u.u_procp->p_pid)) {
1897455Skre 		p->p_msgflgs |= MSGWAIT;
1907455Skre 		sleep((caddr_t)&p->p_mb, MSGPRI);
1917455Skre 	}
1927455Skre }
1937455Skre #endif
194