summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrtm <rtm>2006-07-01 21:26:01 +0000
committerrtm <rtm>2006-07-01 21:26:01 +0000
commit8b4e2a08febc8b957b44732dbc7da831479a0005 (patch)
tree46c3b079ec65f0efbd1f3b603f1b11a3ae09e56d
parentf7cea12b38a86e9b37fa5bc635310d3f85e5f8db (diff)
downloadxv6-labs-8b4e2a08febc8b957b44732dbc7da831479a0005.tar.gz
xv6-labs-8b4e2a08febc8b957b44732dbc7da831479a0005.tar.bz2
xv6-labs-8b4e2a08febc8b957b44732dbc7da831479a0005.zip
swtch saves callee-saved registers
swtch idles on per-CPU stack, not on calling process's stack fix pipe bugs usertest.c tests pipes, fork, exit, close
-rw-r--r--Makefile2
-rw-r--r--fd.c30
-rw-r--r--kalloc.c5
-rw-r--r--main.c2
-rw-r--r--mp.c12
-rw-r--r--pipe.c14
-rw-r--r--proc.c44
-rw-r--r--proc.h11
-rw-r--r--syscall.c38
-rw-r--r--syscall.h1
-rw-r--r--trap.c16
-rw-r--r--ulib.c14
-rw-r--r--usertests.c40
-rw-r--r--x86.h38
14 files changed, 212 insertions, 55 deletions
diff --git a/Makefile b/Makefile
index 0b716b4..f82d260 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ CC = i386-jos-elf-gcc
LD = i386-jos-elf-ld
OBJCOPY = i386-jos-elf-objcopy
OBJDUMP = i386-jos-elf-objdump
-CFLAGS = -nostdinc -I. -O -Wall -MD
+CFLAGS = -nostdinc -I. -O2 -Wall -MD
xv6.img : bootblock kernel
dd if=/dev/zero of=xv6.img count=10000
diff --git a/fd.c b/fd.c
index 0546cef..8b59605 100644
--- a/fd.c
+++ b/fd.c
@@ -37,19 +37,6 @@ fd_alloc()
return 0;
}
-void
-fd_close(struct fd *fd)
-{
- if(fd->type == FD_CLOSED || fd->count <= 0)
- panic("fd_close");
- fd->count -= 1;
- if(fd->count == 0){
- if(fd->type == FD_PIPE)
- pipe_close(fd->pipe, fd->writeable);
- fd->type = FD_CLOSED;
- }
-}
-
/*
* addr is a kernel address, pointing into some process's p->mem.
*/
@@ -78,3 +65,20 @@ fd_read(struct fd *fd, char *addr, int n)
return -1;
}
}
+
+void
+fd_close(struct fd *fd)
+{
+ if(fd->count < 1 || fd->type == FD_CLOSED)
+ panic("fd_close");
+ fd->count -= 1;
+
+ if(fd->count == 0){
+ if(fd->type == FD_PIPE){
+ pipe_close(fd->pipe, fd->writeable);
+ } else {
+ panic("fd_close");
+ }
+ fd->type = FD_CLOSED;
+ }
+}
diff --git a/kalloc.c b/kalloc.c
index 5ea38fd..1944508 100644
--- a/kalloc.c
+++ b/kalloc.c
@@ -45,10 +45,15 @@ kfree(char *cp, int len)
struct run **rr;
struct run *p = (struct run *) cp;
struct run *pend = (struct run *) (cp + len);
+ int i;
if(len % PAGE)
panic("kfree");
+ // XXX fill with junk to help debug
+ for(i = 0; i < len; i++)
+ cp[i] = 1;
+
rr = &freelist;
while(*rr){
struct run *rend = (struct run *) ((char *)(*rr) + (*rr)->len);
diff --git a/main.c b/main.c
index 979048c..4c2a2f9 100644
--- a/main.c
+++ b/main.c
@@ -46,7 +46,7 @@ main()
p = &proc[0];
curproc[cpu()] = p;
p->state = WAITING;
- p->sz = PAGE;
+ p->sz = 4 * PAGE;
p->mem = kalloc(p->sz);
memset(p->mem, 0, p->sz);
p->kstack = kalloc(KSTACKSIZE);
diff --git a/mp.c b/mp.c
index eb5afc9..57b887d 100644
--- a/mp.c
+++ b/mp.c
@@ -6,6 +6,7 @@
#include "x86.h"
#include "traps.h"
#include "mmu.h"
+#include "proc.h"
/*
* Credit: Plan 9 sources, Intel MP spec, and Cliff Frey
@@ -92,16 +93,11 @@ enum { /* LAPIC_TDCR */
};
#define APBOOTCODE 0x7000 // XXX hack
-#define MPSTACK 512
static struct MP* mp; // The MP floating point structure
static uint32_t *lapicaddr;
-static struct cpu {
- uint8_t apicid; // Local APIC ID
- int lintr[2]; // Local APIC
- char mpstack[MPSTACK]; // per-cpu start-up stack, only used to get into main()
-} cpus[NCPU];
-static int ncpu;
+struct cpu cpus[NCPU];
+int ncpu;
static struct cpu *bcpu;
static int
@@ -130,7 +126,7 @@ lapic_timerinit()
void
lapic_timerintr()
{
- cprintf("%d: timer interrupt!\n", cpu());
+ // cprintf("%d: timer interrupt!\n", cpu());
lapic_write (LAPIC_EOI, 0);
}
diff --git a/pipe.c b/pipe.c
index 9a81e0b..3aed4e9 100644
--- a/pipe.c
+++ b/pipe.c
@@ -28,6 +28,10 @@ pipe_alloc(struct fd **fd1, struct fd **fd2)
goto oops;
if((p = (struct pipe *) kalloc(PAGE)) == 0)
goto oops;
+ p->readopen = 1;
+ p->writeopen = 1;
+ p->writep = 0;
+ p->readp = 0;
(*fd1)->type = FD_PIPE;
(*fd1)->readable = 1;
(*fd1)->writeable = 0;
@@ -54,10 +58,13 @@ pipe_alloc(struct fd **fd1, struct fd **fd2)
void
pipe_close(struct pipe *p, int writeable)
{
- if(writeable)
+ if(writeable){
p->writeopen = 0;
- else
+ wakeup(&p->readp);
+ } else {
p->readopen = 0;
+ wakeup(&p->writep);
+ }
if(p->readopen == 0 && p->writeopen == 0)
kfree((char *) p, PAGE);
}
@@ -71,11 +78,13 @@ pipe_write(struct pipe *p, char *addr, int n)
while(((p->writep + 1) % PIPESIZE) == p->readp){
if(p->readopen == 0)
return -1;
+ wakeup(&p->readp);
sleep(&p->writep);
}
p->data[p->writep] = addr[i];
p->writep = (p->writep + 1) % PIPESIZE;
}
+ wakeup(&p->readp);
return i;
}
@@ -96,5 +105,6 @@ pipe_read(struct pipe *p, char *addr, int n)
addr[i] = p->data[p->readp];
p->readp = (p->readp + 1) % PIPESIZE;
}
+ wakeup(&p->writep);
return i;
}
diff --git a/proc.c b/proc.c
index 97e84e3..8ad6a23 100644
--- a/proc.c
+++ b/proc.c
@@ -104,37 +104,47 @@ swtch()
{
struct proc *np;
struct proc *op = curproc[cpu()];
-
+ unsigned sp;
+ int i;
+
+ // force push of callee-saved registers
+ asm volatile("nop" : : : "%edi", "%esi", "%ebx");
+
+ // save calling process's stack pointers
+ op->ebp = read_ebp();
+ op->esp = read_esp();
+
+ // don't execute on calling process's stack
+ sp = (unsigned) cpus[cpu()].mpstack + MPSTACK - 32;
+ asm volatile("movl %0, %%esp" : : "g" (sp));
+ asm volatile("movl %0, %%ebp" : : "g" (sp));
+
+ // gcc might store op on the stack
+ np = curproc[cpu()];
+ np = np + 1;
+
while(1){
- np = op + 1;
- while(np != op){
+ for(i = 0; i < NPROC; i++){
+ if(np >= &proc[NPROC])
+ np = &proc[0];
if(np->state == RUNNABLE)
break;
np++;
- if(np == &proc[NPROC])
- np = &proc[0];
}
- if(np->state == RUNNABLE)
+ if(i < NPROC)
break;
- // cprintf("swtch: nothing to run\n");
+ // cprintf("swtch %d: nothing to run %d %d\n",
+ // cpu(), proc[1].state, proc[2].state);
release_spinlock(&kernel_lock);
acquire_spinlock(&kernel_lock);
+ np = &proc[0];
}
- // XXX this may be too late, should probably save on the way
- // in, in case some other CPU decided to run curproc
- // before we got here. in fact setting state=WAITING and
- // setting these variables had better be atomic w.r.t. other CPUs.
- op->ebp = read_ebp();
- op->esp = read_esp();
-
- cprintf("cpu %d swtch %x -> %x\n", cpu(), op, np);
+ cprintf("cpu %d swtch %x -> %x\n", cpu(), curproc[cpu()], np);
curproc[cpu()] = np;
np->state = RUNNING;
- // XXX callee-saved registers?
-
// h/w sets busy bit in TSS descriptor sometimes, and faults
// if it's set in LTR. so clear tss descriptor busy bit.
np->gdt[SEG_TSS].sd_type = STS_T32A;
diff --git a/proc.h b/proc.h
index 14164db..e371f7d 100644
--- a/proc.h
+++ b/proc.h
@@ -37,3 +37,14 @@ struct proc{
extern struct proc proc[];
extern struct proc *curproc[NCPU];
+
+#define MPSTACK 512
+
+struct cpu {
+ uint8_t apicid; // Local APIC ID
+ int lintr[2]; // Local APIC
+ char mpstack[MPSTACK]; // per-cpu start-up stack, only used to get into main()
+};
+
+extern struct cpu cpus[NCPU];
+extern int ncpu;
diff --git a/syscall.c b/syscall.c
index c27c226..6343531 100644
--- a/syscall.c
+++ b/syscall.c
@@ -91,7 +91,7 @@ sys_pipe()
int
sys_write()
{
- int fd, n;
+ int fd, n, ret;
unsigned addr;
struct proc *p = curproc[cpu()];
@@ -103,13 +103,14 @@ sys_write()
return -1;
if(addr + n > p->sz)
return -1;
- return fd_write(p->fds[fd], p->mem + addr, n);
+ ret = fd_write(p->fds[fd], p->mem + addr, n);
+ return ret;
}
int
sys_read()
{
- int fd, n;
+ int fd, n, ret;
unsigned addr;
struct proc *p = curproc[cpu()];
@@ -121,7 +122,25 @@ sys_read()
return -1;
if(addr + n > p->sz)
return -1;
- return fd_read(p->fds[fd], p->mem + addr, n);
+ ret = fd_read(p->fds[fd], p->mem + addr, n);
+ return ret;
+}
+
+int
+sys_close()
+{
+ int fd;
+ struct proc *p = curproc[cpu()];
+
+ if(fetcharg(0, &fd) < 0)
+ return -1;
+ if(fd < 0 || fd >= NOFILE)
+ return -1;
+ if(p->fds[fd] == 0)
+ return -1;
+ fd_close(p->fds[fd]);
+ p->fds[fd] = 0;
+ return 0;
}
int
@@ -138,6 +157,14 @@ sys_exit()
{
struct proc *p;
struct proc *cp = curproc[cpu()];
+ int fd;
+
+ for(fd = 0; fd < NOFILE; fd++){
+ if(cp->fds[fd]){
+ fd_close(cp->fds[fd]);
+ cp->fds[fd] = 0;
+ }
+ }
cp->state = ZOMBIE;
@@ -227,6 +254,9 @@ syscall()
case SYS_read:
ret = sys_read();
break;
+ case SYS_close:
+ ret = sys_close();
+ break;
default:
cprintf("unknown sys call %d\n", num);
// XXX fault
diff --git a/syscall.h b/syscall.h
index 65d5ced..764b46f 100644
--- a/syscall.h
+++ b/syscall.h
@@ -5,3 +5,4 @@
#define SYS_pipe 5
#define SYS_write 6
#define SYS_read 7
+#define SYS_close 8
diff --git a/trap.c b/trap.c
index 01c2f14..e36540d 100644
--- a/trap.c
+++ b/trap.c
@@ -35,16 +35,28 @@ trap(struct Trapframe *tf)
{
int v = tf->tf_trapno;
+ if(tf->tf_cs == 0x8 && kernel_lock == cpu())
+ cprintf("cpu %d: trap from %x:%x with lock=%d\n",
+ cpu(), tf->tf_cs, tf->tf_eip, kernel_lock);
+
acquire_spinlock(&kernel_lock); // released in trapret in trapasm.S
if(v == T_SYSCALL){
- curproc[cpu()]->tf = tf;
+ struct proc *cp = curproc[cpu()];
+ 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(read_esp() < cp->kstack || read_esp() >= cp->kstack + KSTACKSIZE)
+ panic("trap ret esp wrong");
return;
}
if(v == (IRQ_OFFSET + IRQ_TIMER)){
- curproc[cpu()]->tf = tf;
lapic_timerintr();
return;
}
diff --git a/ulib.c b/ulib.c
index 694501e..d99acdd 100644
--- a/ulib.c
+++ b/ulib.c
@@ -5,6 +5,13 @@ fork()
asm("int $48");
}
+int
+exit()
+{
+ asm("mov $2, %eax");
+ asm("int $48");
+}
+
void
cons_putc(int c)
{
@@ -42,3 +49,10 @@ write(int fd, char *buf, int n)
asm("mov $6, %eax");
asm("int $48");
}
+
+int
+close(int fd)
+{
+ asm("mov $8, %eax");
+ asm("int $48");
+}
diff --git a/usertests.c b/usertests.c
index 62eefda..37540db 100644
--- a/usertests.c
+++ b/usertests.c
@@ -1,22 +1,48 @@
// simple fork and pipe read/write
-char buf[32];
+char buf[2048];
void
pipe1()
{
int fds[2], pid;
+ int seq = 0, i, n, cc, total;
pipe(fds);
- pid = pipe();
+ pid = fork();
if(pid == 0){
- write(fds[1], "xyz", 4);
+ close(fds[0]);
+ for(n = 0; n < 5; n++){
+ for(i = 0; i < 1033; i++)
+ buf[i] = seq++;
+ if(write(fds[1], buf, 1033) != 1033){
+ puts("pipe1 oops 1\n");
+ exit(1);
+ }
+ }
+ exit(0);
} else {
- read(fds[0], buf, sizeof(buf));
- if(buf[0] != 'x' || buf[1] != 'y'){
- puts("pipe1 oops\n");
- return;
+ close(fds[1]);
+ total = 0;
+ cc = 1;
+ while(1){
+ n = read(fds[0], buf, cc);
+ if(n < 1)
+ break;
+ for(i = 0; i < n; i++){
+ if((buf[i] & 0xff) != (seq++ & 0xff)){
+ puts("pipe1 oops 2\n");
+ return;
+ }
+ }
+ total += n;
+ cc = cc * 2;
+ if(cc > sizeof(buf))
+ cc = sizeof(buf);
}
+ if(total != 5 * 1033)
+ puts("pipe1 oops 3\n");
+ close(fds[0]);
}
puts("pipe1 ok\n");
}
diff --git a/x86.h b/x86.h
index b905f83..7bc677f 100644
--- a/x86.h
+++ b/x86.h
@@ -244,6 +244,30 @@ read_esp(void)
return esp;
}
+static __inline uint32_t
+read_esi(void)
+{
+ uint32_t esi;
+ __asm __volatile("movl %%esi,%0" : "=r" (esi));
+ return esi;
+}
+
+static __inline uint32_t
+read_edi(void)
+{
+ uint32_t edi;
+ __asm __volatile("movl %%edi,%0" : "=r" (edi));
+ return edi;
+}
+
+static __inline uint32_t
+read_ebx(void)
+{
+ uint32_t ebx;
+ __asm __volatile("movl %%ebx,%0" : "=r" (ebx));
+ return ebx;
+}
+
static __inline void
cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
{
@@ -280,6 +304,20 @@ 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;