Skip to content
Snippets Groups Projects
Commit b548df15 authored by rtm's avatar rtm
Browse files

pre-empt both user and kernel, in clock interrupt

usertest.c tests pre-emption
kill()
parent 5ce9751c
No related branches found
No related tags found
No related merge requests found
......@@ -80,16 +80,22 @@ trap() ought to lgdt on return, since currently only done in swtch()
protect hardware interrupt vectors from user INT instructions?
i'm getting a curious interrupt when jumping into user space. maybe
it's IRQ 0, but it comes at a weird and changing vector (e.g. 119) if
you don't initialize the PIC. why doesn't jos see this? if i
initialize the PIC with IRQ_OFFSET 32, the interrupt arrives at vector
32.
test out-of-fd cases for creating pipe.
test pipe circular buffer
test pipe writer or reader closes while other active or waiting
test exit vs fd reference counts
test write of more than PIPESIZE
test reader goes first vs writer goes first
test streaming of a lot of data
test pipe reader closes then write
test two readers, two writers.
test children being inherited by grandparent &c
kill
sleep()ing for something
running at user level
running in kernel
ooh, the relevant CPU may never get a clock interrupt
should each cpu have its own clock?
where to check?
loops around sleep()
return from any trap
rules about being killed deep inside a system call
test above cases
cli/sti in acquire/release should nest!
in case you acquire two locks
......@@ -17,6 +17,8 @@ void swtch(void);
void sleep(void *);
void wakeup(void *);
void scheduler(void);
void proc_exit(void);
void yield(void);
// swtch.S
struct jmpbuf;
......
......@@ -158,6 +158,4 @@ ktest()
if(p1 == 0)
panic("ktest2");
kfree(p1, PAGE * 20);
cprintf("ktest ok\n");
}
......@@ -66,11 +66,12 @@ main()
ide_init();
// become interruptable
write_eflags(read_eflags() | FL_IF);
sti();
p = newproc();
// load_icode(p, _binary_usertests_start, (unsigned) _binary_usertests_size);
load_icode(p, _binary_userfs_start, (unsigned) _binary_userfs_size);
load_icode(p, _binary_usertests_start, (unsigned) _binary_usertests_size);
//load_icode(p, _binary_userfs_start, (unsigned) _binary_userfs_size);
cprintf("loaded userfs\n");
scheduler();
......
......@@ -184,3 +184,45 @@ wakeup(void *chan)
if(p->state == WAITING && p->chan == chan)
p->state = RUNNABLE;
}
// give up the CPU but stay marked as RUNNABLE
void
yield()
{
if(curproc[cpu()] == 0 || curproc[cpu()]->state != RUNNING)
panic("yield");
curproc[cpu()]->state = RUNNABLE;
swtch();
}
void
proc_exit()
{
struct proc *p;
struct proc *cp = curproc[cpu()];
int fd;
cprintf("exit %x\n", cp);
for(fd = 0; fd < NOFILE; fd++){
if(cp->fds[fd]){
fd_close(cp->fds[fd]);
cp->fds[fd] = 0;
}
}
cp->state = ZOMBIE;
// wake up parent
for(p = proc; p < &proc[NPROC]; p++)
if(p->pid == cp->ppid)
wakeup(p);
// abandon children
for(p = proc; p < &proc[NPROC]; p++)
if(p->ppid == cp->pid)
p->pid = 1;
// switch into scheduler
swtch();
}
......@@ -41,6 +41,7 @@ struct proc{
int pid;
int ppid;
void *chan; // sleep
int killed;
struct fd *fds[NOFILE];
struct Taskstate ts; // only to give cpu address of kernel stack
......
......@@ -20,7 +20,7 @@ acquire_spinlock(uint32_t* lock)
// on a real machine there would be a memory barrier here
if(DEBUG) cprintf("cpu%d: acquiring at %x\n", cpu_id, getcallerpc(&lock));
write_eflags(read_eflags() & ~FL_IF);
cli();
if (*lock == cpu_id)
panic("recursive lock");
......@@ -37,7 +37,7 @@ release_spinlock(uint32_t* lock)
panic("release_spinlock: releasing a lock that i don't own\n");
*lock = LOCK_FREE;
// on a real machine there would be a memory barrier here
write_eflags(read_eflags() | FL_IF);
sti();
}
void
......
......@@ -155,32 +155,7 @@ sys_fork()
int
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;
// wake up parent
for(p = proc; p < &proc[NPROC]; p++)
if(p->pid == cp->ppid)
wakeup(p);
// abandon children
for(p = proc; p < &proc[NPROC]; p++)
if(p->ppid == cp->pid)
p->pid = 1;
// switch into scheduler
swtch();
proc_exit();
return 0;
}
......@@ -250,6 +225,24 @@ sys_block(void)
return 0;
}
int
sys_kill()
{
int pid;
struct proc *p;
fetcharg(0, &pid);
for(p = proc; p < &proc[NPROC]; p++){
if(p->pid == pid && p->state != UNUSED){
p->killed = 1;
if(p->state == WAITING)
p->state = RUNNABLE;
return 0;
}
}
return -1;
}
void
syscall()
{
......@@ -286,6 +279,9 @@ syscall()
case SYS_block:
ret = sys_block();
break;
case SYS_kill:
ret = sys_kill();
break;
default:
cprintf("unknown sys call %d\n", num);
// XXX fault
......
......@@ -7,3 +7,4 @@
#define SYS_read 7
#define SYS_close 8
#define SYS_block 9
#define SYS_kill 10
......@@ -45,6 +45,8 @@ trap(struct Trapframe *tf)
struct proc *cp = curproc[cpu()];
if(cp == 0)
panic("syscall with no proc");
if(cp->killed)
proc_exit();
cp->tf = tf;
syscall();
if(cp != curproc[cpu()])
......@@ -55,11 +57,20 @@ trap(struct Trapframe *tf)
panic("trap ret wrong tf");
if(read_esp() < (unsigned)cp->kstack || read_esp() >= (unsigned)cp->kstack + KSTACKSIZE)
panic("trap ret esp wrong");
if(cp->killed)
proc_exit();
return;
}
if(v == (IRQ_OFFSET + IRQ_TIMER)){
struct proc *cp = curproc[cpu()];
lapic_timerintr();
if(cp){
sti();
if(cp->killed)
proc_exit();
yield();
}
return;
}
if(v == (IRQ_OFFSET + IRQ_IDE)){
......
// simple fork and pipe read/write
char buf[2048];
// simple fork and pipe read/write
void
pipe1()
{
......@@ -47,9 +47,54 @@ pipe1()
puts("pipe1 ok\n");
}
// meant to be run w/ at most two CPUs
void
preempt()
{
int pid1, pid2, pid3;
int pfds[2];
pid1 = fork();
if(pid1 == 0)
while(1)
;
pid2 = fork();
if(pid2 == 0)
while(1)
;
pipe(pfds);
pid3 = fork();
if(pid3 == 0){
close(pfds[0]);
if(write(pfds[1], "x", 1) != 1)
puts("preempt write error");
close(pfds[1]);
while(1)
;
}
close(pfds[1]);
if(read(pfds[0], buf, sizeof(buf)) != 1){
puts("preempt read error");
return;
}
close(pfds[0]);
kill(pid1);
kill(pid2);
kill(pid3);
wait();
wait();
wait();
puts("preempt ok\n");
}
main()
{
puts("usertests starting\n");
pipe1();
//preempt();
while(1)
;
......
......@@ -10,9 +10,11 @@
STUB(fork)
STUB(exit)
STUB(wait)
STUB(cons_putc)
STUB(pipe)
STUB(read)
STUB(write)
STUB(close)
STUB(block)
STUB(kill)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment