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