2003-12-06 18:08:52 +00:00
|
|
|
/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */
|
|
|
|
/* See COPYRIGHT */
|
|
|
|
|
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
|
|
|
#include <mux.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If you fork off two procs running muxrecvproc and muxsendproc,
|
|
|
|
* then muxrecv/muxsend (and thus muxrpc) will never block except on
|
|
|
|
* rendevouses, which is nice when it's running in one thread of many.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
_muxrecvproc(void *v)
|
|
|
|
{
|
|
|
|
void *p;
|
|
|
|
Mux *mux;
|
|
|
|
Muxqueue *q;
|
|
|
|
|
|
|
|
mux = v;
|
|
|
|
q = _muxqalloc();
|
|
|
|
|
|
|
|
qlock(&mux->lk);
|
|
|
|
mux->readq = q;
|
|
|
|
qlock(&mux->inlk);
|
|
|
|
rwakeup(&mux->rpcfork);
|
|
|
|
qunlock(&mux->lk);
|
|
|
|
|
|
|
|
while((p = mux->recv(mux)) != nil)
|
|
|
|
if(_muxqsend(q, p) < 0){
|
|
|
|
free(p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
qunlock(&mux->inlk);
|
|
|
|
qlock(&mux->lk);
|
|
|
|
_muxqhangup(q);
|
2006-11-04 18:46:00 +00:00
|
|
|
while(_muxnbqrecv(q, &p))
|
2003-12-06 18:08:52 +00:00
|
|
|
free(p);
|
|
|
|
free(q);
|
|
|
|
mux->readq = nil;
|
|
|
|
rwakeup(&mux->rpcfork);
|
|
|
|
qunlock(&mux->lk);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_muxsendproc(void *v)
|
|
|
|
{
|
|
|
|
Muxqueue *q;
|
|
|
|
void *p;
|
|
|
|
Mux *mux;
|
|
|
|
|
|
|
|
mux = v;
|
|
|
|
q = _muxqalloc();
|
|
|
|
|
|
|
|
qlock(&mux->lk);
|
|
|
|
mux->writeq = q;
|
|
|
|
qlock(&mux->outlk);
|
|
|
|
rwakeup(&mux->rpcfork);
|
|
|
|
qunlock(&mux->lk);
|
|
|
|
|
|
|
|
while((p = _muxqrecv(q)) != nil)
|
|
|
|
if(mux->send(mux, p) < 0)
|
|
|
|
break;
|
|
|
|
qunlock(&mux->outlk);
|
|
|
|
qlock(&mux->lk);
|
|
|
|
_muxqhangup(q);
|
2006-11-04 18:46:00 +00:00
|
|
|
while(_muxnbqrecv(q, &p))
|
2003-12-06 18:08:52 +00:00
|
|
|
free(p);
|
|
|
|
free(q);
|
|
|
|
mux->writeq = nil;
|
|
|
|
rwakeup(&mux->rpcfork);
|
|
|
|
qunlock(&mux->lk);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-11-04 18:46:00 +00:00
|
|
|
int
|
|
|
|
_muxrecv(Mux *mux, int canblock, void **vp)
|
2003-12-06 18:08:52 +00:00
|
|
|
{
|
|
|
|
void *p;
|
2006-11-04 18:46:00 +00:00
|
|
|
int ret;
|
2003-12-06 18:08:52 +00:00
|
|
|
|
|
|
|
qlock(&mux->lk);
|
|
|
|
if(mux->readq){
|
|
|
|
qunlock(&mux->lk);
|
2006-11-04 18:46:00 +00:00
|
|
|
if(canblock){
|
|
|
|
*vp = _muxqrecv(mux->readq);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return _muxnbqrecv(mux->readq, vp);
|
2003-12-06 18:08:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
qlock(&mux->inlk);
|
|
|
|
qunlock(&mux->lk);
|
2006-11-04 18:46:00 +00:00
|
|
|
if(canblock){
|
2006-06-25 21:04:52 +00:00
|
|
|
p = mux->recv(mux);
|
2006-11-04 18:46:00 +00:00
|
|
|
ret = 1;
|
|
|
|
}else{
|
2006-06-25 21:04:52 +00:00
|
|
|
if(mux->nbrecv)
|
2006-11-04 18:46:00 +00:00
|
|
|
ret = mux->nbrecv(mux, &p);
|
|
|
|
else{
|
|
|
|
/* send eof, not "no packet ready" */
|
2006-06-25 21:04:52 +00:00
|
|
|
p = nil;
|
2006-11-04 18:46:00 +00:00
|
|
|
ret = 1;
|
|
|
|
}
|
2006-06-25 21:04:52 +00:00
|
|
|
}
|
2003-12-06 18:08:52 +00:00
|
|
|
qunlock(&mux->inlk);
|
2006-11-04 18:46:00 +00:00
|
|
|
*vp = p;
|
|
|
|
return ret;
|
2003-12-06 18:08:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
_muxsend(Mux *mux, void *p)
|
|
|
|
{
|
|
|
|
qlock(&mux->lk);
|
|
|
|
/*
|
|
|
|
if(mux->state != VtStateConnected){
|
|
|
|
packetfree(p);
|
|
|
|
werrstr("not connected");
|
|
|
|
qunlock(&mux->lk);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
if(mux->writeq){
|
|
|
|
qunlock(&mux->lk);
|
|
|
|
if(_muxqsend(mux->writeq, p) < 0){
|
|
|
|
free(p);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
qlock(&mux->outlk);
|
|
|
|
qunlock(&mux->lk);
|
|
|
|
if(mux->send(mux, p) < 0){
|
|
|
|
qunlock(&mux->outlk);
|
|
|
|
/* vthangup(mux); */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
qunlock(&mux->outlk);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|