/*
 * Load program "progname" and start running it in usermode.
 * Does not return except on error.
 *
 * Calls vfs_open on progname and thus may destroy it.
 */
int
runprogram(char *progname, char **argv, unsigned long argc)
{
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;
	pid_t pidRetVal;


	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, &v);
	if (result) {
		return result;
	}

	/* We should be a new thread. */
	assert(curthread->t_vmspace == NULL);

	/* Create filetable for process*/
	curthread->ft = create_process_filetable();
	if(curthread->ft == NULL)
	{
		vfs_close(v);
		return ENOMEM;
	}
	
	/* Initialize STDIN, STDOUT, STDERR */
	struct ft_node* standardIn = create_ft_node();
	struct ft_node* standardOut = create_ft_node();
	struct ft_node* standardErr = create_ft_node();

	char console1[] = "con:";
	result = vfs_open(console1, O_RDONLY, &standardIn->v);
	if(result)
	{
		kprintf("Cannot open STDIN\n");
		vfs_close(v);
		return result;
	}
	standardIn->mode = O_RDONLY;
	array_add(curthread->ft->file_descriptors, standardIn);

	char console2[] = "con:";
	result = vfs_open(console2, O_WRONLY, &standardOut->v);
	if(result)
	{
		kprintf("Cannot open STDOUT\n");
		vfs_close(v);
		return result;
	}
	standardOut->mode = O_WRONLY;
	array_add(curthread->ft->file_descriptors, standardOut);

	char console3[] = "con:";
	result = vfs_open(console3, O_WRONLY, &standardErr->v);
	if(result)
	{
		kprintf("Cannot open STDERR\n");
		vfs_close(v);
		return result;
	}
	standardErr->mode = O_WRONLY;
	array_add(curthread->ft->file_descriptors, standardErr);

	/* Allocate initial PID for this first program */
	result = allocate_pid(&pidRetVal);
	if(result)
	{
		kprintf("Could not allocate PID\n");
		vfs_close(v);
		return result;
	}
	curthread->PID = pidRetVal; 
	((struct p_node *)array_getguy(pid_table, curthread->PID))->is_interested = 0;
	
	/* Create a new address space. */
	curthread->t_vmspace = as_create();
	if (curthread->t_vmspace==NULL) {
		vfs_close(v);
		return ENOMEM;
	}

	/* Activate it. */
	as_activate(curthread->t_vmspace);

	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* thread_exit destroys curthread->t_vmspace */
		vfs_close(v);
		return result;
	}
	//kprintf("finished loadelf in runprog\n");

	/* Done with the file now. */
	vfs_close(v);

	/* Define the user stack in the address space */
	result = as_define_stack(curthread->t_vmspace, &stackptr);
	if (result) {
		/* thread_exit destroys curthread->t_vmspace */
		return result;
	}
	vaddr_t stackptrv[argc+1];
	int i;
	size_t actual;
	for(i = argc-1; i >= 0; i--)
	{
		int len = strlen(argv[i]);
		len++;
		int padding = len % 4;
		stackptr -= len + (4 - padding);
		result = copyoutstr(argv[i], (userptr_t)stackptr, len, &actual);
		if(result)
		{

			return result;
		}
		stackptrv[i] = stackptr;
	}
	stackptrv[argc] = 0;
	for(i = argc; i >= 0; i--)
	{
		stackptr -= sizeof(vaddr_t);
		result = copyout(&stackptrv[i], (userptr_t)stackptr, sizeof(vaddr_t));
		if(result)
		{
			return result;
		}
	}
	//kprintf("Before usernmode\n");
	/* Warp to user mode. */
	md_usermode(argc /*argc*/, (userptr_t)stackptr /*userspace addr of argv*/,
		    stackptr, entrypoint);
	
	/* md_usermode does not return */
	panic("md_usermode returned\n");
	return EINVAL;
}
Exemplo n.º 2
0
/* Create a new process, and add it to the process table*/
int
process_create(const char *name, pid_t parent, struct process **ret)
{
	struct process *process;

	process = kmalloc(sizeof(struct process));
	if(process == NULL) {
		//TODO probably need to fix this.
		return ENOMEM;
	}

	process->p_name = kstrdup(name);
	if(process->p_name == NULL) {
		kfree(process);
		return ENOMEM;
	}

	process->p_waitsem = sem_create(name,0);
	if(process->p_waitsem == NULL) {
		kfree(process->p_name);
		kfree(process);
		return ENOMEM;
	}

	// process->p_forksem = sem_create(name,0);
	// if(process->p_forksem == NULL) {
	// 	kfree(process->p_waitsem);
	// 	kfree(process->p_name);
	// 	kfree(process);
	// 	return ENOMEM;
	// }

	processtable_biglock_acquire();
	pid_t pid;
	int err = allocate_pid(&pid);
	if(err)
	{
		kfree(process->p_waitsem);
		kfree(process->p_name);
		kfree(process);
		return err;
	}
	process->p_id = pid;
	processtable[process->p_id] = process;
	parentprocesslist[process->p_id] = parent;
	processtable_biglock_release();

	// Copy over the file descriptors
	struct process *parent_p = get_process(parent);

	for(int i = 0; i < FD_MAX; i++) {
		process->p_fd_table[i] = parent_p->p_fd_table[i];
		// Increment the file handle open count if valid.
		if(process->p_fd_table[i] != NULL) {
			lock_acquire(process->p_fd_table[i]->fh_open_lk);
				process->p_fd_table[i]->fh_open_count = (process->p_fd_table[i]->fh_open_count) + 1;
			lock_release(process->p_fd_table[i]->fh_open_lk);
		}
	}

	*ret = process;
	return 0;
}