summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Notes4
-rw-r--r--console.c9
-rw-r--r--defs.h3
-rw-r--r--kalloc.c3
-rw-r--r--main.c13
-rw-r--r--mp.c11
-rw-r--r--proc.c25
-rw-r--r--proc.h1
-rw-r--r--spinlock.c32
-rw-r--r--spinlock.h2
-rw-r--r--x86.h14
11 files changed, 85 insertions, 32 deletions
diff --git a/Notes b/Notes
index b99bfe4..8fab37d 100644
--- a/Notes
+++ b/Notes
@@ -125,6 +125,10 @@ in general, the table locks protect both free-ness and
why can't i get a lock in console code?
always triple fault
+ because release turns on interrupts!
+ a bad idea very early in main()
+ but mp_init() calls cprintf
+
lock code shouldn't call cprintf...
ide_init doesn't work now?
and IOAPIC: read from unsupported address
diff --git a/console.c b/console.c
index 3745009..b85a295 100644
--- a/console.c
+++ b/console.c
@@ -4,6 +4,7 @@
#include "spinlock.h"
struct spinlock console_lock;
+int use_printf_lock = 0;
/*
* copy console output to parallel port, which you can tell
@@ -29,7 +30,8 @@ cons_putc(int c)
unsigned short *crt = (unsigned short *) 0xB8000; // base of CGA memory
int ind;
- //acquire(&console_lock);
+ if(use_printf_lock)
+ acquire(&console_lock);
lpt_putc(c);
@@ -62,7 +64,8 @@ cons_putc(int c)
outb(crtport, 15);
outb(crtport + 1, ind);
- //release(&console_lock);
+ if(use_printf_lock)
+ release(&console_lock);
}
void
@@ -127,6 +130,8 @@ cprintf(char *fmt, ...)
void
panic(char *s)
{
+ use_printf_lock = 0;
+ cprintf("panic: ");
cprintf(s, 0);
cprintf("\n", 0);
while(1)
diff --git a/defs.h b/defs.h
index c5dc4d8..4561ff6 100644
--- a/defs.h
+++ b/defs.h
@@ -19,6 +19,8 @@ void wakeup(void *);
void scheduler(void);
void proc_exit(void);
void yield(void);
+void cli(void);
+void sti(void);
// swtch.S
struct jmpbuf;
@@ -46,6 +48,7 @@ void pic_init(void);
// mp.c
void mp_init(void);
+void mp_startthem(void);
int cpu(void);
int mp_isbcpu(void);
void lapic_init(int);
diff --git a/kalloc.c b/kalloc.c
index 969b81d..cc5791d 100644
--- a/kalloc.c
+++ b/kalloc.c
@@ -10,6 +10,9 @@
#include "param.h"
#include "types.h"
#include "defs.h"
+#include "param.h"
+#include "mmu.h"
+#include "proc.h"
#include "spinlock.h"
struct spinlock kalloc_lock;
diff --git a/main.c b/main.c
index 9ba78a9..9015ff7 100644
--- a/main.c
+++ b/main.c
@@ -8,6 +8,7 @@
#include "syscall.h"
#include "elf.h"
#include "param.h"
+#include "spinlock.h"
extern char edata[], end[];
extern int acpu;
@@ -15,23 +16,33 @@ extern char _binary_user1_start[], _binary_user1_size[];
extern char _binary_usertests_start[], _binary_usertests_size[];
extern char _binary_userfs_start[], _binary_userfs_size[];
+extern use_printf_lock;
+
int
main()
{
struct proc *p;
if (acpu) {
+ cpus[cpu()].clis = 1;
cprintf("an application processor\n");
idtinit(); // CPU's idt
lapic_init(cpu());
lapic_timerinit();
lapic_enableintr();
+ sti();
scheduler();
}
acpu = 1;
+
// clear BSS
memset(edata, 0, end - edata);
+ mp_init(); // just set up apic so cpu() works
+ use_printf_lock = 1;
+
+ cpus[cpu()].clis = 1; // cpu starts as if we had called cli()
+
cprintf("\nxV6\n\n");
pic_init(); // initialize PIC
@@ -56,7 +67,7 @@ main()
p->ppid = 0;
setupsegs(p);
- mp_init(); // multiprocessor
+ mp_startthem();
// turn on timer and enable interrupts on the local APIC
lapic_timerinit();
diff --git a/mp.c b/mp.c
index 4258aba..068d036 100644
--- a/mp.c
+++ b/mp.c
@@ -325,8 +325,6 @@ mp_init()
struct MPCTB *mpctb;
struct MPPE *proc;
struct MPBE *bus;
- int c;
- extern int main();
int i;
ncpu = 0;
@@ -386,13 +384,20 @@ mp_init()
lapic_init(bcpu-cpus);
cprintf("ncpu: %d boot %d\n", ncpu, bcpu-cpus);
+}
+void
+mp_startthem()
+{
extern uint8_t _binary_bootother_start[], _binary_bootother_size[];
+ extern int main();
+ int c;
+
memmove((void *) APBOOTCODE,_binary_bootother_start,
(uint32_t) _binary_bootother_size);
for(c = 0; c < ncpu; c++){
- if (cpus+c == bcpu) continue;
+ if (c == cpu()) continue;
cprintf ("starting processor %d\n", c);
*(unsigned *)(APBOOTCODE-4) = (unsigned) (cpus[c].mpstack) + MPSTACK; // tell it what to use for %esp
*(unsigned *)(APBOOTCODE-8) = (unsigned)&main; // tell it where to jump to
diff --git a/proc.c b/proc.c
index 4c2586d..53469a1 100644
--- a/proc.c
+++ b/proc.c
@@ -148,6 +148,7 @@ scheduler(void)
if(i < NPROC){
np->state = RUNNING;
+ release(&proc_table_lock);
break;
}
@@ -157,8 +158,6 @@ scheduler(void)
cpus[cpu()].lastproc = np;
curproc[cpu()] = np;
-
- release(&proc_table_lock);
// h/w sets busy bit in TSS descriptor sometimes, and faults
// if it's set in LTR. so clear tss descriptor busy bit.
@@ -252,3 +251,25 @@ proc_exit()
// switch into scheduler
swtch(ZOMBIE);
}
+
+// disable interrupts
+void
+cli(void)
+{
+ cpus[cpu()].clis += 1;
+ if(cpus[cpu()].clis == 1)
+ __asm __volatile("cli");
+}
+
+// enable interrupts
+void
+sti(void)
+{
+ if(cpus[cpu()].clis < 1){
+ cprintf("cpu %d clis %d\n", cpu(), cpus[cpu()].clis);
+ panic("sti");
+ }
+ cpus[cpu()].clis -= 1;
+ if(cpus[cpu()].clis < 1)
+ __asm __volatile("sti");
+}
diff --git a/proc.h b/proc.h
index b9ec246..4c5807b 100644
--- a/proc.h
+++ b/proc.h
@@ -69,6 +69,7 @@ struct cpu {
struct jmpbuf jmpbuf;
char mpstack[MPSTACK]; // per-cpu start-up stack, only used to get into main()
struct proc *lastproc; // last proc scheduled on this cpu (never NULL)
+ int clis; // cli() nesting depth
};
extern struct cpu cpus[NCPU];
diff --git a/spinlock.c b/spinlock.c
index 9f840a8..bd6bff5 100644
--- a/spinlock.c
+++ b/spinlock.c
@@ -8,6 +8,8 @@
#define DEBUG 0
+extern use_printf_lock;
+
int getcallerpc(void *v) {
return ((int*)v)[-1];
}
@@ -15,37 +17,49 @@ int getcallerpc(void *v) {
void
acquire(struct spinlock * lock)
{
- struct proc * cp = curproc[cpu()];
+ unsigned who;
+
+ if(curproc[cpu()])
+ who = (unsigned) curproc[cpu()];
+ else
+ who = cpu() + 1;
- // on a real machine there would be a memory barrier here
if(DEBUG) cprintf("cpu%d: acquiring at %x\n", cpu(), getcallerpc(&lock));
- if (cp && lock->p == cp && lock->locked){
+
+ if (lock->who == who && lock->locked){
lock->count += 1;
} else {
cli();
- while ( cmpxchg(0, 1, &lock->locked) != 1 ) { ; }
+ // if we get the lock, eax will be zero
+ // if we don't get the lock, eax will be one
+ while ( cmpxchg(0, 1, &lock->locked) == 1 ) { ; }
lock->locker_pc = getcallerpc(&lock);
lock->count = 1;
- lock->p = cp;
+ lock->who = who;
}
+
if(DEBUG) cprintf("cpu%d: acquired at %x\n", cpu(), getcallerpc(&lock));
}
void
release(struct spinlock * lock)
{
- struct proc * cp = curproc[cpu()];
+ unsigned who;
+
+ if(curproc[cpu()])
+ who = (unsigned) curproc[cpu()];
+ else
+ who = cpu() + 1;
if(DEBUG) cprintf ("cpu%d: releasing at %x\n", cpu(), getcallerpc(&lock));
- if(lock->p != cp || lock->count < 1 || lock->locked != 1)
+ if(lock->who != who || lock->count < 1 || lock->locked != 1)
panic("release");
lock->count -= 1;
if(lock->count < 1){
- lock->p = 0;
+ lock->who = 0;
cmpxchg(1, 0, &lock->locked);
sti();
- // on a real machine there would be a memory barrier here
}
}
diff --git a/spinlock.h b/spinlock.h
index ee0a26c..a720b24 100644
--- a/spinlock.h
+++ b/spinlock.h
@@ -1,6 +1,6 @@
struct spinlock {
unsigned int locked;
- struct proc *p;
+ unsigned who;
int count;
unsigned locker_pc;
};
diff --git a/x86.h b/x86.h
index 80a4130..cc809e7 100644
--- a/x86.h
+++ b/x86.h
@@ -304,20 +304,6 @@ read_tsc(void)
return tsc;
}
-// disable interrupts
-static __inline void
-cli(void)
-{
- __asm __volatile("cli");
-}
-
-// enable interrupts
-static __inline void
-sti(void)
-{
- __asm __volatile("sti");
-}
-
struct PushRegs {
/* registers as pushed by pusha */
uint32_t reg_edi;