M ip/ip.c => ip/ip.c +5 -0
@@ 231,6 231,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos)
int lid, len, seglen, chunk, dlen, blklen, offset, medialen;
Route *r, *sr;
IP *ip;
+ Proto *pr;
ip = f->ip;
@@ 262,6 263,10 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos)
if(r == nil){
ip->stats[OutNoRoutes]++;
netlog(f, Logip, "no interface %V\n", eh->dst);
+ if(!gating){
+ freeblist(bp);
+ error("no route");
+ }
goto free;
}
M ip/tcp.c => ip/tcp.c +34 -24
@@ 1319,27 1319,30 @@ tcphangup(Conv *s)
if(waserror())
return commonerror();
if(s->raddr != 0) {
- seg.flags = RST | ACK;
- seg.ack = tcb->rcv.nxt;
- tcb->rcv.una = 0;
- seg.seq = tcb->snd.ptr;
- seg.wnd = 0;
- seg.urg = 0;
- seg.mss = 0;
- seg.ws = 0;
- switch(s->ipversion) {
- case V4:
- tcb->protohdr.tcp4hdr.vihl = IP_VER4;
- hbp = htontcp4(&seg, nil, &tcb->protohdr.tcp4hdr, tcb);
- ipoput4(s->p->f, hbp, 0, s->ttl, s->tos);
- break;
- case V6:
- tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
- hbp = htontcp6(&seg, nil, &tcb->protohdr.tcp6hdr, tcb);
- ipoput6(s->p->f, hbp, 0, s->ttl, s->tos);
- break;
- default:
- panic("tcphangup: version %d", s->ipversion);
+ if(!waserror()){
+ seg.flags = RST | ACK;
+ seg.ack = tcb->rcv.nxt;
+ tcb->rcv.una = 0;
+ seg.seq = tcb->snd.ptr;
+ seg.wnd = 0;
+ seg.urg = 0;
+ seg.mss = 0;
+ seg.ws = 0;
+ switch(s->ipversion) {
+ case V4:
+ tcb->protohdr.tcp4hdr.vihl = IP_VER4;
+ hbp = htontcp4(&seg, nil, &tcb->protohdr.tcp4hdr, tcb);
+ ipoput4(s->p->f, hbp, 0, s->ttl, s->tos);
+ break;
+ case V6:
+ tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
+ hbp = htontcp6(&seg, nil, &tcb->protohdr.tcp6hdr, tcb);
+ ipoput6(s->p->f, hbp, 0, s->ttl, s->tos);
+ break;
+ default:
+ panic("tcphangup: version %d", s->ipversion);
+ }
+ poperror();
}
}
localclose(s, nil);
@@ 2408,6 2411,11 @@ tcpoutput(Conv *s)
tpriv = s->p->priv;
version = s->ipversion;
+ if(waserror()){
+ localclose(s, up->errstr);
+ return;
+ }
+
for(msgs = 0; msgs < 100; msgs++) {
tcb = (Tcpctl*)s->ptcl;
@@ 2415,7 2423,7 @@ tcpoutput(Conv *s)
case Listen:
case Closed:
case Finwait2:
- return;
+ goto out;
}
/* force an ack when a window has opened up */
@@ 2542,7 2550,7 @@ tcpoutput(Conv *s)
hbp = htontcp4(&seg, bp, &tcb->protohdr.tcp4hdr, tcb);
if(hbp == nil) {
freeblist(bp);
- return;
+ goto out;
}
break;
case V6:
@@ 2550,7 2558,7 @@ tcpoutput(Conv *s)
hbp = htontcp6(&seg, bp, &tcb->protohdr.tcp6hdr, tcb);
if(hbp == nil) {
freeblist(bp);
- return;
+ goto out;
}
break;
default:
@@ 2596,6 2604,8 @@ tcpoutput(Conv *s)
qlock(s);
}
}
+out:
+ poperror();
}
/*
M pc/devarch.c => pc/devarch.c +31 -36
@@ 110,9 110,9 @@ ioinit(void)
ioalloc(0x10000, 1, 0, "dummy");
/*
* Someone needs to explain why this was here...
- */
ioalloc(0x0fff, 1, 0, "dummy"); // i82557 is at 0x1000, the dummy
// entry is needed for swappable devs.
+ */
if ((excluded = getconf("ioexclude")) != nil) {
char *s;
@@ 391,8 391,7 @@ archread(Chan *c, void *a, long n, vlong offset)
break;
}
- /* allocate a buffer to avoid page faults in the loop */
- if((buf = malloc(n+1)) == nil) /* +1 for the NUL */
+ if((buf = malloc(n)) == nil)
error(Enomem);
p = buf;
n = n/Linelen;
@@ 404,7 403,7 @@ archread(Chan *c, void *a, long n, vlong offset)
continue;
if(strcmp(m->tag, "dummy") == 0)
break;
- snprint(p, Linelen+1, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
+ sprint(p, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
p += Linelen;
n--;
}
@@ 624,9 623,11 @@ cpuidprint(void)
* figure out:
* - cpu type
* - whether or not we have a TSC (cycle counter)
- * - whether or not is supports page size extensions
+ * - whether or not it supports page size extensions
+ * (if so turn it on)
+ * - whether or not it supports machine check exceptions
* (if so turn it on)
- * - whether or not is supports machine check exceptions
+ * - whether or not it supports the page global flag
* (if so turn it on)
*/
int
@@ 669,11 670,11 @@ cpuidentify(void)
guesscpuhz(t->aalcycles);
/*
- * If machine check exception or page size extensions are supported
- * enable them in CR4 and clear any other set extensions.
+ * If machine check exception, page size extensions or page global bit
+ * are supported enable them in CR4 and clear any other set extensions.
* If machine check was enabled clear out any lingering status.
*/
- if(m->cpuiddx & 0x88){
+ if(m->cpuiddx & 0x2088){
cr4 = 0;
if(m->cpuiddx & 0x08)
cr4 |= 0x10; /* page size extensions */
@@ 688,38 689,32 @@ cpuidentify(void)
rdmsr(0x01, &mct);
}
}
+
+ /*
+ * Detect whether the chip supports the global bit
+ * in page directory and page table entries. When set
+ * in a particular entry, it means ``don't bother removing
+ * this from the TLB when CR3 changes.''
+ *
+ * We flag all kernel pages with this bit. Doing so lessens the
+ * overhead of switching processes on bare hardware,
+ * even more so on VMware. See mmu.c:/^memglobal.
+ *
+ * For future reference, should we ever need to do a
+ * full TLB flush, it can be accomplished by clearing
+ * the PGE bit in CR4, writing to CR3, and then
+ * restoring the PGE bit.
+ */
+ if(m->cpuiddx & 0x2000){
+ cr4 |= 0x80; /* page global enable bit */
+ m->havepge = 1;
+ }
+
putcr4(cr4);
if(m->cpuiddx & 0x80)
rdmsr(0x01, &mct);
}
- /*
- * Detect whether the chip supports the global bit
- * in page directory and page table entries. When set
- * in a particular entry, it means ``don't bother removing
- * this from the TLB when CR3 changes.''
- *
- * We flag all kernel pages with this bit. Doing so lessens the
- * overhead of switching processes on bare hardware,
- * even more so on VMware. See mmu.c:/^memglobal.
- *
- * This feature exists on Intel Pentium Pro and later
- * processors. Presumably the AMD processors have
- * a similar notion, but I can't find it in the meager
- * documentation I've tried.
- *
- * For future reference, should we ever need to do a
- * full TLB flush, it can be accomplished by clearing
- * the PGE bit in CR4, writing to CR3, and then
- * restoring the PGE bit.
- */
- if(tab==x86intel && t->family >= 6){
- cr4 = getcr4();
- cr4 |= 0x80; /* page global enable bit */
- putcr4(cr4);
- m->havepge = 1;
- }
-
cputype = t;
return t->family;
}
M port/devproc.c => port/devproc.c +16 -0
@@ 45,6 45,8 @@ enum
CMstop,
CMwaitstop,
CMwired,
+ CMfair,
+ CMunfair,
};
#define STATSIZE (2*KNAMELEN+12+9*12)
@@ 91,6 93,8 @@ Cmdtab proccmd[] = {
CMstop, "stop", 1,
CMwaitstop, "waitstop", 1,
CMwired, "wired", 2,
+ CMfair, "fair", 1,
+ CMunfair, "unfair", 1,
};
/* Segment type from portdat.h */
@@ 118,6 122,8 @@ Segment* txt2data(Proc*, Segment*);
int procstopped(void*);
void mntscan(Mntwalk*, Proc*);
+extern int unfair;
+
static int
procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp)
{
@@ 1191,6 1197,16 @@ procctlreq(Proc *p, char *va, int n)
case CMwired:
procwired(p, atoi(cb->f[1]));
break;
+ case CMfair:
+ if(!iseve())
+ error(Eperm);
+ unfair = 0;
+ break;
+ case CMunfair:
+ if(!iseve())
+ error(Eperm);
+ unfair = 1;
+ break;
}
poperror();
M port/proc.c => port/proc.c +2 -1
@@ 9,6 9,7 @@ int nrdy;
Ref noteidalloc;
long delayedscheds; /* statistics */
+int unfair; /* unfair scheduling */
static Ref pidalloc;
@@ 228,7 229,7 @@ loop:
*/
spllo();
for(;;){
- if((++(m->fairness) & 0x3) == 0){
+ if(!unfair && (++(m->fairness) & 0x3) == 0){
/*
* once in a while, run process that's been waiting longest
* regardless of movetime