M ip/devip.c => ip/devip.c +14 -4
@@ 799,11 799,16 @@ connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
p = x->connect(c, cb->f, cb->nf);
if(p != nil)
error(p);
- qunlock(c);
+ qunlock(c);
+ if(waserror()){
+ qlock(c);
+ nexterror();
+ }
sleep(&c->cr, connected, c);
-
qlock(c);
+ poperror();
+
if(c->cerr[0] != '\0')
error(c->cerr);
}
@@ 846,11 851,16 @@ announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
p = x->announce(c, cb->f, cb->nf);
if(p != nil)
error(p);
- qunlock(c);
+ qunlock(c);
+ if(waserror()){
+ qlock(c);
+ nexterror();
+ }
sleep(&c->cr, announced, c);
-
qlock(c);
+ poperror();
+
if(c->cerr[0] != '\0')
error(c->cerr);
}
M ip/tcp.c => ip/tcp.c +25 -16
@@ 1649,7 1649,9 @@ raise:
}
/*
- * always enters and exits with the tcb locked
+ * always enters and exits with the s locked. We drop
+ * the lock to ipoput the packet so some care has to be
+ * taken by callers.
*/
void
tcpoutput(Conv *s)
@@ 1667,22 1669,22 @@ tcpoutput(Conv *s)
f = s->p->f;
tpriv = s->p->priv;
- tcb = (Tcpctl*)s->ptcl;
-
- switch(tcb->state) {
- case Listen:
- case Closed:
- case Finwait2:
- return;
- }
-
- /* force an ack when a window has opened up */
- if(tcb->rcv.blocked && tcb->rcv.wnd > 0){
- tcb->rcv.blocked = 0;
- tcb->flags |= FORCE;
- }
-
for(msgs = 0; msgs < 100; msgs++) {
+ tcb = (Tcpctl*)s->ptcl;
+
+ switch(tcb->state) {
+ case Listen:
+ case Closed:
+ case Finwait2:
+ return;
+ }
+
+ /* force an ack when a window has opened up */
+ if(tcb->rcv.blocked && tcb->rcv.wnd > 0){
+ tcb->rcv.blocked = 0;
+ tcb->flags |= FORCE;
+ }
+
sndcnt = tcb->sndcnt;
sent = tcb->snd.ptr - tcb->snd.una;
@@ 1850,7 1852,14 @@ tcpoutput(Conv *s)
tpriv->stats[OutSegs]++;
if(tcb->kacounter > 0)
tcpgo(tpriv, &tcb->katimer);
+ qunlock(s);
+ if(waserror()){
+ qlock(s);
+ nexterror();
+ }
ipoput(f, hbp, 0, s->ttl, s->tos);
+ qlock(s);
+ poperror();
}
}
M pc/apm.c => pc/apm.c +1 -0
@@ 162,6 162,7 @@ apmlink(void)
loadgdt();
addarchfile("apm", 0660, apmread, apmwrite);
+ doze = halt;
print("apm0: configured cbase %.8lux off %.8lux\n", ax<<4, ebx);
M pc/fns.h => pc/fns.h +3 -1
@@ 25,6 25,7 @@ int dmadone(int);
void dmaend(int);
int dmainit(int, int);
long dmasetup(int, void*, long, int);
+void (*doze)(void);
#define evenaddr(x) /* x86 doesn't care */
void fpenv(FPsave*);
void fpinit(void);
@@ 38,6 39,7 @@ ulong getcr3(void);
ulong getcr4(void);
char* getconf(char*);
int havecycintr(void);
+void halt(void); /* x86 HLT */
int i8042auxcmd(int);
void i8042auxenable(void (*)(int, int));
void i8042reset(void);
@@ 47,7 49,7 @@ uvlong i8253read(uvlong*);
void i8259init(void);
int i8259enable(Vctl*);
void idle(void);
-#define idlehands() /* nothing to do in the runproc */
+#define idlehands() if(doze==0);else doze() /* nothing to do in the runproc */
int inb(int);
void insb(int, void*, int);
ushort ins(int);
M pc/l.s => pc/l.s +8 -0
@@ 12,6 12,7 @@
#define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */
#define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */
#define WBINVD BYTE $0x0F; BYTE $0x09
+#define HLT BYTE $0xF4
/*
* Macros for calculating offsets within the page directory base
@@ 505,6 506,13 @@ TEXT setlabel(SB), $0
RET
/*
+ * Attempt at power saving. -rsc
+ */
+TEXT halt(SB), $0
+ HLT
+ RET
+
+/*
* Interrupt/exception handling.
* Each entry in the vector table calls either _strayintr or _strayintrx depending
* on whether an error code has been automatically pushed onto the stack