plan9port/src/libmux/io.c
2003-12-06 18:08:52 +00:00

136 lines
2.1 KiB
C

/* 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);
while((p = _muxnbqrecv(q)) != nil)
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);
while((p = _muxnbqrecv(q)) != nil)
free(p);
free(q);
mux->writeq = nil;
rwakeup(&mux->rpcfork);
qunlock(&mux->lk);
return;
}
void*
_muxrecv(Mux *mux)
{
void *p;
qlock(&mux->lk);
/*
if(mux->state != VtStateConnected){
werrstr("not connected");
qunlock(&mux->lk);
return nil;
}
*/
if(mux->readq){
qunlock(&mux->lk);
return _muxqrecv(mux->readq);
}
qlock(&mux->inlk);
qunlock(&mux->lk);
p = mux->recv(mux);
qunlock(&mux->inlk);
/*
if(!p)
vthangup(mux);
*/
return p;
}
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;
}