diff options
| -rw-r--r-- | defs.h | 1 | ||||
| -rw-r--r-- | lapic.c | 14 | ||||
| -rw-r--r-- | main.c | 2 | ||||
| -rw-r--r-- | mmu.h | 9 | ||||
| -rw-r--r-- | proc.c | 34 | ||||
| -rw-r--r-- | proc.h | 30 | ||||
| -rw-r--r-- | trapasm.S | 3 | ||||
| -rw-r--r-- | vm.c | 7 | 
8 files changed, 33 insertions, 67 deletions
| @@ -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); @@ -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; @@ -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 @@ -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__ @@ -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. @@ -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: @@ -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 @@ -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 | 
