Example #1
0
/**
 * Basically, This function serves procs blocked due
 * to a lock or semaphore..etc
 * the first proc is marked as ready and pushed into ready procs
 */
void
wait_wakeup(struct Proc_List *list)
{

    proc_t *blocked;
    blocked = LIST_FIRST(list);
    blocked->status = RUNNABLE;
    LIST_REMOVE(blocked, wait_link);
    proc_ready(blocked);
    // I shall not schedule immediately
    /*
    	proc_t *proc, *nproc;
    	LIST_FOREACH(proc, &waiting_procs, wait_link)
    	{
    		if(proc->blocking_id == bproc->id)
    		{
    			nproc = proc;
    			proc->blocking_id = 0;
    			proc->status = RUNNABLE;
    			proc_ready(proc);
    			break; // sorry fellas, only one at a time..
    		}
    	}
    	LIST_FOREACH(proc, &waiting_procs, wait_link)
    	{
    		if(proc->blocking_id == bproc->id)
    		{
    			proc->blocking_id = nproc->id;
    		}
    	}
    	return;
    */
}
Example #2
0
// Check to see if any input is available for the root process
// and if the root process is waiting for it, and if so, wake the process.
void
file_wakeroot(void)
{
	spinlock_acquire(&file_lock);
	if (proc_root && proc_root->state == PROC_STOP)
		proc_ready(proc_root);
	spinlock_release(&file_lock);
}
Example #3
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();
}
Example #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();
}
Example #5
0
static void
do_put(trapframe *tf, uint32_t cmd)
{
	proc *curr = proc_cur();
  spinlock_acquire(&curr->lock);

  uint32_t child_index = tf->regs.edx;
  uint8_t node_number  = child_index >> 8 & 0xff;  // First 8 bits are the node number
  uint8_t child_number = child_index & 0xff;// The last 8 bits for child number

  // cprintf("node %d put: dest node: %d, child: %d, home node: %d\n", 
  //   net_node, node_number, child_number, RRNODE(curr->home));

  // When migrating, make sure to adjust eip! => entry == 0
  // Trying to migrate home and this is not its home
  if(node_number == 0) {
    node_number = RRNODE(curr->home);
  }
  if (net_node != node_number) {
    // cprintf("sys_put: %p migrating to %d\n", curr, RRNODE(curr->home));
    spinlock_release(&curr->lock);
    net_migrate(tf, node_number, 0);
  }

  proc *child = curr->child[child_number];

  if(!child) 
    child = proc_alloc(curr, child_number);
  if(child->state != PROC_STOP)
    proc_wait(curr, child, tf);
  
  spinlock_release(&curr->lock);

  // cprintf("do_put: current proc: %p, cpu_cur proc: %p\n", curr, cpu_cur()->proc);
	if(cmd & SYS_REGS) {
		usercopy(tf, 0, &child->sv, tf->regs.ebx, sizeof(procstate));
    child->sv.tf.ds = CPU_GDT_UDATA | 3;
		child->sv.tf.es = CPU_GDT_UDATA | 3;
		child->sv.tf.cs = CPU_GDT_UCODE | 3;
		child->sv.tf.ss = CPU_GDT_UDATA | 3;
		child->sv.tf.eflags &= FL_USER;
		child->sv.tf.eflags |= FL_IF;
  }
  uint32_t dest = tf->regs.edi; //syscall.h
  uint32_t size = tf->regs.ecx;
  uint32_t src = tf->regs.esi;

  if(cmd & SYS_MEMOP) {
    int op = cmd & SYS_MEMOP;
    // Check if the destination range is okay
    if(dest < VM_USERLO || dest > VM_USERHI || dest + size > VM_USERHI)
        systrap(tf, T_GPFLT, 0);
    if(op == SYS_COPY) {
      // we have to check the source too
      if(src < VM_USERLO || src > VM_USERHI || src + size > VM_USERHI)
          systrap(tf, T_GPFLT, 0);
      pmap_copy(curr->pdir, src, child->pdir, dest, size);
    } else
      pmap_remove(child->pdir, dest, size);
  }

	if(cmd & SYS_PERM)
		pmap_setperm(child->pdir, dest, size, cmd & SYS_RW);

	if(cmd & SYS_SNAP)
    // copy pdir to rpdir
    pmap_copy(child->pdir, VM_USERLO, child->rpdir, VM_USERLO, VM_USERHI-VM_USERLO);

	if(cmd & SYS_START)
		proc_ready(child);

	trap_return(tf);	// syscall completed
}
Example #6
0
static void
do_put(trapframe *tf, uint32_t cmd)
{
  proc *p = proc_cur();
  assert(p->state == PROC_RUN && p->runcpu == cpu_cur());
  cprintf("PUT proc %x eip %x esp %x cmd %x\n", p, tf->eip, tf->esp, cmd);

  spinlock_acquire(&p->lock);

  // Find the named child process; create if it doesn't exist
  uint32_t cn = tf->regs.edx & 0xff;
  proc *cp = p->child[cn];
  if (!cp) {
    cp = proc_alloc(p, cn);
    if (!cp)  // XX handle more gracefully
      panic("sys_put: no memory for child");
  }

  // Synchronize with child if necessary.
  if (cp->state != PROC_STOP)
    proc_wait(p, cp, tf);

  // Since the child is now stopped, it's ours to control;
  // we no longer need our process lock -
  // and we don't want to be holding it if usercopy() below aborts.
  spinlock_release(&p->lock);

  // Put child's general register state
  if (cmd & SYS_REGS) {
    int len = offsetof(procstate, fx);  // just integer regs
    if (cmd & SYS_FPU) len = sizeof(procstate); // whole shebang

  usercopy(tf,0,&cp->sv, tf->regs.ebx, len);
    // Copy user's trapframe into child process
    procstate *cs = (procstate*) tf->regs.ebx;
    memcpy(&cp->sv, cs, len);

    // Make sure process uses user-mode segments and eflag settings
    cp->sv.tf.ds = CPU_GDT_UDATA | 3;
    cp->sv.tf.es = CPU_GDT_UDATA | 3;
    cp->sv.tf.cs = CPU_GDT_UCODE | 3;
    cp->sv.tf.ss = CPU_GDT_UDATA | 3;
    cp->sv.tf.eflags &= FL_USER;
    cp->sv.tf.eflags |= FL_IF;  // enable interrupts
  }
	uint32_t sva = tf->regs.esi;
	uint32_t dva = tf->regs.edi;
	uint32_t size = tf->regs.ecx;
	switch (cmd & SYS_MEMOP) {
	case 0:	// no memory operation
		break;
	case SYS_COPY:
		// validate source region
		if (PTOFF(sva) || PTOFF(size)
				|| sva < VM_USERLO || sva > VM_USERHI
				|| size > VM_USERHI-sva)
			systrap(tf, T_GPFLT, 0);
		// fall thru...
	case SYS_ZERO:
		// validate destination region
		if (PTOFF(dva) || PTOFF(size)
				|| dva < VM_USERLO || dva > VM_USERHI
				|| size > VM_USERHI-dva)
			systrap(tf, T_GPFLT, 0);

		switch (cmd & SYS_MEMOP) {
		case SYS_ZERO:	// zero memory and clear permissions
			pmap_remove(cp->pdir, dva, size);
			break;
		case SYS_COPY:	// copy from local src to dest in child
			pmap_copy(p->pdir, sva, cp->pdir, dva, size);
			break;
		}
		break;
	default:
		systrap(tf, T_GPFLT, 0);
	}

	if (cmd & SYS_PERM) {
		// validate destination region
		if (PGOFF(dva) || PGOFF(size)
				|| dva < VM_USERLO || dva > VM_USERHI
				|| size > VM_USERHI-dva)
			systrap(tf, T_GPFLT, 0);
		if (!pmap_setperm(cp->pdir, dva, size, cmd & SYS_RW))
			panic("pmap_put: no memory to set permissions");
	}

	if (cmd & SYS_SNAP)	// Snapshot child's state
		pmap_copy(cp->pdir, VM_USERLO, cp->rpdir, VM_USERLO,
				VM_USERHI-VM_USERLO);

  // Start the child if requested
  if (cmd & SYS_START)
    proc_ready(cp);

  trap_return(tf);  // syscall completed
}
Example #7
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
}