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