Esempio n. 1
0
// Put the current process to sleep by "returning" to its parent process.
// Used both when a process calls the SYS_RET system call explicitly,
// and when a process causes an unhandled trap in user mode.
// The 'entry' parameter is as in proc_save().
void gcc_noreturn
proc_ret(trapframe *tf, int entry)
{
	proc *cp = proc_cur();
	proc *p = cp->parent;
	
	if (p == NULL){
		if (tf->trapno != T_SYSCALL){
			trap_print(tf);
			panic("no parent to reflect trap");
		}
		file_io(tf);
		cprintf("fileio done\n");
	}

	spinlock_acquire(&cp->lock);
	cp->state = PROC_STOP;
	cp->runcpu = NULL;
	proc_save(cp, tf, entry);
	spinlock_release(&cp->lock);
	
	spinlock_acquire(&p->lock);
	if (p->state == PROC_WAIT && p->waitchild == cp) {
		p->waitchild = NULL;
		proc_run(p);
	}
	spinlock_release(&p->lock);
	
	proc_sched();
}
Esempio n. 2
0
// Yield the current CPU to another ready process.
// Called while handling a timer interrupt.
void gcc_noreturn
proc_yield(trapframe *tf)
{
	//proc * p = cpu_cur()->proc;
	proc *p = proc_cur();
	proc_save(p, tf, -1); // -1 because timer interrupt
	proc_ready(p);
	proc_sched();
}
Esempio n. 3
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)
{
	cprintf("proc_wait parent=%p child=%p\n", p, cp);
	p->state = PROC_WAIT;
	p->waitchild = cp;
	proc_save(p, tf, 0);
	spinlock_release(&(p->lock));
	proc_sched();
}
Esempio n. 4
0
// Yield the current CPU to another ready process.
// Called while handling a timer interrupt.
void gcc_noreturn
proc_yield(trapframe *tf)
{
	proc *p;
	p = cpu_cur()->proc;
	spinlock_acquire(&(p->lock));
	proc_save(p, tf, -1);
	spinlock_release(&(p->lock));
	proc_ready(p);
	proc_sched();
}
Esempio n. 5
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
}
Esempio n. 6
0
// Put the current process to sleep by "returning" to its parent process.
// Used both when a process calls the SYS_RET system call explicitly,
// and when a process causes an unhandled trap in user mode.
// The 'entry' parameter is as in proc_save().
void gcc_noreturn
proc_ret(trapframe *tf, int entry)
{
	proc *p;
	proc *cp;
	cp = cpu_cur()->proc;
	p = cp->parent;
	cprintf("proc_ret child=%p parent=%p\n", cp, p);
	spinlock_acquire(&(p->lock));
	spinlock_acquire(&(cp->lock));
	cp->state = PROC_STOP;
	proc_save(cp, tf, entry);
	spinlock_release(&(cp->lock));
	if(p->state == PROC_WAIT && p->waitchild == cp) {
		proc_run(p);
	}
	spinlock_release(&(p->lock));
	proc_sched();
}
Esempio n. 7
0
// Called from proc_ret() when the root process "returns" -
// this function performs any new output the root process requested,
// or if it didn't request output, puts the root process to sleep
// waiting for input to arrive from some I/O device.
void
file_io(trapframe *tf)
{
	proc *cp = proc_cur();
	assert(cp == proc_root);	// only root process should do this!

	// Note that we don't need to bother protecting ourselves
	// against memory access traps while accessing user memory here,
	// because we consider the root process a special, "trusted" process:
	// the whole system goes down anyway if the root process goes haywire.
	// This is very different from handling system calls
	// on behalf of arbitrary processes that might be buggy or evil.

	// Perform I/O with whatever devices we have access to.
	bool iodone = 0;
	iodone |= cons_io();

	// Has the root process exited?
	if (files->exited) {
		cprintf("root process exited with status %d\n", files->status);
		done();
	}

	//cprintf("iodone = %d\n", iodone);

	// We successfully did some I/O, let the root process run again.
	if (iodone)
		trap_return(tf);

	// No I/O ready - put the root process to sleep waiting for I/O.
	spinlock_acquire(&file_lock);
	cp->state = PROC_STOP;		// we're becoming stopped
	cp->runcpu = NULL;		// no longer running
	proc_save(cp, tf, 1);		// save process's state
	spinlock_release(&file_lock);

	proc_sched();			// go do something else
}
Esempio n. 8
0
// Called first from entry.S on the bootstrap processor,
// and later from boot/bootother.S on all other processors.
// As a rule, "init" functions in PIOS are called once on EACH processor.
void
init(void)
{
	extern char start[], edata[], end[];

	// Before anything else, complete the ELF loading process.
	// Clear all uninitialized global data (BSS) in our program,
	// ensuring that all static/global variables start out zero.
	if (cpu_onboot())
		memset(edata, 0, end - edata);

	// Initialize the console.
	// Can't call cprintf until after we do this!
	cons_init();

  	extern uint8_t _binary_obj_boot_bootother_start[],
    	_binary_obj_boot_bootother_size[];

  	uint8_t *code = (uint8_t*)lowmem_bootother_vec;
  	memmove(code, _binary_obj_boot_bootother_start, (uint32_t) _binary_obj_boot_bootother_size);

	// Lab 1: test cprintf and debug_trace
	cprintf("1234 decimal is %o octal!\n", 1234);
	debug_check();

	// Initialize and load the bootstrap CPU's GDT, TSS, and IDT.
	cpu_init();
	trap_init();

	// Physical memory detection/initialization.
	// Can't call mem_alloc until after we do this!
	mem_init();

	// Lab 2: check spinlock implementation
	if (cpu_onboot())
		spinlock_check();

	// Initialize the paged virtual memory system.
	pmap_init();

	// Find and start other processors in a multiprocessor system
	mp_init();		// Find info about processors in system
	pic_init();		// setup the legacy PIC (mainly to disable it)
	ioapic_init();		// prepare to handle external device interrupts
	lapic_init();		// setup this CPU's local APIC
	cpu_bootothers();	// Get other processors started
//	cprintf("CPU %d (%s) has booted\n", cpu_cur()->id,
//		cpu_onboot() ? "BP" : "AP");

	file_init();		// Create root directory and console I/O files

	// Lab 4: uncomment this when you can handle IRQ_SERIAL and IRQ_KBD.
	//cons_intenable();	// Let the console start producing interrupts

	// Initialize the process management code.
	proc_init();
	// Initialize the process management code.
	proc_init();


	if(!cpu_onboot())
		proc_sched();
 	proc *root = proc_root = proc_alloc(NULL,0);
  
  	elfhdr *ehs = (elfhdr *)ROOTEXE_START;
  	assert(ehs->e_magic == ELF_MAGIC);

  	proghdr *phs = (proghdr *) ((void *) ehs + ehs->e_phoff);
  	proghdr *ep = phs + ehs->e_phnum;

  	for (; phs < ep; phs++)
	{
    		if (phs->p_type != ELF_PROG_LOAD)
      		continue;

    		void *fa = (void *) ehs + ROUNDDOWN(phs->p_offset, PAGESIZE);
    		uint32_t va = ROUNDDOWN(phs->p_va, PAGESIZE);
    		uint32_t zva = phs->p_va + phs->p_filesz;
    		uint32_t eva = ROUNDUP(phs->p_va + phs->p_memsz, PAGESIZE);

    		uint32_t perm = SYS_READ | PTE_P | PTE_U;
    		if(phs->p_flags & ELF_PROG_FLAG_WRITE) perm |= SYS_WRITE | PTE_W;

    		for (; va < eva; va += PAGESIZE, fa += PAGESIZE) 
		{
    			pageinfo *pi = mem_alloc(); assert(pi != NULL);
      			if(va < ROUNDDOWN(zva, PAGESIZE))
        			memmove(mem_pi2ptr(pi), fa, PAGESIZE);
      			else if (va < zva && phs->p_filesz)
			{
      				memset(mem_pi2ptr(pi),0, PAGESIZE);
      				memmove(mem_pi2ptr(pi), fa, zva-va);
      			} 
			else
        			memset(mem_pi2ptr(pi), 0, PAGESIZE);

      			pte_t *pte = pmap_insert(root->pdir, pi, va, perm);
      			assert(pte != NULL);
      		}
      }

      root->sv.tf.eip = ehs->e_entry;
      root->sv.tf.eflags |= FL_IF;

      pageinfo *pi = mem_alloc(); assert(pi != NULL);
      pte_t *pte = pmap_insert(root->pdir, pi, VM_STACKHI-PAGESIZE,
      SYS_READ | SYS_WRITE | PTE_P | PTE_U | PTE_W);

      assert(pte != NULL);
      root->sv.tf.esp = VM_STACKHI;

      proc_ready(root);
      proc_sched();
	// Initialize the I/O system.

	// Lab 1: change this so it enters user() in user mode,
	// running on the user_stack declared above,
	// instead of just calling user() directly.
	user(); // FIXME: Maybe get rid of this
}