summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--defs.h1
-rw-r--r--lapic.c14
-rw-r--r--main.c2
-rw-r--r--mmu.h9
-rw-r--r--proc.c34
-rw-r--r--proc.h30
-rw-r--r--trapasm.S3
-rw-r--r--vm.c7
8 files changed, 33 insertions, 67 deletions
diff --git a/defs.h b/defs.h
index 5e049ae..c4870d0 100644
--- a/defs.h
+++ b/defs.h
@@ -108,6 +108,7 @@ void exit(void);
int fork(void);
int growproc(int);
int kill(int);
+struct cpu* mycpu(void);
struct proc* myproc();
void pinit(void);
void procdump(void);
diff --git a/lapic.c b/lapic.c
index 9039665..9a12f17 100644
--- a/lapic.c
+++ b/lapic.c
@@ -98,22 +98,12 @@ lapicinit(void)
lapicw(TPR, 0);
}
+// Should be called with interrupts disabled: the calling thread shouldn't be
+// rescheduled between reading lapic[ID] and checking against cpu array.
int
lapiccpunum(void)
{
int apicid, i;
-
- // Cannot call cpunum when interrupts are enabled:
- // result not guaranteed to last long enough to be used!
- // Would prefer to panic but even printing is chancy here:
- // almost everything, including cprintf and panic, calls cpu,
- // often indirectly through acquire and release.
- if(readeflags()&FL_IF){
- static int n;
- if(n++ == 0)
- cprintf("cpunum called from %x with interrupts enabled\n",
- __builtin_return_address(0));
- }
if (!lapic)
return 0;
diff --git a/main.c b/main.c
index d7e59cf..e5b7d64 100644
--- a/main.c
+++ b/main.c
@@ -53,7 +53,7 @@ mpenter(void)
static void
mpmain(void)
{
- cprintf("cpu%d: starting %d\n", cpuid(), lapiccpunum());
+ cprintf("cpu%d: starting %d\n", cpuid(), cpuid());
idtinit(); // load idt register
xchg(&(mycpu()->started), 1); // tell startothers() we're up
scheduler(); // start running processes
diff --git a/mmu.h b/mmu.h
index e732ccd..a1afa9f 100644
--- a/mmu.h
+++ b/mmu.h
@@ -42,13 +42,12 @@
// various segment selectors.
#define SEG_KCODE 1 // kernel code
#define SEG_KDATA 2 // kernel data+stack
-#define SEG_KCPU 3 // kernel per-cpu data
-#define SEG_UCODE 4 // user code
-#define SEG_UDATA 5 // user data+stack
-#define SEG_TSS 6 // this process's task state
+#define SEG_UCODE 3 // user code
+#define SEG_UDATA 4 // user data+stack
+#define SEG_TSS 5 // this process's task state
// cpu->gdt[NSEGS] holds the above segments.
-#define NSEGS 7
+#define NSEGS 6
//PAGEBREAK!
#ifndef __ASSEMBLER__
diff --git a/proc.c b/proc.c
index 4e8f461..6445725 100644
--- a/proc.c
+++ b/proc.c
@@ -26,12 +26,29 @@ pinit(void)
initlock(&ptable.lock, "ptable");
}
-// XXX get rid off?
+// Must be called with interrupts disabled
int
cpuid() {
return mycpu()-cpus;
}
+// Must be called with interrupts disabled
+struct cpu*
+mycpu(void)
+{
+ // Would prefer to panic but even printing is chancy here: almost everything,
+ // including cprintf and panic, calls mycpu(), often indirectly through
+ // acquire and release.
+ if(readeflags()&FL_IF){
+ static int n;
+ if(n++ == 0)
+ cprintf("mycpu called from %x with interrupts enabled\n",
+ __builtin_return_address(0));
+ }
+
+ return &cpus[lapiccpunum()];
+}
+
// Disable interrupts so that we are not rescheduled
// while reading proc from the cpu structure
struct proc*
@@ -304,7 +321,8 @@ scheduler(void)
{
struct proc *p;
struct cpu *c = mycpu();
-
+ c->proc = 0;
+
for(;;){
// Enable interrupts on this processor.
sti();
@@ -321,15 +339,13 @@ scheduler(void)
c->proc = p;
switchuvm(p);
p->state = RUNNING;
- p->cpu = c;
- // cprintf("%d: switch to %d\n", c-cpus, p->pid);
- swtch(&(p->cpu->scheduler), p->context);
+
+ swtch(&(c->scheduler), p->context);
switchkvm();
// Process is done running for now.
// It should have changed its p->state before coming back.
c->proc = 0;
- p->cpu = 0;
}
release(&ptable.lock);
@@ -358,9 +374,7 @@ sched(void)
if(readeflags()&FL_IF)
panic("sched interruptible");
intena = mycpu()->intena;
- // cprintf("%d: before swtch %d %x\n", p->cpu-cpus, p->pid, * (int *) 0x1d);
- swtch(&p->context, p->cpu->scheduler);
- // cprintf("%d/%d: after swtch %d %x\n", cpuid(), p->cpu-cpus, p->pid, * (int *) 0x1d);
+ swtch(&p->context, mycpu()->scheduler);
mycpu()->intena = intena;
}
@@ -422,8 +436,6 @@ sleep(void *chan, struct spinlock *lk)
p->chan = chan;
p->state = SLEEPING;
- // cprintf("sleep %d\n", p->pid);
-
sched();
// Tidy up.
diff --git a/proc.h b/proc.h
index 7047d54..1647114 100644
--- a/proc.h
+++ b/proc.h
@@ -7,39 +7,12 @@ struct cpu {
volatile uint started; // Has the CPU started?
int ncli; // Depth of pushcli nesting.
int intena; // Were interrupts enabled before pushcli?
- // Per-CPU variables, holding pointers to the current cpu and to the current
- // process (see cpu() and proc() in proc.c)
- struct cpu *cpu; // On cpu 0, cpu = &cpus[0]; on cpu 1, cpu=&cpus[1], etc.
- struct proc *proc; // The currently-running process on this cpu
+ struct proc *proc; // The process running on this cpu or null
};
extern struct cpu cpus[NCPU];
extern int ncpu;
-// The asm suffix tells gcc to use "%gs:0" to refer to cpu
-// and "%gs:4" to refer to proc. seginit sets up the
-// %gs segment register so that %gs refers to the memory
-// holding those two variables in the local cpu's struct cpu.
-// This is similar to how thread-local variables are implemented
-// in thread libraries such as Linux pthreads.
-
-static inline struct cpu*
-mycpu(void) {
- struct cpu *cpu;
- asm("movl %%gs:0, %0" : "=r"(cpu));
- return cpu;
-}
-
-#if 0
-static inline struct proc*
-myproc(void) {
- struct proc *proc;
- asm("movl %%gs:4, %0" : "=r"(proc));
- return proc;
-}
-#endif
-
-
//PAGEBREAK: 17
// Saved registers for kernel context switches.
// Don't need to save all the segment registers (%cs, etc),
@@ -76,7 +49,6 @@ struct proc {
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
- struct cpu *cpu; // If running, which cpu.
};
// Process memory is laid out contiguously, low addresses first:
diff --git a/trapasm.S b/trapasm.S
index 787727f..2271d27 100644
--- a/trapasm.S
+++ b/trapasm.S
@@ -14,9 +14,6 @@ alltraps:
movw $(SEG_KDATA<<3), %ax
movw %ax, %ds
movw %ax, %es
- movw $(SEG_KCPU<<3), %ax
- movw %ax, %fs
- movw %ax, %gs
# Call trap(tf), where tf=%esp
pushl %esp
diff --git a/vm.c b/vm.c
index d1640e8..9ac7401 100644
--- a/vm.c
+++ b/vm.c
@@ -21,17 +21,12 @@ seginit(void)
// Cannot share a CODE descriptor for both kernel and user
// because it would have to have DPL_USR, but the CPU forbids
// an interrupt from CPL=0 to DPL=3.
- c = &cpus[lapiccpunum()];
+ c = &cpus[cpuid()];
c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0);
c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER);
c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);
- c->cpu = c;
- c->proc = 0;
- // Map cpu and proc -- these are private per cpu.
- c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 4, 0);
lgdt(c->gdt, sizeof(c->gdt));
- loadgs(SEG_KCPU << 3);
}
// Return the address of the PTE in page table pgdir