diff --git a/Notes b/Notes index 9cebfab..1a2ad2e 100644 --- a/Notes +++ b/Notes @@ -95,49 +95,15 @@ inode->count counts in-memory pointers to the struct blocks and inodes have ad-hoc sleep-locks provide a single mechanism? -test 14-character file names -and file arguments longer than 14 - kalloc() can return 0; do callers handle this right? -OH! recursive interrupts will use up any amount of cpu[].stack! - underflow and wrecks *previous* cpu's struct - -disk scheduling -mkdir -sh arguments -sh redirection -indirect blocks -is there a create/create race for same file name? - resulting in two entries w/ same name in directory? -why does shell often ignore first line of input? - test: one process unlinks a file while another links to it test: one process opens a file while another deletes it -test: mkdir. deadlock d/.. vs ../d, two processes. +test: deadlock d/.. vs ../d, two processes. test: dup() shared fd->off test: sbrk test: does echo foo > x truncate x? -make proc[0] runnable -cpu early tss and gdt -how do we get cpu0 scheduler() to use mpstack, not proc[0].kstack? -when iget() first sleeps, where does it longjmp to? -maybe set up proc[0] to be runnable, with entry proc0main(), then - have main() call scheduler()? - perhaps so proc[0] uses right kstack? - and scheduler() uses mpstack? -ltr sets the busy bit in the TSS, faults if already set - so gdt and TSS per cpu? - we don't want to be using some random process's gdt when it changes it. -maybe get rid of per-proc gdt and ts - one per cpu - refresh it when needed - setupsegs(proc *) - -why do we get 0 characters from keyboard? -are the locks in the right place in keyboardintr? - sh: support pipes? leave it for the class? sh: dynamic memory allocation? sh: should sh support ; () & --- need malloc @@ -146,3 +112,11 @@ sh: stop stdin on ctrl-d (for cat > y) really should have bdwrite() for file content and make some inode updates async so soft updates make sense + +disk scheduling +echo foo > bar should truncate bar + so O_CREATE should not truncate + but O_TRUNC should + +make it work on one cpu +make it work on amsterdam diff --git a/console.c b/console.c index d1741dd..803a896 100644 --- a/console.c +++ b/console.c @@ -9,10 +9,6 @@ struct spinlock console_lock; int panicked = 0; int use_console_lock = 0; -// per-cpu copy of output to help panic/lock debugging -char obuf[NCPU][1024]; -uint obufi[NCPU]; - /* * copy console output to parallel port, which you can tell * .bochsrc to copy to the stdout: @@ -37,10 +33,6 @@ cons_putc(int c) ushort *crt = (ushort *) 0xB8000; // base of CGA memory int ind; - obuf[rcr4()][obufi[rcr4()]++] = c; - if(obufi[rcr4()] >= 1024) - obufi[rcr4()] = 0; - if(panicked){ cli(); for(;;) diff --git a/defs.h b/defs.h index 1e41dba..fd154ac 100644 --- a/defs.h +++ b/defs.h @@ -16,7 +16,7 @@ struct jmpbuf; void setupsegs(struct proc *); struct proc * copyproc(struct proc*); struct spinlock; -char *growproc(int); +int growproc(int); void sleep(void *, struct spinlock *); void wakeup(void *); void scheduler(void); diff --git a/main.c b/main.c index 9611f74..5470e6a 100644 --- a/main.c +++ b/main.c @@ -25,8 +25,6 @@ main0(void) int i; struct proc *p; - lcr4(0); // xxx copy of cpu # - // clear BSS memset(edata, 0, end - edata); @@ -97,8 +95,6 @@ main0(void) void mpmain(void) { - lcr4(1); // xxx copy of cpu # - cprintf("cpu%d: starting\n", cpu()); idtinit(); // CPU's idt if(cpu() == 0) diff --git a/param.h b/param.h index c8d15b7..c62b533 100644 --- a/param.h +++ b/param.h @@ -1,10 +1,10 @@ -#define NPROC 64 -#define PAGE 4096 -#define KSTACKSIZE PAGE -#define NCPU 8 -#define NOFILE 16 // file descriptors per process -#define NFD 100 // file descriptors per system -#define NREQUEST 100 // outstanding disk requests -#define NBUF 10 -#define NINODE 100 -#define NDEV 10 +#define NPROC 64 // maximum number of processes +#define PAGE 4096 // granularity of user-space memory allocation +#define KSTACKSIZE PAGE // size of per-process kernel stack +#define NCPU 8 // maximum number of CPUs +#define NOFILE 16 // file descriptors per process +#define NFD 100 // file descriptors per system +#define NREQUEST 100 // outstanding disk requests +#define NBUF 10 // size of disk block cache +#define NINODE 100 // maximum number of active i-nodes +#define NDEV 10 // maximum major device number diff --git a/proc.c b/proc.c index 4767827..81149d7 100644 --- a/proc.c +++ b/proc.c @@ -138,22 +138,22 @@ copyproc(struct proc* p) return np; } -char * +int growproc(int n) { struct proc *cp = curproc[cpu()]; char *newmem, *oldmem; newmem = kalloc(cp->sz + n); - if(newmem == 0) return (char *) -1; + if(newmem == 0) + return -1; memmove(newmem, cp->mem, cp->sz); memset(newmem + cp->sz, 0, n); oldmem = cp->mem; cp->mem = newmem; kfree(oldmem, cp->sz); - cprintf("growproc: added %d bytes to %d bytes\n", n, cp->sz); cp->sz += n; - return cp->sz - n; + return 0; } // Per-CPU process scheduler. diff --git a/spinlock.c b/spinlock.c index 663fe33..c77e444 100644 --- a/spinlock.c +++ b/spinlock.c @@ -6,18 +6,11 @@ #include "proc.h" #include "spinlock.h" -// Can't call cprintf from inside these routines, -// because cprintf uses them itself. -//#define cprintf dont_use_cprintf - -#define LOCKMAGIC 0x6673ffea - extern int use_console_lock; void initlock(struct spinlock *lock, char *name) { - lock->magic = LOCKMAGIC; lock->name = name; lock->locked = 0; lock->cpu = 0xffffffff; @@ -38,8 +31,6 @@ getcallerpcs(void *v, uint pcs[]) void acquire(struct spinlock * lock) { - if(lock->magic != LOCKMAGIC) - panic("weird lock magic"); if(holding(lock)) panic("acquire"); @@ -47,34 +38,32 @@ acquire(struct spinlock * lock) cli(); cpus[cpu()].nlock++; - while(cmpxchg(0, 1, &lock->locked) == 1) - ; - cpuid(0, 0, 0, 0, 0); // memory barrier - getcallerpcs(&lock, lock->pcs); - lock->cpu = cpu() + 10; - cpus[cpu()].lastacquire = lock; + while(cmpxchg(0, 1, &lock->locked) == 1) + ; + cpuid(0, 0, 0, 0, 0); // memory barrier + getcallerpcs(&lock, lock->pcs); + lock->cpu = cpu() + 10; + cpus[cpu()].lastacquire = lock; } void release(struct spinlock * lock) { - if(lock->magic != LOCKMAGIC) - panic("weird lock magic"); - if(!holding(lock)) - panic("release"); + if(!holding(lock)) + panic("release"); - cpus[cpu()].lastrelease = lock; - lock->pcs[0] = 0; - lock->cpu = 0xffffffff; - cpuid(0, 0, 0, 0, 0); // memory barrier - lock->locked = 0; - if(--cpus[cpu()].nlock == 0) - sti(); + cpus[cpu()].lastrelease = lock; + lock->pcs[0] = 0; + lock->cpu = 0xffffffff; + cpuid(0, 0, 0, 0, 0); // memory barrier + lock->locked = 0; + if(--cpus[cpu()].nlock == 0) + sti(); } int holding(struct spinlock *lock) { - return lock->locked && lock->cpu == cpu() + 10; + return lock->locked && lock->cpu == cpu() + 10; } diff --git a/spinlock.h b/spinlock.h index f124f15..ae5ad1f 100644 --- a/spinlock.h +++ b/spinlock.h @@ -1,5 +1,4 @@ struct spinlock { - uint magic; char *name; uint locked; int cpu; diff --git a/syscall.c b/syscall.c index b0933db..0c4d654 100644 --- a/syscall.c +++ b/syscall.c @@ -473,15 +473,15 @@ sys_getpid(void) int sys_sbrk(void) { - char *r; int n; struct proc *cp = curproc[cpu()]; if(fetcharg(0, &n) < 0) return -1; - r = growproc(n); + if(growproc(n) != 0) + return -1; setupsegs(cp); - return (int) r; + return 0; } int diff --git a/trap.c b/trap.c index f26024b..f9a9fc8 100644 --- a/trap.c +++ b/trap.c @@ -34,59 +34,19 @@ void trap(struct trapframe *tf) { int v = tf->trapno; - - if(cpus[cpu()].nlock){ - cprintf("trap v %d eip %x cpu %d nlock %d\n", - v, tf->eip, cpu(), cpus[cpu()].nlock); - panic("interrupt while holding a lock"); - } - - if(curproc[cpu()] == 0){ - if(&tf < cpus[cpu()].mpstack || &tf > cpus[cpu()].mpstack + MPSTACK){ - cprintf("&tf %x mpstack %x\n", &tf, cpus[cpu()].mpstack); - panic("trap cpu stack"); - } - } else if(curproc[cpu()]){ - if(&tf < curproc[cpu()]->kstack){ - panic("trap kstack"); - } - } if(v == T_SYSCALL){ struct proc *cp = curproc[cpu()]; int num = cp->tf->eax; - if((read_eflags() & FL_IF) == 0) - panic("syscall but interrupts now disabled"); - if(cp == 0) - panic("syscall with no proc"); if(cp->killed) proc_exit(); cp->tf = tf; syscall(); - if(cp != curproc[cpu()]) - panic("trap ret wrong curproc"); - if(cp->state != RUNNING) - panic("trap ret but not RUNNING"); - if(tf != cp->tf) - panic("trap ret wrong tf"); - if(cpus[cpu()].nlock){ - cprintf("num=%d\n", num); - panic("syscall returning locks held"); - } - if((read_eflags() & FL_IF) == 0) - panic("syscall returning but FL_IF clear"); - if(read_esp() < (uint)cp->kstack || - read_esp() >= (uint)cp->kstack + KSTACKSIZE) - panic("trap ret esp wrong"); if(cp->killed) proc_exit(); - // XXX probably ought to lgdt on trap return return; } - //if(read_eflags() & FL_IF) - //panic("interrupt but interrupts enabled"); - if(v == (IRQ_OFFSET + IRQ_TIMER)){ struct proc *cp = curproc[cpu()]; lapic_timerintr(); @@ -108,8 +68,6 @@ trap(struct trapframe *tf) if(v == (IRQ_OFFSET + IRQ_IDE)){ ide_intr(); - if(cpus[cpu()].nlock) - panic("ide_intr returned while holding a lock"); cli(); // prevent a waiting interrupt from overflowing stack lapic_eoi(); return; @@ -117,9 +75,6 @@ trap(struct trapframe *tf) if(v == (IRQ_OFFSET + IRQ_KBD)){ kbd_intr(); - if(cpus[cpu()].nlock){ - panic("kbd_intr returned while holding a lock"); - } cli(); // prevent a waiting interrupt from overflowing stack lapic_eoi(); return; diff --git a/x86.h b/x86.h index ea60064..7d3452d 100644 --- a/x86.h +++ b/x86.h @@ -1,45 +1,3 @@ -static __inline void breakpoint(void) __attribute__((always_inline)); -static __inline uchar inb(int port) __attribute__((always_inline)); -static __inline void insb(int port, void *addr, int cnt) __attribute__((always_inline)); -static __inline ushort inw(int port) __attribute__((always_inline)); -static __inline void insw(int port, void *addr, int cnt) __attribute__((always_inline)); -static __inline uint inl(int port) __attribute__((always_inline)); -static __inline void insl(int port, void *addr, int cnt) __attribute__((always_inline)); -static __inline void outb(int port, uchar data) __attribute__((always_inline)); -static __inline void outsb(int port, const void *addr, int cnt) __attribute__((always_inline)); -static __inline void outw(int port, ushort data) __attribute__((always_inline)); -static __inline void outsw(int port, const void *addr, int cnt) __attribute__((always_inline)); -static __inline void outsl(int port, const void *addr, int cnt) __attribute__((always_inline)); -static __inline void outl(int port, uint data) __attribute__((always_inline)); -static __inline void invlpg(void *addr) __attribute__((always_inline)); -struct segdesc; -static __inline void lgdt(struct segdesc *p, int) __attribute__((always_inline)); -struct gatedesc; -static __inline void lidt(struct gatedesc *p, int) __attribute__((always_inline)); -static __inline void lldt(ushort sel) __attribute__((always_inline)); -static __inline void ltr(ushort sel) __attribute__((always_inline)); -static __inline void lcr0(uint val) __attribute__((always_inline)); -static __inline uint rcr0(void) __attribute__((always_inline)); -static __inline uint rcr2(void) __attribute__((always_inline)); -static __inline void lcr3(uint val) __attribute__((always_inline)); -static __inline uint rcr3(void) __attribute__((always_inline)); -static __inline void lcr4(uint val) __attribute__((always_inline)); -static __inline uint rcr4(void) __attribute__((always_inline)); -static __inline void tlbflush(void) __attribute__((always_inline)); -static __inline uint read_eflags(void) __attribute__((always_inline)); -static __inline void write_eflags(uint eflags) __attribute__((always_inline)); -static __inline uint read_ebp(void) __attribute__((always_inline)); -static __inline uint read_esp(void) __attribute__((always_inline)); -static __inline void cpuid(uint info, uint *eaxp, uint *ebxp, uint *ecxp, uint *edxp); -static __inline void cli(void) __attribute__((always_inline)); -static __inline void sti(void) __attribute__((always_inline)); - -static __inline void -breakpoint(void) -{ - __asm __volatile("int3"); -} - static __inline uchar inb(int port) { @@ -48,40 +6,6 @@ inb(int port) return data; } -static __inline void -insb(int port, void *addr, int cnt) -{ - __asm __volatile("cld\n\trepne\n\tinsb" : - "=D" (addr), "=c" (cnt) : - "d" (port), "0" (addr), "1" (cnt) : - "memory", "cc"); -} - -static __inline ushort -inw(int port) -{ - ushort data; - __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port)); - return data; -} - -static __inline void -insw(int port, void *addr, int cnt) -{ - __asm __volatile("cld\n\trepne\n\tinsw" : - "=D" (addr), "=c" (cnt) : - "d" (port), "0" (addr), "1" (cnt) : - "memory", "cc"); -} - -static __inline uint -inl(int port) -{ - uint data; - __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port)); - return data; -} - static __inline void insl(int port, void *addr, int cnt) { @@ -97,30 +21,12 @@ outb(int port, uchar data) __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port)); } -static __inline void -outsb(int port, const void *addr, int cnt) -{ - __asm __volatile("cld\n\trepne\n\toutsb" : - "=S" (addr), "=c" (cnt) : - "d" (port), "0" (addr), "1" (cnt) : - "cc"); -} - static __inline void outw(int port, ushort data) { __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port)); } -static __inline void -outsw(int port, const void *addr, int cnt) -{ - __asm __volatile("cld\n\trepne\n\toutsw" : - "=S" (addr), "=c" (cnt) : - "d" (port), "0" (addr), "1" (cnt) : - "cc"); -} - static __inline void outsl(int port, const void *addr, int cnt) { @@ -130,17 +36,7 @@ outsl(int port, const void *addr, int cnt) "cc"); } -static __inline void -outl(int port, uint data) -{ - __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port)); -} - -static __inline void -invlpg(void *addr) -{ - __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory"); -} +struct segdesc; static __inline void lgdt(struct segdesc *p, int size) @@ -154,6 +50,8 @@ lgdt(struct segdesc *p, int size) asm volatile("lgdt (%0)" : : "g" (pd)); } +struct gatedesc; + static __inline void lidt(struct gatedesc *p, int size) { @@ -166,76 +64,12 @@ lidt(struct gatedesc *p, int size) asm volatile("lidt (%0)" : : "g" (pd)); } -static __inline void -lldt(ushort sel) -{ - __asm __volatile("lldt %0" : : "r" (sel)); -} - static __inline void ltr(ushort sel) { __asm __volatile("ltr %0" : : "r" (sel)); } -static __inline void -lcr0(uint val) -{ - __asm __volatile("movl %0,%%cr0" : : "r" (val)); -} - -static __inline uint -rcr0(void) -{ - uint val; - __asm __volatile("movl %%cr0,%0" : "=r" (val)); - return val; -} - -static __inline uint -rcr2(void) -{ - uint val; - __asm __volatile("movl %%cr2,%0" : "=r" (val)); - return val; -} - -static __inline void -lcr3(uint val) -{ - __asm __volatile("movl %0,%%cr3" : : "r" (val)); -} - -static __inline uint -rcr3(void) -{ - uint val; - __asm __volatile("movl %%cr3,%0" : "=r" (val)); - return val; -} - -static __inline void -lcr4(uint val) -{ - __asm __volatile("movl %0,%%cr4" : : "r" (val)); -} - -static __inline uint -rcr4(void) -{ - uint cr4; - __asm __volatile("movl %%cr4,%0" : "=r" (cr4)); - return cr4; -} - -static __inline void -tlbflush(void) -{ - uint cr3; - __asm __volatile("movl %%cr3,%0" : "=r" (cr3)); - __asm __volatile("movl %0,%%cr3" : : "r" (cr3)); -} - static __inline uint read_eflags(void) { @@ -250,46 +84,6 @@ write_eflags(uint eflags) __asm __volatile("pushl %0; popfl" : : "r" (eflags)); } -static __inline uint -read_ebp(void) -{ - uint ebp; - __asm __volatile("movl %%ebp,%0" : "=r" (ebp)); - return ebp; -} - -static __inline uint -read_esp(void) -{ - uint esp; - __asm __volatile("movl %%esp,%0" : "=r" (esp)); - return esp; -} - -static __inline uint -read_esi(void) -{ - uint esi; - __asm __volatile("movl %%esi,%0" : "=r" (esi)); - return esi; -} - -static __inline uint -read_edi(void) -{ - uint edi; - __asm __volatile("movl %%edi,%0" : "=r" (edi)); - return edi; -} - -static __inline uint -read_ebx(void) -{ - uint ebx; - __asm __volatile("movl %%ebx,%0" : "=r" (ebx)); - return ebx; -} - static __inline void cpuid(uint info, uint *eaxp, uint *ebxp, uint *ecxp, uint *edxp) {