Beispiel #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();
}
Beispiel #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();
}
Beispiel #3
0
static void
do_ret(trapframe *tf, uint32_t cmd) {
  proc *curr = proc_cur();

  // cprintf("node %d return: home: %d\n", net_node, RRNODE(curr->home));
  // This is not this node's home
  if(RRNODE(curr->home) != net_node) {
    // cprintf("sys_ret: %p returning home to %d\n", curr, RRNODE(curr->home));
    // spinlock_release(&curr->lock);
    net_migrate(tf, RRNODE(curr->home), 0);
  }
  proc_ret(tf, 1);
}
Beispiel #4
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
}
Beispiel #5
0
static void
do_get(trapframe *tf, uint32_t cmd)
{ 
  proc *curr = proc_cur();
  spinlock_acquire(&curr->lock);
  // Find child index (includes node number and child number)
  int child_index = tf->regs.edx;
  uint8_t node_number  = child_index >> 8;  // First 8 bits are the node number
  uint8_t child_number = child_index & 0xff;// The last 8 bits for child number

  // cprintf("node %d get: 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_get: %p migrating to %d\n", curr, node_number);
    spinlock_release(&curr->lock);
    net_migrate(tf, node_number, 0);
  }

  proc *child = curr->child[child_number];
  if(!child)
    child = &proc_null;
    // cprintf("No child process %d\n", child_index);
  if(child->state != PROC_STOP)
	proc_wait(curr, child, tf);

  spinlock_release(&curr->lock);
  // cprintf("do_get: current proc: %p, cpu_cur proc: %p\n", curr, cpu_cur()->proc);
  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(child->pdir, src, curr->pdir, dest, size);
    } else if(op == SYS_MERGE) {
        pmap_merge(child->rpdir, child->pdir, src, curr->pdir, dest, size);
    } else
        pmap_remove(curr->pdir, dest, size);
  }

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

    if(cmd & SYS_REGS)
		usercopy(tf, 1, &child->sv, tf->regs.ebx, sizeof(procstate));

	trap_return(tf);	// syscall completed
}
Beispiel #6
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
}
Beispiel #7
0
  static void
do_get(trapframe *tf, uint32_t cmd)
{
  proc *p = proc_cur();
  assert(p->state == PROC_RUN && p->runcpu == cpu_cur());
  //cprintf("GET proc %x eip %x esp %x cmd %x\n", p, tf->eip, tf->esp, cmd);

  spinlock_acquire(&p->lock);

  // Find the named child process; DON'T create if it doesn't exist
  uint32_t cn = tf->regs.edx & 0xff;
  proc *cp = p->child[cn];
  if (!cp)
    cp = &proc_null;

  // 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);

  // Get 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, 1, &cp->sv, tf->regs.ebx, len);
    // Copy child process's trapframe into user space
    procstate *cs = (procstate*) tf->regs.ebx;
    memcpy(cs, &cp->sv, len);
  }
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:
	case SYS_MERGE:
		// 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(p->pdir, dva, size);
			break;
		case SYS_COPY:	// copy from local src to dest in child
			pmap_copy(cp->pdir, sva, p->pdir, dva, size);
			break;
		case SYS_MERGE:	// merge from local src to dest in child
			pmap_merge(cp->rpdir, cp->pdir, sva,
					p->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(p->pdir, dva, size, cmd & SYS_RW))
			panic("pmap_get: no memory to set permissions");
	}

	if (cmd & SYS_SNAP)
		systrap(tf, T_GPFLT, 0);	// only valid for PUT
  trap_return(tf);  // syscall completed
}
Beispiel #8
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
}