This commit is contained in:
mischief 2014-02-02 07:41:56 -08:00
commit 35d19fc6fb
4 changed files with 142 additions and 156 deletions

View file

@ -1133,3 +1133,62 @@ timerset(Tval x)
if(doi8253set)
(*arch->timerset)(x);
}
/*
* put the processor in the halt state if we've no processes to run.
* an interrupt will get us going again.
*
* halting in an smp system can result in a startup latency for
* processes that become ready.
* if idle_spin is zero, we care more about saving energy
* than reducing this latency.
*
* the performance loss with idle_spin == 0 seems to be slight
* and it reduces lock contention (thus system time and real time)
* on many-core systems with large values of NPROC.
*/
void
idlehands(void)
{
extern int nrdy, idle_spin;
if(conf.nmach == 1)
halt();
else if(m->cpuidcx & Monitor)
mwait(&nrdy);
else if(idle_spin == 0)
halt();
}
int
isaconfig(char *class, int ctlrno, ISAConf *isa)
{
char cc[32], *p;
int i;
snprint(cc, sizeof cc, "%s%d", class, ctlrno);
p = getconf(cc);
if(p == nil)
return 0;
isa->type = "";
isa->nopt = tokenize(p, isa->opt, NISAOPT);
for(i = 0; i < isa->nopt; i++){
p = isa->opt[i];
if(cistrncmp(p, "type=", 5) == 0)
isa->type = p + 5;
else if(cistrncmp(p, "port=", 5) == 0)
isa->port = strtoul(p+5, &p, 0);
else if(cistrncmp(p, "irq=", 4) == 0)
isa->irq = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "dma=", 4) == 0)
isa->dma = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "mem=", 4) == 0)
isa->mem = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "size=", 5) == 0)
isa->size = strtoul(p+5, &p, 0);
else if(cistrncmp(p, "freq=", 5) == 0)
isa->freq = strtoul(p+5, &p, 0);
}
return 1;
}

View file

@ -1000,109 +1000,3 @@ exit(int ispanic)
shutdown(ispanic);
arch->reset();
}
int
isaconfig(char *class, int ctlrno, ISAConf *isa)
{
char cc[32], *p;
int i;
snprint(cc, sizeof cc, "%s%d", class, ctlrno);
p = getconf(cc);
if(p == nil)
return 0;
isa->type = "";
isa->nopt = tokenize(p, isa->opt, NISAOPT);
for(i = 0; i < isa->nopt; i++){
p = isa->opt[i];
if(cistrncmp(p, "type=", 5) == 0)
isa->type = p + 5;
else if(cistrncmp(p, "port=", 5) == 0)
isa->port = strtoul(p+5, &p, 0);
else if(cistrncmp(p, "irq=", 4) == 0)
isa->irq = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "dma=", 4) == 0)
isa->dma = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "mem=", 4) == 0)
isa->mem = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "size=", 5) == 0)
isa->size = strtoul(p+5, &p, 0);
else if(cistrncmp(p, "freq=", 5) == 0)
isa->freq = strtoul(p+5, &p, 0);
}
return 1;
}
int
cistrcmp(char *a, char *b)
{
int ac, bc;
for(;;){
ac = *a++;
bc = *b++;
if(ac >= 'A' && ac <= 'Z')
ac = 'a' + (ac - 'A');
if(bc >= 'A' && bc <= 'Z')
bc = 'a' + (bc - 'A');
ac -= bc;
if(ac)
return ac;
if(bc == 0)
break;
}
return 0;
}
int
cistrncmp(char *a, char *b, int n)
{
unsigned ac, bc;
while(n > 0){
ac = *a++;
bc = *b++;
n--;
if(ac >= 'A' && ac <= 'Z')
ac = 'a' + (ac - 'A');
if(bc >= 'A' && bc <= 'Z')
bc = 'a' + (bc - 'A');
ac -= bc;
if(ac)
return ac;
if(bc == 0)
break;
}
return 0;
}
/*
* put the processor in the halt state if we've no processes to run.
* an interrupt will get us going again.
*
* halting in an smp system can result in a startup latency for
* processes that become ready.
* if idle_spin is zero, we care more about saving energy
* than reducing this latency.
*
* the performance loss with idle_spin == 0 seems to be slight
* and it reduces lock contention (thus system time and real time)
* on many-core systems with large values of NPROC.
*/
void
idlehands(void)
{
extern int nrdy;
if(conf.nmach == 1)
halt();
else if(m->cpuidcx & Monitor)
mwait(&nrdy);
else if(idle_spin == 0)
halt();
}

View file

@ -331,10 +331,20 @@ TEXT mb586(SB), 1, $-4
CPUID
RET
/*
* Park a processor. Should never fall through a return from main to here,
* should only be called by application processors when shutting down.
*/
TEXT idle(SB), 1, $-4
_idle:
STI
HLT
JMP _idle
/*
* BIOS32.
*/
TEXT bios32call(SB), 1, $-1
TEXT bios32call(SB), 1, $-4
XORL AX, AX
INCL AX
RET
@ -526,14 +536,30 @@ TEXT setlabel(SB), 1, $-4
MOVL $0, AX /* return 0 */
RET
TEXT idle(SB), $0
_idle:
TEXT halt(SB), 1, $-4
CLI
CMPL nrdy(SB), $0
JEQ _nothingready
STI
RET
_nothingready:
STI
HLT
JMP _idle
RET
TEXT halt(SB), 1, $-4
HLT
TEXT mwait(SB), 1, $-4
MOVQ RARG, AX
MOVL (AX), CX
ORL CX, CX
JNZ _mwaitdone
XORL DX, DX
BYTE $0x0f; BYTE $0x01; BYTE $0xc8 /* MONITOR */
MOVL (AX), CX
ORL CX, CX
JNZ _mwaitdone
XORL AX, AX
BYTE $0x0f; BYTE $0x01; BYTE $0xc9 /* MWAIT */
_mwaitdone:
RET
/*

View file

@ -26,6 +26,8 @@ char *confname[MAXCONF];
char *confval[MAXCONF];
int nconf;
int delaylink;
int idle_spin;
uchar *sp; /* user stack of init proc */
extern void (*i8237alloc)(void);
@ -419,12 +421,56 @@ main()
schedinit();
}
void
exit(int)
static void
shutdown(int ispanic)
{
print("exit\n");
splhi();
for(;;);
int ms, once;
lock(&active);
if(ispanic)
active.ispanic = ispanic;
else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
active.ispanic = 0;
once = active.machs & (1<<m->machno);
/*
* setting exiting will make hzclock() on each processor call exit(0),
* which calls shutdown(0) and arch->reset(), which on mp systems is
* mpshutdown, from which there is no return: the processor is idled
* or initiates a reboot. clearing our bit in machs avoids calling
* exit(0) from hzclock() on this processor.
*/
active.machs &= ~(1<<m->machno);
active.exiting = 1;
unlock(&active);
if(once)
iprint("cpu%d: exiting\n", m->machno);
/* wait for any other processors to shutdown */
spllo();
for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
delay(TK2MS(2));
if(active.machs == 0 && consactive() == 0)
break;
}
if(active.ispanic){
if(!cpuserver)
for(;;)
halt();
if(getconf("*debug"))
delay(5*60*1000);
else
delay(10000);
}else
delay(1000);
}
void
exit(int ispanic)
{
shutdown(ispanic);
arch->reset();
}
void
@ -433,12 +479,6 @@ reboot(void*, void*, ulong)
exit(0);
}
void
idlehands(void)
{
halt();
}
/*
* SIMD Floating Point.
* Assembler support to get at the individual instructions
@ -707,36 +747,3 @@ procsave(Proc *p)
*/
mmuflushtlb();
}
int
isaconfig(char *class, int ctlrno, ISAConf *isa)
{
char cc[32], *p;
int i;
snprint(cc, sizeof cc, "%s%d", class, ctlrno);
p = getconf(cc);
if(p == nil)
return 0;
isa->type = "";
isa->nopt = tokenize(p, isa->opt, NISAOPT);
for(i = 0; i < isa->nopt; i++){
p = isa->opt[i];
if(cistrncmp(p, "type=", 5) == 0)
isa->type = p + 5;
else if(cistrncmp(p, "port=", 5) == 0)
isa->port = strtoul(p+5, &p, 0);
else if(cistrncmp(p, "irq=", 4) == 0)
isa->irq = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "dma=", 4) == 0)
isa->dma = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "mem=", 4) == 0)
isa->mem = strtoul(p+4, &p, 0);
else if(cistrncmp(p, "size=", 5) == 0)
isa->size = strtoul(p+5, &p, 0);
else if(cistrncmp(p, "freq=", 5) == 0)
isa->freq = strtoul(p+5, &p, 0);
}
return 1;
}