/* * 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; }
/* 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; }