M ip/devip.c => ip/devip.c +19 -8
@@ 501,8 501,9 @@ closeconv(Conv *cv)
while((mp = cv->multi) != nil)
ipifcremmulti(cv, mp->ma, mp->ia);
- /* The close routine will unlock the conv */
cv->p->close(cv);
+ cv->state = Idle;
+ qunlock(cv);
}
static void
@@ 789,6 790,8 @@ connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
{
char *p;
+ if(c->state != 0)
+ error(Econinuse);
c->state = Connecting;
c->cerr[0] = '\0';
if(x->connect == nil)
@@ 796,7 799,11 @@ connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
p = x->connect(c, cb->f, cb->nf);
if(p != nil)
error(p);
+ qunlock(c);
+
sleep(&c->cr, connected, c);
+
+ qlock(c);
if(c->cerr[0] != '\0')
error(c->cerr);
}
@@ 830,6 837,8 @@ announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
{
char *p;
+ if(c->state != 0)
+ error(Econinuse);
c->state = Announcing;
c->cerr[0] = '\0';
if(x->announce == nil)
@@ 837,7 846,11 @@ announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
p = x->announce(c, cb->f, cb->nf);
if(p != nil)
error(p);
+ qunlock(c);
+
sleep(&c->cr, announced, c);
+
+ qlock(c);
if(c->cerr[0] != '\0')
error(c->cerr);
}
@@ 934,12 947,9 @@ ipwrite(Chan* ch, void *v, long n, vlong off)
c = x->conv[CONV(ch->qid)];
cb = parsecmd(a, n);
- if(canqlock(&c->car) == 0){
- free(cb);
- error("connect/announce in progress");
- }
+ qlock(c);
if(waserror()) {
- qunlock(&c->car);
+ qunlock(c);
free(cb);
nexterror();
}
@@ 983,7 993,7 @@ ipwrite(Chan* ch, void *v, long n, vlong off)
error(p);
} else
error("unknown control request");
- qunlock(&c->car);
+ qunlock(c);
free(cb);
poperror();
}
@@ 1129,7 1139,7 @@ retry:
c->inuse = 1;
strcpy(c->owner, user);
c->perm = 0660;
- c->state = 0;
+ c->state = Idle;
ipmove(c->laddr, IPnoaddr);
ipmove(c->raddr, IPnoaddr);
c->lport = 0;
@@ 1211,6 1221,7 @@ Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport)
nc->lport = lport;
nc->next = nil;
*l = nc;
+ c->state = Connected;
qunlock(c);
wakeup(&c->listenr);
M ip/esp.c => ip/esp.c +0 -2
@@ 219,8 219,6 @@ espclose(Conv *c)
free(ecb->espstate);
free(ecb->ahstate);
memset(ecb, 0, sizeof(Espcb));
-
- qunlock(c);
}
void
M ip/gre.c => ip/gre.c +0 -2
@@ 114,8 114,6 @@ greclose(Conv *c)
ipmove(c->raddr, IPnoaddr);
c->lport = 0;
c->rport = 0;
-
- qunlock(c);
}
int drop;
M ip/icmp.c => ip/icmp.c +0 -1
@@ 145,7 145,6 @@ icmpclose(Conv *c)
ipmove(c->laddr, IPnoaddr);
ipmove(c->raddr, IPnoaddr);
c->lport = 0;
- qunlock(c);
}
static void
M ip/il.c => ip/il.c +0 -1
@@ 304,7 304,6 @@ ilclose(Conv *c)
break;
}
ilfreeq(ic);
- qunlock(c);
}
void
M ip/ip.h => ip/ip.h +1 -0
@@ 48,6 48,7 @@ enum
enum
{
+ Idle= 0,
Announcing= 1,
Announced= 2,
Connecting= 3,
M ip/ipifc.c => ip/ipifc.c +4 -10
@@ 99,7 99,7 @@ ipfindmedium(char *name)
/*
* attach a device (or pkt driver) to the interface.
- * called with c->car locked
+ * called with c locked
*/
static char*
ipifcbind(Conv *c, char **argv, int argc)
@@ 136,11 136,8 @@ ipifcbind(Conv *c, char **argv, int argc)
ifc->m = m;
ifc->minmtu = ifc->m->minmtu;
ifc->maxmtu = ifc->m->maxmtu;
- if(ifc->m->unbindonclose == 0){
- qlock(ifc->conv);
+ if(ifc->m->unbindonclose == 0)
ifc->conv->inuse++;
- qunlock(ifc->conv);
- }
ifc->ifcid++;
wunlock(ifc);
@@ 151,6 148,7 @@ ipifcbind(Conv *c, char **argv, int argc)
/*
* detach a device from an interface, close the interface
+ * called with ifc->conv closed
*/
static char*
ipifcunbind(Ipifc *ifc)
@@ 166,11 164,8 @@ ipifcunbind(Ipifc *ifc)
wlock(ifc);
/* dissociate routes */
- if(ifc->m != nil && ifc->m->unbindonclose == 0){
- qlock(ifc->conv);
+ if(ifc->m != nil && ifc->m->unbindonclose == 0)
ifc->conv->inuse--;
- qunlock(ifc->conv);
- }
ifc->ifcid++;
/* disassociate device */
@@ 309,7 304,6 @@ ipifcclose(Conv *c)
m = ifc->m;
if(m != nil && m->unbindonclose)
ipifcunbind(ifc);
- qunlock(c);
}
/*
M ip/ipmux.c => ip/ipmux.c +0 -2
@@ 619,8 619,6 @@ ipmuxclose(Conv *c)
wunlock(f);
ipmuxtreefree(r->chain);
r->chain = nil;
-
- qunlock(c);
}
/*
M ip/rudp.c => ip/rudp.c +0 -1
@@ 296,7 296,6 @@ rudpclose(Conv *c)
ucb->r = 0;
qunlock(ucb);
- qunlock(c);
}
/*
M ip/tcp.c => ip/tcp.c +12 -18
@@ 402,7 402,6 @@ tcpclose(Conv *c)
tcpoutput(c);
break;
}
- qunlock(c);
}
void
@@ 412,6 411,11 @@ tcpkick(Conv *s, int len)
tcb = (Tcpctl*)s->ptcl;
+ if(waserror()){
+ qunlock(s);
+ nexterror();
+ }
+ qlock(s);
switch(tcb->state) {
case Listen:
@@ 426,22 430,17 @@ tcpkick(Conv *s, int len)
/*
* Push data
*/
- if(waserror()){
- qunlock(s);
- nexterror();
- }
- qlock(s);
tcb->sndcnt += len;
tcprcvwin(s);
tcpoutput(s);
- qunlock(s);
- poperror();
break;
default:
- qlock(s);
localclose(s, "Hangup");
- qunlock(s);
+ break;
}
+
+ qunlock(s);
+ poperror();
}
void
@@ 682,6 681,9 @@ inittcpctl(Conv *s)
tcb->mss = tcb->cwind = tcpmtu(s);
}
+/*
+ * called with s qlocked
+ */
void
tcpstart(Conv *s, int mode, ushort window)
{
@@ 703,13 705,7 @@ tcpstart(Conv *s, int mode, ushort window)
tcb = (Tcpctl*)s->ptcl;
- qlock(s);
/* Send SYN, go into SYN_SENT state */
- if(waserror()){
- qunlock(s);
- nexterror();
- }
-
inittcpctl(s);
tcb->window = window;
tcb->rcv.wnd = window;
@@ 729,8 725,6 @@ tcpstart(Conv *s, int mode, ushort window)
tcpoutput(s);
break;
}
- qunlock(s);
- poperror();
}
static char*
M ip/udp.c => ip/udp.c +5 -7
@@ 140,8 140,6 @@ udpclose(Conv *c)
ucb = (Udpcb*)c->ptcl;
ucb->headers = 0;
-
- qunlock(c);
}
void
@@ 404,22 402,22 @@ found:
}
-/* close any incoming calls waiting on this conversation */
+/*
+ * close any incoming calls waiting on this conversation
+ * called with c locked
+ */
void
udpcloseincalls(Conv *c)
{
Conv *nc;
- qlock(c);
-
for(nc = c->incall; nc; nc = c->incall){
c->incall = nc->next;
closeconv(nc);
}
-
- qunlock(c);
}
+/* called with c locked */
char*
udpctl(Conv *c, char **f, int n)
{
M port/error.h => port/error.h +1 -0
@@ 33,6 33,7 @@ extern char Eisstream[]; /* seek on a stream */
extern char Ebadexec[]; /* exec header invalid */
extern char Etimedout[]; /* connection timed out */
extern char Econrefused[]; /* connection refused */
+extern char Econinuse[]; /* connection in use */
extern char Eintr[]; /* interrupted */
extern char Enomem[]; /* kernel allocate failed */
extern char Enoswap[]; /* swap space full */