summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsc <rsc>2007-08-27 13:34:35 +0000
committerrsc <rsc>2007-08-27 13:34:35 +0000
commitefc12b8e616ed3394468c1802da8e1f39e387cd3 (patch)
tree62340875e823c6784bde20077ccebd51cd5b4fe1
parente1872bb130da5a9b198ca484da8534304ea9fc79 (diff)
downloadxv6-labs-efc12b8e616ed3394468c1802da8e1f39e387cd3.tar.gz
xv6-labs-efc12b8e616ed3394468c1802da8e1f39e387cd3.tar.bz2
xv6-labs-efc12b8e616ed3394468c1802da8e1f39e387cd3.zip
Replace yield system call with sleep.
-rw-r--r--defs.h2
-rw-r--r--syscall.c4
-rw-r--r--syscall.h2
-rw-r--r--sysproc.c17
-rw-r--r--trap.c42
-rw-r--r--trapasm.S2
-rw-r--r--user.h1
-rw-r--r--usys.S2
-rw-r--r--zombie.c6
9 files changed, 52 insertions, 26 deletions
diff --git a/defs.h b/defs.h
index af22433..7af5421 100644
--- a/defs.h
+++ b/defs.h
@@ -139,7 +139,9 @@ void syscall(void);
// trap.c
void idtinit(void);
+extern int ticks;
void tvinit(void);
+extern struct spinlock tickslock;
// number of elements in fixed-size array
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
diff --git a/syscall.c b/syscall.c
index d7cf123..9fed725 100644
--- a/syscall.c
+++ b/syscall.c
@@ -102,10 +102,10 @@ extern int sys_open(void);
extern int sys_pipe(void);
extern int sys_read(void);
extern int sys_sbrk(void);
+extern int sys_sleep(void);
extern int sys_unlink(void);
extern int sys_wait(void);
extern int sys_write(void);
-extern int sys_yield(void);
static int (*syscalls[])(void) = {
[SYS_chdir] sys_chdir,
@@ -124,10 +124,10 @@ static int (*syscalls[])(void) = {
[SYS_pipe] sys_pipe,
[SYS_read] sys_read,
[SYS_sbrk] sys_sbrk,
+[SYS_sleep] sys_sleep,
[SYS_unlink] sys_unlink,
[SYS_wait] sys_wait,
[SYS_write] sys_write,
-[SYS_yield] sys_yield,
};
void
diff --git a/syscall.h b/syscall.h
index 85ea220..f4b7807 100644
--- a/syscall.h
+++ b/syscall.h
@@ -18,4 +18,4 @@
#define SYS_dup 17
#define SYS_getpid 18
#define SYS_sbrk 19
-#define SYS_yield 20
+#define SYS_sleep 20
diff --git a/sysproc.c b/sysproc.c
index 8cf3291..48fbe37 100644
--- a/sysproc.c
+++ b/sysproc.c
@@ -70,8 +70,21 @@ sys_sbrk(void)
}
int
-sys_yield(void)
+sys_sleep(void)
{
- yield();
+ int n, ticks0;
+
+ if(argint(0, &n) < 0)
+ return -1;
+ acquire(&tickslock);
+ ticks0 = ticks;
+ while(ticks - ticks0 < n){
+ if(cp->killed){
+ release(&tickslock);
+ return -1;
+ }
+ sleep(&ticks, &tickslock);
+ }
+ release(&tickslock);
return 0;
}
diff --git a/trap.c b/trap.c
index 217e79d..e045aed 100644
--- a/trap.c
+++ b/trap.c
@@ -6,10 +6,13 @@
#include "x86.h"
#include "traps.h"
#include "syscall.h"
+#include "spinlock.h"
// Interrupt descriptor table (shared by all CPUs).
struct gatedesc idt[256];
extern uint vectors[]; // in vectors.S: array of 256 entry pointers
+struct spinlock tickslock;
+int ticks;
void
tvinit(void)
@@ -19,6 +22,8 @@ tvinit(void)
for(i = 0; i < 256; i++)
SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0);
SETGATE(idt[T_SYSCALL], 0, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER);
+
+ initlock(&tickslock, "time");
}
void
@@ -47,21 +52,14 @@ trap(struct trapframe *tf)
// PAGEBREAK: 10
switch(tf->trapno){
case IRQ_OFFSET + IRQ_TIMER:
- lapic_timerintr();
- cpus[cpu()].nlock--;
- if(cp){
- // 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
- // until it gets to the regular system call return.)
- if((tf->cs&3) == DPL_USER && cp->killed)
- proc_exit();
-
- // Force process to give up CPU and let others run.
- // If locks were held with interrupts on, would need to check nlock.
- if(cp->state == RUNNING)
- yield();
+ if(cpu() == 0){
+ acquire(&tickslock);
+ ticks++;
+ wakeup(&ticks);
+ release(&tickslock);
}
- return;
+ lapic_eoi();
+ break;
case IRQ_OFFSET + IRQ_IDE:
ide_intr();
@@ -75,6 +73,7 @@ trap(struct trapframe *tf)
case IRQ_OFFSET + IRQ_SPURIOUS:
cprintf("spurious interrupt from cpu %d eip %x\n", cpu(), tf->eip);
+ lapic_eoi();
break;
default:
@@ -84,12 +83,23 @@ trap(struct trapframe *tf)
cp->pid, cp->name, tf->trapno, tf->err, cpu(), tf->eip);
proc_exit();
}
-
// Otherwise it's our mistake.
cprintf("unexpected trap %d from cpu %d eip %x\n",
tf->trapno, cpu(), tf->eip);
panic("trap");
}
-
cpus[cpu()].nlock--;
+
+ if(tf->trapno == IRQ_OFFSET + IRQ_TIMER && cp != 0){
+ // 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
+ // until it gets to the regular system call return.)
+ if((tf->cs&3) == DPL_USER && cp->killed)
+ proc_exit();
+
+ // Force process to give up CPU and let others run.
+ // If locks were held with interrupts on, would need to check nlock.
+ if(cp->state == RUNNING)
+ yield();
+ }
}
diff --git a/trapasm.S b/trapasm.S
index ac96413..87a832a 100644
--- a/trapasm.S
+++ b/trapasm.S
@@ -3,7 +3,7 @@
.globl trapret1
.globl alltraps
-.set SEG_KDATA_SEL 0x10 # selector for SEG_KDATA
+.set SEG_KDATA_SEL, 0x10 # selector for SEG_KDATA
# vectors.S sends all traps here.
alltraps:
diff --git a/user.h b/user.h
index 1bbe2fd..c3ee675 100644
--- a/user.h
+++ b/user.h
@@ -18,6 +18,7 @@ int chdir(char*);
int dup(int);
int getpid();
char* sbrk(int);
+int sleep(int);
// ulib.c
int stat(char*, struct stat*);
diff --git a/usys.S b/usys.S
index 210774d..380cb91 100644
--- a/usys.S
+++ b/usys.S
@@ -27,4 +27,4 @@ STUB(chdir)
STUB(dup)
STUB(getpid)
STUB(sbrk)
-STUB(yield)
+STUB(sleep)
diff --git a/zombie.c b/zombie.c
index 883ea75..07ad798 100644
--- a/zombie.c
+++ b/zombie.c
@@ -1,4 +1,5 @@
-// Create a zombie process.
+// Create a zombie process that
+// must be reparented at exit.
#include "types.h"
#include "stat.h"
@@ -10,7 +11,6 @@ main(void)
int i;
if(fork() > 0)
- for(i=0; i<10; i++)
- yield();
+ sleep(5); // Let child exit before parent.
exit();
}