Exemplo 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();
}
Exemplo 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();
}
Exemplo 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();
}
Exemplo 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();
}
Exemplo 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
}
Exemplo n.º 6
0
void *proc_mmap(struct proc *p, int prot, int flags) {
	void *addr = NULL;
	char *code = "\xcd\x80\x00\x00\x00\x00\x00\x00";
	proc_save(p);
	p->regs = p->oregs;
	p->regs.rax = SYS_mmap; 
	p->regs.rdi = 0;
	p->regs.rsi = 4;
	p->regs.rdx = prot;
	p->regs.r10 = flags;
	p->regs.r8 = -1;
	p->regs.r9 = 0;
	p->regs.rip = EBASE;
	char savebuf[8] = {0};
	int n = proc_read(p, (void*)EBASE, savebuf, 8);
	if (n != 8) {
		perror("read");
		exit(1);
	}
	n = proc_write(p, (void*)EBASE, code, 8);
	if (n != 8) {
		perror("write");
		exit(1);
	}
	proc_regs(p, 1);
	printf("syscall mmap begin...\n");
	ptrace(PTRACE_SYSCALL, p->pid, NULL, NULL);
	while (1) {
		proc_wait(p);
		if (p->stat != SYSCALL_STOP) {
			goto cont;
		}
		proc_regs(p, 0);
		if (p->regs.orig_rax == SYS_mmap) {
			if (p->insys == 0) {
				p->insys = 1;
			} else if (p->insys == 1) {
				addr = (void *)p->regs.rax;
				p->insys = 0;
				break;
			}
		}
cont:
		ptrace(PTRACE_SYSCALL, p->pid, NULL, NULL);
	}
	proc_write(p, (void *)EBASE, savebuf, 4);
	proc_restore(p);
	return addr;
}
Exemplo n.º 7
0
int proc_mprotect(struct proc *p, void *addr, int prot) {
	int ret = 0;
	unsigned long err = 0;
	char *code = "\x0f\x05\x00\x00\x00\x00\x00\x00";
	proc_save(p);
	p->regs = p->oregs;
	p->regs.rax = SYS_mprotect; 
	p->regs.rdi = (unsigned long)addr;
	p->regs.rsi = 0x1000;
	p->regs.rdx = prot;
	p->regs.rip = EBASE;
	char savebuf[8] = {0};
	int n = proc_read(p, (void*)EBASE, savebuf, 8);
	if (n != 8) {
		perror("read");
		exit(1);
	}
	n = proc_write(p, (void*)EBASE, code, 8);
	if (n != 8) {
		perror("write");
		exit(1);
	}
	proc_regs(p, 1);
	ptrace(PTRACE_SYSCALL, p->pid, NULL, NULL);
	while (1) {
		proc_wait(p);
		if (p->stat != SYSCALL_STOP) {
			printf("not syscall\n");
			goto cont;
		}
		proc_regs(p, 0);
		if (p->regs.orig_rax == SYS_mprotect) {
			if (p->insys == 0) {
				p->insys = 1;
			} else if (p->insys == 1) {
				err = p->regs.rax;
				p->insys = 0;
				break;
			}
		}
cont:
		ptrace(PTRACE_SYSCALL, p->pid, NULL, NULL);
	}
	proc_write(p, (void *)EBASE, savebuf, 8);
	proc_restore(p);
	printf("%d, %s\n", err, strerror(-err));
	return ret;
}
Exemplo n.º 8
0
void proc_exit(struct proc *p, int no) {
	char *code = "\xcd\x80\x00\x00\x00\x00\x00\x00";
	proc_save(p);
	p->regs = p->oregs;
	p->regs.rax = SYS_exit;
	p->regs.rdi = no;
	p->regs.rip = EBASE;
	char savebuf[8] = {0};
	int n = proc_read(p, (void*)EBASE, savebuf, 8);
	if (n != 8) {
		perror("read");
		exit(1);
	}
	proc_write(p, (void*)EBASE, code, 8);
	proc_regs(p, 1);
	printf("syscall exit begin...\n");
	ptrace(PTRACE_SYSCALL, p->pid, NULL, NULL);
	while (1) {
		proc_wait(p);
		if (p->stat == DEAD) {
			printf("%p: ", p->status);
			if (WIFEXITED(p->status)) {
				printf("exit code %d\n", WEXITSTATUS(p->status));
			} else if (WIFSIGNALED(p->status)) {
				printf("signal %d\n", WTERMSIG(p->status));
			}
			break;
		}
		if (p->stat != SYSCALL_STOP) {
			goto cont;
		}
		proc_regs(p, 0);
		if (p->regs.orig_rax == SYS_exit) {
			if (p->insys == 0) {
				p->insys = 1;
			} else if (p->insys == 1) {
				p->insys = 0;
				break;
			}
		}
cont:
		ptrace(PTRACE_SYSCALL, p->pid, NULL, NULL);
	}
}
Exemplo n.º 9
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();
}
Exemplo n.º 10
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
}