Beispiel #1
0
void spinlock_check()
{
	const int NUMLOCKS=10;
	const int NUMRUNS=5;
	int i,j,run;
	const char* file = "spinlock_check";
	spinlock locks[NUMLOCKS];

	// Initialize the locks
	for(i=0;i<NUMLOCKS;i++) spinlock_init_(&locks[i], file, 0);
	// Make sure that all locks have CPU set to NULL initially
	for(i=0;i<NUMLOCKS;i++) assert(locks[i].cpu==NULL);
	// Make sure that all locks have the correct debug info.
	for(i=0;i<NUMLOCKS;i++) assert(locks[i].file==file);

	for (run=0;run<NUMRUNS;run++) 
	{
		// Lock all locks
		for(i=0;i<NUMLOCKS;i++)
			spinlock_godeep(i, &locks[i]);

		// Make sure that all locks have the right CPU
		for(i=0;i<NUMLOCKS;i++)
			assert(locks[i].cpu == cpu_cur());
		// Make sure that all locks have holding correctly implemented.
		for(i=0;i<NUMLOCKS;i++)
			assert(spinlock_holding(&locks[i]) != 0);
		// Make sure that top i frames are somewhere in godeep.
		for(i=0;i<NUMLOCKS;i++) 
		{
			for(j=0; j<=i && j < DEBUG_TRACEFRAMES ; j++) 
			{
				assert(locks[i].eips[j] >=
					(uint32_t)spinlock_godeep);
				assert(locks[i].eips[j] <
					(uint32_t)spinlock_godeep+100);
			}
		}

		// Release all locks
		for(i=0;i<NUMLOCKS;i++) spinlock_release(&locks[i]);
		// Make sure that the CPU has been cleared
		for(i=0;i<NUMLOCKS;i++) assert(locks[i].cpu == NULL);
		for(i=0;i<NUMLOCKS;i++) assert(locks[i].eips[0]==0);
		// Make sure that all locks have holding correctly implemented.
		for(i=0;i<NUMLOCKS;i++) assert(spinlock_holding(&locks[i]) == 0);
	}
	cprintf("spinlock_check() succeeded!\n");
}
Beispiel #2
0
// Save the current process's state before switching to another process.
// Copies trapframe 'tf' into the proc struct,
// and saves any other relevant state such as FPU state.
// The 'entry' parameter is one of:
//	-1	if we entered the kernel via a trap before executing an insn
//	0	if we entered via a syscall and must abort/rollback the syscall
//	1	if we entered via a syscall and are completing the syscall
void
proc_save(proc *p, trapframe *tf, int entry)
{
	if(!spinlock_holding(&(p->lock))) panic("not holding p->lock");
	// memcpy(&(p->sv.tf), tf, sizeof(p->sv.tf));
	p->sv.tf = *tf;
	if(entry == 0) p->sv.tf.eip -= 2;
}
Beispiel #3
0
// Release the lock.
void
spinlock_release(struct spinlock *lk)
{
    if(!spinlock_holding(lk))
        panic("Not holding lock");
    lk->cpu = NULL;
    lk->eips[0] = 0;
    xchg(&(lk->locked), 0);
}
Beispiel #4
0
// Acquire the lock.
// Loops (spins) until the lock is acquired.
// Holding a lock for a long time may cause
// other CPUs to waste time spinning to acquire it.
void
spinlock_acquire(struct spinlock *lk)
{
    if(spinlock_holding(lk))
        panic("Already holding lock.");
    while(xchg(&(lk->locked), 1) != 0)
        pause();
    lk->cpu = cpu_cur();
    debug_trace(read_ebp(), lk->eips);
}
Beispiel #5
0
// Switch to and run a specified process, which must already be locked.
void gcc_noreturn
proc_run(proc *p)
{
	// cprintf("proc_run %p\n", p);
	if(!spinlock_holding(&(p->lock))) panic("should have p->lock.\n");
	p->runcpu = cpu_cur();
	p->state = PROC_RUN;
	cpu_cur()->proc = p;
	spinlock_release(&(p->lock));

	trap_return(&(p->sv.tf));
}
Beispiel #6
0
// Go to sleep waiting for a given child process to finish running.
// Parent process 'p' must be running and locked on entry.
// The supplied trapframe represents p's register state on syscall entry.
void gcc_noreturn
proc_wait(proc *p, proc *cp, trapframe *tf)
{
	//assert(proc_cur() == p);
	assert(spinlock_holding(&p->lock));
	proc_save(p, tf, 0); //saves the trapframe in the parent, roll back the INT instruction (entry of 0)
	p->state = PROC_WAIT;
	p->runcpu = NULL;
	p->waitchild = cp;
	spinlock_release(&p->lock); //release the lock on the parent
	proc_sched(); //runs scheduler again
}
Beispiel #7
0
//
// Allocates a physical page from the page free list.
// Does NOT set the contents of the physical page to zero -
// the caller must do that if necessary.
//
// RETURNS 
//   - a pointer to the page's pageinfo struct if successful
//   - NULL if no available physical pages.
//
// Hint: pi->refs should not be incremented 
// Hint: be sure to use proper mutual exclusion for multiprocessor operation.
pageinfo *
mem_alloc(void)
{
  if(!spinlock_holding(&_freelist_lock));
    spinlock_acquire(&_freelist_lock);
	pageinfo *p = mem_freelist;
	if(p != NULL)
		mem_freelist = p->free_next;	// Remove page from free list
	p->home = 0;
	p->shared = 0;
  spinlock_release(&_freelist_lock);
  return p;
}
Beispiel #8
0
// `High'-level console I/O.  Used by readline and cprintf.
void
cputs(const char *str)
{
	if (read_cs() & 3)
		return sys_cputs(str);	// use syscall from user mode

	// Hold the console spinlock while printing the entire string,
	// so that the output of different cputs calls won't get mixed.
	// Implement ad hoc recursive locking for debugging convenience.
	bool already = spinlock_holding(&cons_lock);
	if (!already)
		spinlock_acquire(&cons_lock);

	char ch;
	while (*str)
		cons_putc(*str++);

	if (!already)
		spinlock_release(&cons_lock);
}
Beispiel #9
0
// Switch to and run a specified process, which must already be locked.
void gcc_noreturn
proc_run(proc *p)
{
	if (!spinlock_holding(&p->lock)) panic("proc_run without lock");

	//if (p->parent) cprintf("running child\n");
	//	else cprintf("running root\n");
	
	p->state = PROC_RUN;
	p->runcpu = cpu_cur();
	cpu_cur()->proc = p;
	
	// Enable interrupts (for preemption)
	p->sv.tf.eflags |= (1 << 9);
	p->sv.tf.ds = CPU_GDT_UDATA | 3;
	p->sv.tf.es = CPU_GDT_UDATA | 3;
	p->sv.tf.cs = CPU_GDT_UCODE | 3;
	p->sv.tf.ss = CPU_GDT_UDATA | 3;
	lcr3 (mem_phys(p->pdir));
	
	spinlock_release(&p->lock);
	
	trap_return(&p->sv.tf);
}