Merge branch 'nogs'

This commit is contained in:
Frans Kaashoek 2017-08-07 14:35:05 -04:00
commit 61cb32aa9b
19 changed files with 181 additions and 165 deletions

View file

@ -111,7 +111,8 @@ panic(char *s)
cli(); cli();
cons.locking = 0; cons.locking = 0;
cprintf("cpu with apicid %d: panic: ", cpu->apicid); // use lapiccpunum so that we can call panic from mycpu()
cprintf("lapicid %d: panic: ", lapicid());
cprintf(s); cprintf(s);
cprintf("\n"); cprintf("\n");
getcallerpcs(&s, pcs); getcallerpcs(&s, pcs);
@ -242,7 +243,7 @@ consoleread(struct inode *ip, char *dst, int n)
acquire(&cons.lock); acquire(&cons.lock);
while(n > 0){ while(n > 0){
while(input.r == input.w){ while(input.r == input.w){
if(proc->killed){ if(myproc()->killed){
release(&cons.lock); release(&cons.lock);
ilock(ip); ilock(ip);
return -1; return -1;

6
defs.h
View file

@ -74,7 +74,7 @@ void kbdintr(void);
// lapic.c // lapic.c
void cmostime(struct rtcdate *r); void cmostime(struct rtcdate *r);
int cpunum(void); int lapicid(void);
extern volatile uint* lapic; extern volatile uint* lapic;
void lapiceoi(void); void lapiceoi(void);
void lapicinit(void); void lapicinit(void);
@ -103,14 +103,18 @@ int pipewrite(struct pipe*, char*, int);
//PAGEBREAK: 16 //PAGEBREAK: 16
// proc.c // proc.c
int cpuid(void);
void exit(void); void exit(void);
int fork(void); int fork(void);
int growproc(int); int growproc(int);
int kill(int); int kill(int);
struct cpu* mycpu(void);
struct proc* myproc();
void pinit(void); void pinit(void);
void procdump(void); void procdump(void);
void scheduler(void) __attribute__((noreturn)); void scheduler(void) __attribute__((noreturn));
void sched(void); void sched(void);
void setproc(struct proc*);
void sleep(void*, struct spinlock*); void sleep(void*, struct spinlock*);
void userinit(void); void userinit(void);
int wait(void); int wait(void);

16
exec.c
View file

@ -17,11 +17,13 @@ exec(char *path, char **argv)
struct inode *ip; struct inode *ip;
struct proghdr ph; struct proghdr ph;
pde_t *pgdir, *oldpgdir; pde_t *pgdir, *oldpgdir;
struct proc *curproc = myproc();
begin_op(); begin_op();
if((ip = namei(path)) == 0){ if((ip = namei(path)) == 0){
end_op(); end_op();
cprintf("exec: fail\n");
return -1; return -1;
} }
ilock(ip); ilock(ip);
@ -89,15 +91,15 @@ exec(char *path, char **argv)
for(last=s=path; *s; s++) for(last=s=path; *s; s++)
if(*s == '/') if(*s == '/')
last = s+1; last = s+1;
safestrcpy(proc->name, last, sizeof(proc->name)); safestrcpy(curproc->name, last, sizeof(curproc->name));
// Commit to the user image. // Commit to the user image.
oldpgdir = proc->pgdir; oldpgdir = curproc->pgdir;
proc->pgdir = pgdir; curproc->pgdir = pgdir;
proc->sz = sz; curproc->sz = sz;
proc->tf->eip = elf.entry; // main curproc->tf->eip = elf.entry; // main
proc->tf->esp = sp; curproc->tf->esp = sp;
switchuvm(proc); switchuvm(curproc);
freevm(oldpgdir); freevm(oldpgdir);
return 0; return 0;

2
fs.c
View file

@ -615,7 +615,7 @@ namex(char *path, int nameiparent, char *name)
if(*path == '/') if(*path == '/')
ip = iget(ROOTDEV, ROOTINO); ip = iget(ROOTDEV, ROOTINO);
else else
ip = idup(proc->cwd); ip = idup(myproc()->cwd);
while((path = skipelem(path, name)) != 0){ while((path = skipelem(path, name)) != 0){
ilock(ip); ilock(ip);

3
ide.c
View file

@ -108,9 +108,9 @@ ideintr(void)
// First queued buffer is the active request. // First queued buffer is the active request.
acquire(&idelock); acquire(&idelock);
if((b = idequeue) == 0){ if((b = idequeue) == 0){
release(&idelock); release(&idelock);
// cprintf("spurious IDE interrupt\n");
return; return;
} }
idequeue = b->qnext; idequeue = b->qnext;
@ -164,5 +164,6 @@ iderw(struct buf *b)
sleep(b, &idelock); sleep(b, &idelock);
} }
release(&idelock); release(&idelock);
} }

25
lapic.c
View file

@ -9,7 +9,6 @@
#include "traps.h" #include "traps.h"
#include "mmu.h" #include "mmu.h"
#include "x86.h" #include "x86.h"
#include "proc.h" // ncpu
// Local APIC registers, divided by 4 for use as uint[] indices. // Local APIC registers, divided by 4 for use as uint[] indices.
#define ID (0x0020/4) // ID #define ID (0x0020/4) // ID
@ -99,31 +98,11 @@ lapicinit(void)
} }
int int
cpunum(void) lapicid(void)
{ {
int apicid, i;
// Cannot call cpu 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("cpu called from %x with interrupts enabled\n",
__builtin_return_address(0));
}
if (!lapic) if (!lapic)
return 0; return 0;
return lapic[ID] >> 24;
apicid = lapic[ID] >> 24;
for (i = 0; i < ncpu; ++i) {
if (cpus[i].apicid == apicid)
return i;
}
panic("unknown apicid\n");
} }
// Acknowledge interrupt. // Acknowledge interrupt.

7
main.c
View file

@ -22,7 +22,6 @@ main(void)
mpinit(); // detect other processors mpinit(); // detect other processors
lapicinit(); // interrupt controller lapicinit(); // interrupt controller
seginit(); // segment descriptors seginit(); // segment descriptors
cprintf("\ncpu%d: starting xv6\n\n", cpunum());
picinit(); // another interrupt controller picinit(); // another interrupt controller
ioapicinit(); // another interrupt controller ioapicinit(); // another interrupt controller
consoleinit(); // console hardware consoleinit(); // console hardware
@ -54,9 +53,9 @@ mpenter(void)
static void static void
mpmain(void) mpmain(void)
{ {
cprintf("cpu%d: starting\n", cpunum()); cprintf("cpu%d: starting %d\n", cpuid(), cpuid());
idtinit(); // load idt register idtinit(); // load idt register
xchg(&cpu->started, 1); // tell startothers() we're up xchg(&(mycpu()->started), 1); // tell startothers() we're up
scheduler(); // start running processes scheduler(); // start running processes
} }
@ -78,7 +77,7 @@ startothers(void)
memmove(code, _binary_entryother_start, (uint)_binary_entryother_size); memmove(code, _binary_entryother_start, (uint)_binary_entryother_size);
for(c = cpus; c < cpus+ncpu; c++){ for(c = cpus; c < cpus+ncpu; c++){
if(c == cpus+cpunum()) // We've started already. if(c == mycpu()) // We've started already.
continue; continue;
// Tell entryother.S what stack to use, where to enter, and what // Tell entryother.S what stack to use, where to enter, and what

9
mmu.h
View file

@ -42,13 +42,12 @@
// various segment selectors. // various segment selectors.
#define SEG_KCODE 1 // kernel code #define SEG_KCODE 1 // kernel code
#define SEG_KDATA 2 // kernel data+stack #define SEG_KDATA 2 // kernel data+stack
#define SEG_KCPU 3 // kernel per-cpu data #define SEG_UCODE 3 // user code
#define SEG_UCODE 4 // user code #define SEG_UDATA 4 // user data+stack
#define SEG_UDATA 5 // user data+stack #define SEG_TSS 5 // this process's task state
#define SEG_TSS 6 // this process's task state
// cpu->gdt[NSEGS] holds the above segments. // cpu->gdt[NSEGS] holds the above segments.
#define NSEGS 7 #define NSEGS 6
//PAGEBREAK! //PAGEBREAK!
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__

4
pipe.c
View file

@ -83,7 +83,7 @@ pipewrite(struct pipe *p, char *addr, int n)
acquire(&p->lock); acquire(&p->lock);
for(i = 0; i < n; i++){ for(i = 0; i < n; i++){
while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full
if(p->readopen == 0 || proc->killed){ if(p->readopen == 0 || myproc()->killed){
release(&p->lock); release(&p->lock);
return -1; return -1;
} }
@ -104,7 +104,7 @@ piperead(struct pipe *p, char *addr, int n)
acquire(&p->lock); acquire(&p->lock);
while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty
if(proc->killed){ if(myproc()->killed){
release(&p->lock); release(&p->lock);
return -1; return -1;
} }

129
proc.c
View file

@ -26,6 +26,45 @@ pinit(void)
initlock(&ptable.lock, "ptable"); initlock(&ptable.lock, "ptable");
} }
// Must be called with interrupts disabled
int
cpuid() {
return mycpu()-cpus;
}
// Must be called with interrupts disabled to avoid the caller being rescheduled
// between reading lapicid and running through the loop.
struct cpu*
mycpu(void)
{
int apicid, i;
if(readeflags()&FL_IF)
panic("mycpu called with interrupts enabled\n");
apicid = lapicid();
// APIC IDs are not guaranteed to be contiguous. Maybe we should have
// a reverse map, or reserve a register to store &cpus[i].
for (i = 0; i < ncpu; ++i) {
if (cpus[i].apicid == apicid)
return &cpus[i];
}
panic("unknown apicid\n");
}
// Disable interrupts so that we are not rescheduled
// while reading proc from the cpu structure
struct proc*
myproc(void) {
struct cpu *c;
struct proc *p;
pushcli();
c = mycpu();
p = c->proc;
popcli();
return p;
}
//PAGEBREAK: 32 //PAGEBREAK: 32
// Look in the process table for an UNUSED proc. // Look in the process table for an UNUSED proc.
// If found, change state to EMBRYO and initialize // If found, change state to EMBRYO and initialize
@ -120,17 +159,18 @@ int
growproc(int n) growproc(int n)
{ {
uint sz; uint sz;
struct proc *curproc = myproc();
sz = proc->sz; sz = curproc->sz;
if(n > 0){ if(n > 0){
if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0)
return -1; return -1;
} else if(n < 0){ } else if(n < 0){
if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0)
return -1; return -1;
} }
proc->sz = sz; curproc->sz = sz;
switchuvm(proc); switchuvm(curproc);
return 0; return 0;
} }
@ -142,32 +182,33 @@ fork(void)
{ {
int i, pid; int i, pid;
struct proc *np; struct proc *np;
struct proc *curproc = myproc();
// Allocate process. // Allocate process.
if((np = allocproc()) == 0){ if((np = allocproc()) == 0){
return -1; return -1;
} }
// Copy process state from p. // Copy process state from proc.
if((np->pgdir = copyuvm(proc->pgdir, proc->sz)) == 0){ if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){
kfree(np->kstack); kfree(np->kstack);
np->kstack = 0; np->kstack = 0;
np->state = UNUSED; np->state = UNUSED;
return -1; return -1;
} }
np->sz = proc->sz; np->sz = curproc->sz;
np->parent = proc; np->parent = curproc;
*np->tf = *proc->tf; *np->tf = *curproc->tf;
// Clear %eax so that fork returns 0 in the child. // Clear %eax so that fork returns 0 in the child.
np->tf->eax = 0; np->tf->eax = 0;
for(i = 0; i < NOFILE; i++) for(i = 0; i < NOFILE; i++)
if(proc->ofile[i]) if(curproc->ofile[i])
np->ofile[i] = filedup(proc->ofile[i]); np->ofile[i] = filedup(curproc->ofile[i]);
np->cwd = idup(proc->cwd); np->cwd = idup(curproc->cwd);
safestrcpy(np->name, proc->name, sizeof(proc->name)); safestrcpy(np->name, curproc->name, sizeof(curproc->name));
pid = np->pid; pid = np->pid;
@ -186,33 +227,34 @@ fork(void)
void void
exit(void) exit(void)
{ {
struct proc *curproc = myproc();
struct proc *p; struct proc *p;
int fd; int fd;
if(proc == initproc) if(curproc == initproc)
panic("init exiting"); panic("init exiting");
// Close all open files. // Close all open files.
for(fd = 0; fd < NOFILE; fd++){ for(fd = 0; fd < NOFILE; fd++){
if(proc->ofile[fd]){ if(curproc->ofile[fd]){
fileclose(proc->ofile[fd]); fileclose(curproc->ofile[fd]);
proc->ofile[fd] = 0; curproc->ofile[fd] = 0;
} }
} }
begin_op(); begin_op();
iput(proc->cwd); iput(curproc->cwd);
end_op(); end_op();
proc->cwd = 0; curproc->cwd = 0;
acquire(&ptable.lock); acquire(&ptable.lock);
// Parent might be sleeping in wait(). // Parent might be sleeping in wait().
wakeup1(proc->parent); wakeup1(curproc->parent);
// Pass abandoned children to init. // Pass abandoned children to init.
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
if(p->parent == proc){ if(p->parent == curproc){
p->parent = initproc; p->parent = initproc;
if(p->state == ZOMBIE) if(p->state == ZOMBIE)
wakeup1(initproc); wakeup1(initproc);
@ -220,7 +262,7 @@ exit(void)
} }
// Jump into the scheduler, never to return. // Jump into the scheduler, never to return.
proc->state = ZOMBIE; curproc->state = ZOMBIE;
sched(); sched();
panic("zombie exit"); panic("zombie exit");
} }
@ -232,13 +274,14 @@ wait(void)
{ {
struct proc *p; struct proc *p;
int havekids, pid; int havekids, pid;
struct proc *curproc = myproc();
acquire(&ptable.lock); acquire(&ptable.lock);
for(;;){ for(;;){
// Scan through table looking for exited children. // Scan through table looking for exited children.
havekids = 0; havekids = 0;
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
if(p->parent != proc) if(p->parent != curproc)
continue; continue;
havekids = 1; havekids = 1;
if(p->state == ZOMBIE){ if(p->state == ZOMBIE){
@ -258,13 +301,13 @@ wait(void)
} }
// No point waiting if we don't have any children. // No point waiting if we don't have any children.
if(!havekids || proc->killed){ if(!havekids || curproc->killed){
release(&ptable.lock); release(&ptable.lock);
return -1; return -1;
} }
// Wait for children to exit. (See wakeup1 call in proc_exit.) // Wait for children to exit. (See wakeup1 call in proc_exit.)
sleep(proc, &ptable.lock); //DOC: wait-sleep sleep(curproc, &ptable.lock); //DOC: wait-sleep
} }
} }
@ -280,6 +323,8 @@ void
scheduler(void) scheduler(void)
{ {
struct proc *p; struct proc *p;
struct cpu *c = mycpu();
c->proc = 0;
for(;;){ for(;;){
// Enable interrupts on this processor. // Enable interrupts on this processor.
@ -294,15 +339,16 @@ scheduler(void)
// Switch to chosen process. It is the process's job // Switch to chosen process. It is the process's job
// to release ptable.lock and then reacquire it // to release ptable.lock and then reacquire it
// before jumping back to us. // before jumping back to us.
proc = p; c->proc = p;
switchuvm(p); switchuvm(p);
p->state = RUNNING; p->state = RUNNING;
swtch(&cpu->scheduler, p->context);
swtch(&(c->scheduler), p->context);
switchkvm(); switchkvm();
// Process is done running for now. // Process is done running for now.
// It should have changed its p->state before coming back. // It should have changed its p->state before coming back.
proc = 0; c->proc = 0;
} }
release(&ptable.lock); release(&ptable.lock);
@ -320,18 +366,19 @@ void
sched(void) sched(void)
{ {
int intena; int intena;
struct proc *p = myproc();
if(!holding(&ptable.lock)) if(!holding(&ptable.lock))
panic("sched ptable.lock"); panic("sched ptable.lock");
if(cpu->ncli != 1) if(mycpu()->ncli != 1)
panic("sched locks"); panic("sched locks");
if(proc->state == RUNNING) if(p->state == RUNNING)
panic("sched running"); panic("sched running");
if(readeflags()&FL_IF) if(readeflags()&FL_IF)
panic("sched interruptible"); panic("sched interruptible");
intena = cpu->intena; intena = mycpu()->intena;
swtch(&proc->context, cpu->scheduler); swtch(&p->context, mycpu()->scheduler);
cpu->intena = intena; mycpu()->intena = intena;
} }
// Give up the CPU for one scheduling round. // Give up the CPU for one scheduling round.
@ -339,7 +386,7 @@ void
yield(void) yield(void)
{ {
acquire(&ptable.lock); //DOC: yieldlock acquire(&ptable.lock); //DOC: yieldlock
proc->state = RUNNABLE; myproc()->state = RUNNABLE;
sched(); sched();
release(&ptable.lock); release(&ptable.lock);
} }
@ -370,7 +417,9 @@ forkret(void)
void void
sleep(void *chan, struct spinlock *lk) sleep(void *chan, struct spinlock *lk)
{ {
if(proc == 0) struct proc *p = myproc();
if(p == 0)
panic("sleep"); panic("sleep");
if(lk == 0) if(lk == 0)
@ -386,14 +435,14 @@ sleep(void *chan, struct spinlock *lk)
acquire(&ptable.lock); //DOC: sleeplock1 acquire(&ptable.lock); //DOC: sleeplock1
release(lk); release(lk);
} }
// Go to sleep. // Go to sleep.
proc->chan = chan; p->chan = chan;
proc->state = SLEEPING; p->state = SLEEPING;
sched(); sched();
// Tidy up. // Tidy up.
proc->chan = 0; p->chan = 0;
// Reacquire original lock. // Reacquire original lock.
if(lk != &ptable.lock){ //DOC: sleeplock2 if(lk != &ptable.lock){ //DOC: sleeplock2

16
proc.h
View file

@ -7,26 +7,12 @@ struct cpu {
volatile uint started; // Has the CPU started? volatile uint started; // Has the CPU started?
int ncli; // Depth of pushcli nesting. int ncli; // Depth of pushcli nesting.
int intena; // Were interrupts enabled before pushcli? int intena; // Were interrupts enabled before pushcli?
struct proc *proc; // The process running on this cpu or null
// Cpu-local storage variables; see below
struct cpu *cpu;
struct proc *proc; // The currently-running process.
}; };
extern struct cpu cpus[NCPU]; extern struct cpu cpus[NCPU];
extern int ncpu; extern int ncpu;
// Per-CPU variables, holding pointers to the
// current cpu and to the current process.
// 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.
extern struct cpu *cpu asm("%gs:0"); // &cpus[cpunum()]
extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc
//PAGEBREAK: 17 //PAGEBREAK: 17
// Saved registers for kernel context switches. // Saved registers for kernel context switches.
// Don't need to save all the segment registers (%cs, etc), // Don't need to save all the segment registers (%cs, etc),

View file

@ -27,7 +27,7 @@ acquiresleep(struct sleeplock *lk)
sleep(lk, &lk->lk); sleep(lk, &lk->lk);
} }
lk->locked = 1; lk->locked = 1;
lk->pid = proc->pid; lk->pid = myproc()->pid;
release(&lk->lk); release(&lk->lk);
} }

View file

@ -38,7 +38,7 @@ acquire(struct spinlock *lk)
__sync_synchronize(); __sync_synchronize();
// Record info about lock acquisition for debugging. // Record info about lock acquisition for debugging.
lk->cpu = cpu; lk->cpu = mycpu();
getcallerpcs(&lk, lk->pcs); getcallerpcs(&lk, lk->pcs);
} }
@ -89,7 +89,7 @@ getcallerpcs(void *v, uint pcs[])
int int
holding(struct spinlock *lock) holding(struct spinlock *lock)
{ {
return lock->locked && lock->cpu == cpu; return lock->locked && lock->cpu == mycpu();
} }
@ -104,9 +104,9 @@ pushcli(void)
eflags = readeflags(); eflags = readeflags();
cli(); cli();
if(cpu->ncli == 0) if(mycpu()->ncli == 0)
cpu->intena = eflags & FL_IF; mycpu()->intena = eflags & FL_IF;
cpu->ncli += 1; mycpu()->ncli += 1;
} }
void void
@ -114,9 +114,9 @@ popcli(void)
{ {
if(readeflags()&FL_IF) if(readeflags()&FL_IF)
panic("popcli - interruptible"); panic("popcli - interruptible");
if(--cpu->ncli < 0) if(--mycpu()->ncli < 0)
panic("popcli"); panic("popcli");
if(cpu->ncli == 0 && cpu->intena) if(mycpu()->ncli == 0 && mycpu()->intena)
sti(); sti();
} }

View file

@ -17,7 +17,9 @@
int int
fetchint(uint addr, int *ip) fetchint(uint addr, int *ip)
{ {
if(addr >= proc->sz || addr+4 > proc->sz) struct proc *curproc = myproc();
if(addr >= curproc->sz || addr+4 > curproc->sz)
return -1; return -1;
*ip = *(int*)(addr); *ip = *(int*)(addr);
return 0; return 0;
@ -30,14 +32,16 @@ int
fetchstr(uint addr, char **pp) fetchstr(uint addr, char **pp)
{ {
char *s, *ep; char *s, *ep;
struct proc *curproc = myproc();
if(addr >= proc->sz) if(addr >= curproc->sz)
return -1; return -1;
*pp = (char*)addr; *pp = (char*)addr;
ep = (char*)proc->sz; ep = (char*)curproc->sz;
for(s = *pp; s < ep; s++) for(s = *pp; s < ep; s++){
if(*s == 0) if(*s == 0)
return s - *pp; return s - *pp;
}
return -1; return -1;
} }
@ -45,7 +49,7 @@ fetchstr(uint addr, char **pp)
int int
argint(int n, int *ip) argint(int n, int *ip)
{ {
return fetchint(proc->tf->esp + 4 + 4*n, ip); return fetchint((myproc()->tf->esp) + 4 + 4*n, ip);
} }
// Fetch the nth word-sized system call argument as a pointer // Fetch the nth word-sized system call argument as a pointer
@ -55,10 +59,11 @@ int
argptr(int n, char **pp, int size) argptr(int n, char **pp, int size)
{ {
int i; int i;
struct proc *curproc = myproc();
if(argint(n, &i) < 0) if(argint(n, &i) < 0)
return -1; return -1;
if(size < 0 || (uint)i >= proc->sz || (uint)i+size > proc->sz) if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz)
return -1; return -1;
*pp = (char*)i; *pp = (char*)i;
return 0; return 0;
@ -127,13 +132,14 @@ void
syscall(void) syscall(void)
{ {
int num; int num;
struct proc *curproc = myproc();
num = proc->tf->eax; num = curproc->tf->eax;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
proc->tf->eax = syscalls[num](); curproc->tf->eax = syscalls[num]();
} else { } else {
cprintf("%d %s: unknown sys call %d\n", cprintf("%d %s: unknown sys call %d\n",
proc->pid, proc->name, num); curproc->pid, curproc->name, num);
proc->tf->eax = -1; curproc->tf->eax = -1;
} }
} }

View file

@ -26,7 +26,7 @@ argfd(int n, int *pfd, struct file **pf)
if(argint(n, &fd) < 0) if(argint(n, &fd) < 0)
return -1; return -1;
if(fd < 0 || fd >= NOFILE || (f=proc->ofile[fd]) == 0) if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
return -1; return -1;
if(pfd) if(pfd)
*pfd = fd; *pfd = fd;
@ -41,10 +41,11 @@ static int
fdalloc(struct file *f) fdalloc(struct file *f)
{ {
int fd; int fd;
struct proc *curproc = myproc();
for(fd = 0; fd < NOFILE; fd++){ for(fd = 0; fd < NOFILE; fd++){
if(proc->ofile[fd] == 0){ if(curproc->ofile[fd] == 0){
proc->ofile[fd] = f; curproc->ofile[fd] = f;
return fd; return fd;
} }
} }
@ -97,7 +98,7 @@ sys_close(void)
if(argfd(0, &fd, &f) < 0) if(argfd(0, &fd, &f) < 0)
return -1; return -1;
proc->ofile[fd] = 0; myproc()->ofile[fd] = 0;
fileclose(f); fileclose(f);
return 0; return 0;
} }
@ -373,6 +374,7 @@ sys_chdir(void)
{ {
char *path; char *path;
struct inode *ip; struct inode *ip;
struct proc *curproc = myproc();
begin_op(); begin_op();
if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){ if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){
@ -386,9 +388,9 @@ sys_chdir(void)
return -1; return -1;
} }
iunlock(ip); iunlock(ip);
iput(proc->cwd); iput(curproc->cwd);
end_op(); end_op();
proc->cwd = ip; curproc->cwd = ip;
return 0; return 0;
} }
@ -432,7 +434,7 @@ sys_pipe(void)
fd0 = -1; fd0 = -1;
if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){ if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
if(fd0 >= 0) if(fd0 >= 0)
proc->ofile[fd0] = 0; myproc()->ofile[fd0] = 0;
fileclose(rf); fileclose(rf);
fileclose(wf); fileclose(wf);
return -1; return -1;

View file

@ -39,7 +39,7 @@ sys_kill(void)
int int
sys_getpid(void) sys_getpid(void)
{ {
return proc->pid; return myproc()->pid;
} }
int int
@ -50,7 +50,7 @@ sys_sbrk(void)
if(argint(0, &n) < 0) if(argint(0, &n) < 0)
return -1; return -1;
addr = proc->sz; addr = myproc()->sz;
if(growproc(n) < 0) if(growproc(n) < 0)
return -1; return -1;
return addr; return addr;
@ -67,7 +67,7 @@ sys_sleep(void)
acquire(&tickslock); acquire(&tickslock);
ticks0 = ticks; ticks0 = ticks;
while(ticks - ticks0 < n){ while(ticks - ticks0 < n){
if(proc->killed){ if(myproc()->killed){
release(&tickslock); release(&tickslock);
return -1; return -1;
} }

24
trap.c
View file

@ -37,18 +37,18 @@ void
trap(struct trapframe *tf) trap(struct trapframe *tf)
{ {
if(tf->trapno == T_SYSCALL){ if(tf->trapno == T_SYSCALL){
if(proc->killed) if(myproc()->killed)
exit(); exit();
proc->tf = tf; myproc()->tf = tf;
syscall(); syscall();
if(proc->killed) if(myproc()->killed)
exit(); exit();
return; return;
} }
switch(tf->trapno){ switch(tf->trapno){
case T_IRQ0 + IRQ_TIMER: case T_IRQ0 + IRQ_TIMER:
if(cpunum() == 0){ if(cpuid() == 0){
acquire(&tickslock); acquire(&tickslock);
ticks++; ticks++;
wakeup(&ticks); wakeup(&ticks);
@ -74,38 +74,38 @@ trap(struct trapframe *tf)
case T_IRQ0 + 7: case T_IRQ0 + 7:
case T_IRQ0 + IRQ_SPURIOUS: case T_IRQ0 + IRQ_SPURIOUS:
cprintf("cpu%d: spurious interrupt at %x:%x\n", cprintf("cpu%d: spurious interrupt at %x:%x\n",
cpunum(), tf->cs, tf->eip); cpuid(), tf->cs, tf->eip);
lapiceoi(); lapiceoi();
break; break;
//PAGEBREAK: 13 //PAGEBREAK: 13
default: default:
if(proc == 0 || (tf->cs&3) == 0){ if(myproc() == 0 || (tf->cs&3) == 0){
// In kernel, it must be our mistake. // In kernel, it must be our mistake.
cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
tf->trapno, cpunum(), tf->eip, rcr2()); tf->trapno, cpuid(), tf->eip, rcr2());
panic("trap"); panic("trap");
} }
// In user space, assume process misbehaved. // In user space, assume process misbehaved.
cprintf("pid %d %s: trap %d err %d on cpu %d " cprintf("pid %d %s: trap %d err %d on cpu %d "
"eip 0x%x addr 0x%x--kill proc\n", "eip 0x%x addr 0x%x--kill proc\n",
proc->pid, proc->name, tf->trapno, tf->err, cpunum(), tf->eip, myproc()->pid, myproc()->name, tf->trapno, tf->err, cpuid(), tf->eip,
rcr2()); rcr2());
proc->killed = 1; myproc()->killed = 1;
} }
// Force process exit if it has been killed and is in user space. // Force process exit if it has been killed and is in user space.
// (If it is still executing in the kernel, let it keep running // (If it is still executing in the kernel, let it keep running
// until it gets to the regular system call return.) // until it gets to the regular system call return.)
if(proc && proc->killed && (tf->cs&3) == DPL_USER) if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
exit(); exit();
// Force process to give up CPU on clock tick. // Force process to give up CPU on clock tick.
// If interrupts were on while locks held, would need to check nlock. // If interrupts were on while locks held, would need to check nlock.
if(proc && proc->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER) if(myproc() && myproc()->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER)
yield(); yield();
// Check if the process has been killed since we yielded // Check if the process has been killed since we yielded
if(proc && proc->killed && (tf->cs&3) == DPL_USER) if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
exit(); exit();
} }

View file

@ -14,9 +14,6 @@ alltraps:
movw $(SEG_KDATA<<3), %ax movw $(SEG_KDATA<<3), %ax
movw %ax, %ds movw %ax, %ds
movw %ax, %es movw %ax, %es
movw $(SEG_KCPU<<3), %ax
movw %ax, %fs
movw %ax, %gs
# Call trap(tf), where tf=%esp # Call trap(tf), where tf=%esp
pushl %esp pushl %esp

21
vm.c
View file

@ -21,21 +21,12 @@ seginit(void)
// Cannot share a CODE descriptor for both kernel and user // Cannot share a CODE descriptor for both kernel and user
// because it would have to have DPL_USR, but the CPU forbids // because it would have to have DPL_USR, but the CPU forbids
// an interrupt from CPL=0 to DPL=3. // an interrupt from CPL=0 to DPL=3.
c = &cpus[cpunum()]; c = &cpus[cpuid()];
c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0); 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_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER); 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->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);
// Map cpu and proc -- these are private per cpu.
c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0);
lgdt(c->gdt, sizeof(c->gdt)); lgdt(c->gdt, sizeof(c->gdt));
loadgs(SEG_KCPU << 3);
// Initialize cpu-local storage.
cpu = c;
proc = 0;
} }
// Return the address of the PTE in page table pgdir // Return the address of the PTE in page table pgdir
@ -173,13 +164,13 @@ switchuvm(struct proc *p)
panic("switchuvm: no pgdir"); panic("switchuvm: no pgdir");
pushcli(); pushcli();
cpu->gdt[SEG_TSS] = SEG16(STS_T32A, &cpu->ts, sizeof(cpu->ts)-1, 0); mycpu()->gdt[SEG_TSS] = SEG16(STS_T32A, &mycpu()->ts, sizeof(mycpu()->ts)-1, 0);
cpu->gdt[SEG_TSS].s = 0; mycpu()->gdt[SEG_TSS].s = 0;
cpu->ts.ss0 = SEG_KDATA << 3; mycpu()->ts.ss0 = SEG_KDATA << 3;
cpu->ts.esp0 = (uint)p->kstack + KSTACKSIZE; mycpu()->ts.esp0 = (uint)p->kstack + KSTACKSIZE;
// setting IOPL=0 in eflags *and* iomb beyond the tss segment limit // setting IOPL=0 in eflags *and* iomb beyond the tss segment limit
// forbids I/O instructions (e.g., inb and outb) from user space // forbids I/O instructions (e.g., inb and outb) from user space
cpu->ts.iomb = (ushort) 0xFFFF; mycpu()->ts.iomb = (ushort) 0xFFFF;
ltr(SEG_TSS << 3); ltr(SEG_TSS << 3);
lcr3(V2P(p->pgdir)); // switch to process's address space lcr3(V2P(p->pgdir)); // switch to process's address space
popcli(); popcli();