1*10002Ssam /* uipc_mu_msg.c Melb 4.3 82/12/28 */
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
mu_msg()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 }
59*10002Ssam u.u_error = copyout((caddr_t)&p->p_mb,
60*10002Ssam (caddr_t)uap->msgp, sizeof(mmsgbuf));
617455Skre p->p_msgflgs &= ~(MSGOK|MSGWRPLY);
627455Skre if (p->p_mb.msg_rply)
637455Skre p->p_msgflgs |= MSGRPLY;
647455Skre else {
657455Skre p->p_mb.msg_val = 0;
667455Skre if (p->p_msgflgs & MSGWAIT) {
677455Skre p->p_msgflgs &= ~MSGWAIT;
687455Skre wakeup((caddr_t)&p->p_mb);
697455Skre }
707455Skre }
717455Skre return;
727455Skre
737455Skre case MSG_SEND:
747455Skre case MSG_SNDW:
757455Skre case MSG_RPLY:
76*10002Ssam u.u_error = copyin((caddr_t)uap->msgp, (caddr_t)&mb,
77*10002Ssam sizeof(mmsgbuf));
78*10002Ssam if (u.u_error)
797455Skre return;
807455Skre if (uap->cmd == MSG_RPLY) {
817455Skre if (!(p->p_msgflgs & MSGRPLY) ||
827455Skre mb.msg_pid != p->p_mb.msg_pid) {
837455Skre u.u_error = EINVAL;
847455Skre return;
857455Skre }
867455Skre p->p_mb.msg_val = 0;
877455Skre if (!mb.msg_rply && p->p_msgflgs & MSGWAIT) {
887455Skre p->p_msgflgs &= ~MSGWAIT;
897455Skre wakeup((caddr_t)&p->p_mb);
907455Skre }
917455Skre } else {
927455Skre if (p->p_msgflgs & MSGRPLY) {
937455Skre while (pp = mu_send(&p->p_mb,
949168Ssam (int)p->p_mb.msg_pid, 0)) {
957455Skre pp->p_msgflgs |= MSGWAIT;
967455Skre sleep((caddr_t)&pp->p_mb,
977455Skre MSGPRI);
987455Skre }
997455Skre u.u_error = 0; /* not err if exited */
1007455Skre p->p_mb.msg_val = 0;
1017455Skre if (!mb.msg_rply &&
1027455Skre p->p_msgflgs & MSGWAIT) {
1037455Skre p->p_msgflgs &= ~MSGWAIT;
1047455Skre wakeup((caddr_t)&p->p_mb);
1057455Skre }
1067455Skre }
1077455Skre }
1087455Skre p->p_msgflgs &= ~MSGRPLY;
1097455Skre if (mb.msg_rply) {
1107455Skre if (p->p_mb.msg_val) {
1117455Skre u.u_error = ENOSPC;
1127455Skre return;
1137455Skre }
1147455Skre p->p_mb = mb;
1157455Skre p->p_mb.msg_rply = 0;
1167455Skre p->p_mb.msg_val = 0;
1177455Skre p->p_msgflgs |= MSGWRPLY;
1187455Skre }
1197455Skre mb.msg_uid = u.u_uid;
1209168Ssam while ((pp = mu_send(&mb, (int)mb.msg_pid, p->p_pid)) &&
1217455Skre uap->wait & MSG_W_POST) {
1227455Skre pp->p_msgflgs |= MSGWAIT;
1237455Skre sleep((caddr_t)&pp->p_mb, MSGPRI);
1247455Skre }
1257455Skre if (pp)
1267455Skre u.u_error = EBUSY;
1277455Skre if (u.u_error) {
1287455Skre if (mb.msg_rply)
1297455Skre p->p_msgflgs &= ~MSGWRPLY;
1307455Skre return;
1317455Skre }
1327455Skre if (uap->cmd == MSG_SNDW) {
1337455Skre uap->cmd = MSG_RECV;
1347455Skre break;
1357455Skre }
1367455Skre return;
1377455Skre
1387455Skre default:
1397455Skre u.u_error = EINVAL;
1407455Skre return;
1417455Skre }
1427455Skre }
1437455Skre }
1447455Skre
1457455Skre struct proc *
mu_send(mp,pid,from)1467455Skre mu_send(mp, pid, from)
1479168Ssam register mmsgbuf *mp;
1489168Ssam register int pid, from;
1497455Skre {
1507455Skre register struct proc *p;
1517455Skre
1527455Skre p = pfind(pid);
1537455Skre
1547455Skre if (p == NULL || p->p_stat == SZOMB ||
1557455Skre !(p->p_msgflgs & (MSGOK|MSGENAB|MSGWRPLY))) {
1567455Skre u.u_error = ESRCH;
1577455Skre return((struct proc *)0);
1587455Skre }
1597455Skre
1607455Skre if (p->p_mb.msg_val ||
1617455Skre from != 0 && p->p_msgflgs&MSGWRPLY && from != p->p_mb.msg_pid)
1627455Skre return(p);
1637455Skre
1647455Skre p->p_mb = *mp;
1657455Skre p->p_mb.msg_val = 1;
1667455Skre p->p_mb.msg_pid = from;
1677455Skre if (from == 0)
1687455Skre p->p_mb.msg_rply = 0;
1697455Skre if (p->p_msgflgs & MSGOK)
1707455Skre wakeup((caddr_t)&p->p_mb);
1717455Skre else if (p->p_msgflgs & MSGENAB)
1727455Skre psignal(p, SIGMESG);
1737455Skre return((struct proc *)0);
1747455Skre }
1757455Skre
msgto(pid,data)1767455Skre msgto(pid, data)
1777455Skre int pid;
1787455Skre DATA_T data;
1797455Skre {
1807455Skre register struct proc *p;
1817455Skre mmsgbuf mb;
1827455Skre
1837455Skre mb.msg_uid = 0; /* all msgs from system are from root */
1847455Skre mb.msg_data = data;
1857455Skre mb.msg_rply = 0;
1867455Skre while (p = mu_send(&mb, pid, u.u_procp->p_pid)) {
1877455Skre p->p_msgflgs |= MSGWAIT;
1887455Skre sleep((caddr_t)&p->p_mb, MSGPRI);
1897455Skre }
1907455Skre }
1917455Skre #endif
192