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