ref: 35d19fc6fbd7f33a36497516ac7b0bc7d516fcc0
parent: d082e3a5ae2a9ceafd5db6f7108af0ba194b8d52
parent: 6a55790197d8eed5b7e020a7b964ae260d0d205b
author: mischief <mischief@offblast.org>
date: Sun Feb 2 02:41:56 EST 2014
merge
--- a/sys/src/9/pc/devarch.c
+++ b/sys/src/9/pc/devarch.c
@@ -1133,3 +1133,62 @@
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;
+}
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -1000,109 +1000,3 @@
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();
-}
--- a/sys/src/9/pc64/l.s
+++ b/sys/src/9/pc64/l.s
@@ -332,9 +332,19 @@
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 @@
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
/*
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -26,6 +26,8 @@
char *confval[MAXCONF];
int nconf;
int delaylink;
+int idle_spin;
+
uchar *sp; /* user stack of init proc */
extern void (*i8237alloc)(void);
@@ -419,24 +421,62 @@
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
-reboot(void*, void*, ulong)
+exit(int ispanic)
{
- exit(0);
+ shutdown(ispanic);
+ arch->reset();
}
void
-idlehands(void)
+reboot(void*, void*, ulong)
{
- halt();
+ exit(0);
}
/*
@@ -706,37 +746,4 @@
* especially on VMware, but it turns out not to matter.
*/
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;
}
--
⑨