so we need recursive locks?
or you must hold the lock to call wakeup?
-if locks contain proc *, they can't be used at interrupt time
- only proc_table_lock will be used at interrupt time?
- maybe it doesn't matter if we use curproc?
-
in general, the table locks protect both free-ness and
public variables of table elements
in many cases you can use table elements w/o a lock
e.g. if you are the process, or you are using an fd
-why can't i get a lock in console code?
- always triple fault
- because release turns on interrupts!
- a bad idea very early in main()
- but mp_init() calls cprintf
-
lock code shouldn't call cprintf...
-ide_init doesn't work now?
-and IOAPIC: read from unsupported address
- when running pre-empt user test
- so maybe something wrong with clock interrupts
- no! if one cpu holds lock w/ curproc0=,
- then another cpu can take it, it looks like
- a recursive acquire()
+
+nasty hack to allow locks before first process,
+ and to allow them in interrupts when curproc may be zero
+
+race between release and sleep in sys_wait()
+race between sys_exit waking up parent and setting state=ZOMBIE
{
struct proc *p = curproc[cpu()];
if(p == 0)
- panic("swtch");
+ panic("swtch no proc");
+ if(p->locks != 0)
+ panic("swtch w/ locks");
p->newstate = newstate; // basically an argument to scheduler()
if(setjmp(&p->jmpbuf) == 0)
longjmp(&cpus[cpu()].jmpbuf);
struct proc *p;
acquire(&proc_table_lock);
- for(p = proc; p < &proc[NPROC]; p++)
- if(p->state == WAITING && p->chan == chan)
+ for(p = proc; p < &proc[NPROC]; p++){
+ if(p->state == WAITING && p->chan == chan){
p->state = RUNNABLE;
+ }
+ }
release(&proc_table_lock);
}
struct proc *cp = curproc[cpu()];
int fd;
- cprintf("exit %x\n", cp);
+ cprintf("exit %x pid %d ppid %d\n", cp, cp->pid, cp->ppid);
for(fd = 0; fd < NOFILE; fd++){
if(cp->fds[fd]){
if(p->ppid == cp->pid)
p->pid = 1;
- acquire(&proc_table_lock);
+ release(&proc_table_lock);
// switch into scheduler
swtch(ZOMBIE);
void
sti(void)
{
- if(cpus[cpu()].clis < 1){
- cprintf("cpu %d clis %d\n", cpu(), cpus[cpu()].clis);
+ if(cpus[cpu()].clis < 1)
panic("sti");
- }
cpus[cpu()].clis -= 1;
if(cpus[cpu()].clis < 1)
__asm __volatile("sti");
int ppid;
void *chan; // sleep
int killed;
+ int locks; // # of locks currently held
struct fd *fds[NOFILE];
struct Taskstate ts; // only to give cpu address of kernel stack
void
acquire(struct spinlock * lock)
{
+ struct proc *cp = curproc[cpu()];
unsigned who;
- if(curproc[cpu()])
- who = (unsigned) curproc[cpu()];
+ if(cp)
+ who = (unsigned) cp;
else
who = cpu() + 1;
lock->who = who;
}
+ if(cp)
+ cp->locks += 1;
+
if(DEBUG) cprintf("cpu%d: acquired at %x\n", cpu(), getcallerpc(&lock));
}
void
release(struct spinlock * lock)
{
+ struct proc *cp = curproc[cpu()];
unsigned who;
- if(curproc[cpu()])
- who = (unsigned) curproc[cpu()];
+ if(cp)
+ who = (unsigned) cp;
else
who = cpu() + 1;
panic("release");
lock->count -= 1;
+ if(cp)
+ cp->locks -= 1;
if(lock->count < 1){
lock->who = 0;
cmpxchg(1, 0, &lock->locked);
struct proc *cp = curproc[cpu()];
lapic_timerintr();
if(cp){
+ if(cpus[cpu()].clis != 0)
+ panic("trap clis > 0");
+ cpus[cpu()].clis += 1;
sti();
if(cp->killed)
proc_exit();
}
return;
}
+
if(v == (IRQ_OFFSET + IRQ_IDE)){
ide_intr();
return;
main()
{
puts("usertests starting\n");
- //pipe1();
- preempt();
+ pipe1();
+ //preempt();
while(1)
;