can haz threads?

This commit is contained in:
Markus Schober 2012-02-15 22:56:16 -06:00
parent cffbb02240
commit 4453aba2de
6 changed files with 48 additions and 19 deletions

View File

@ -64,7 +64,7 @@ DECL_SYSCALL3(lseek, int, int, int);
DECL_SYSCALL2(stat, const char *, void *);
/* Process Control */
DECL_SYSCALL0(getpid);
DECL_SYSCALL0(sys_getpid);
DECL_SYSCALL3(execve, char *, char **, char **);
DECL_SYSCALL0(fork);
DECL_SYSCALL2(kill, int, int);

View File

@ -257,7 +257,7 @@ extern void switch_task(uint8_t reschedule);
extern void switch_from_cross_thread_lock();
extern void switch_next();
extern uint32_t fork();
extern uint32_t clone(uintptr_t new_stack, uintptr_t old_stack);
extern uint32_t clone(uintptr_t new_stack, uintptr_t thread_func, uintptr_t arg);
extern uint32_t getpid();
extern void enter_user_jmp(uintptr_t location, int argc, char ** argv, uintptr_t stack);

View File

@ -22,6 +22,8 @@ typedef struct page_directory {
page_table_t *tables[1024]; /* 1024 pointers to page tables... */
uintptr_t physical_tables[1024]; /* Physical addresses of the tables */
uintptr_t physical_address; /* The physical address of physical_tables */
int32_t ref_count;
} page_directory_t;

View File

@ -150,6 +150,7 @@ process_t * spawn_init() {
* of the process' entry in the process tree. */
init->tree_entry = process_tree->root;
init->id = 0; /* Init is PID 1 */
init->group = 0;
init->name = "init"; /* Um, duh. */
init->user = 0; /* UID 0 */
init->group = 0; /* Task group 0 */
@ -224,6 +225,7 @@ process_t * spawn_process(volatile process_t * parent) {
/* Allocate a new process */
process_t * proc = malloc(sizeof(process_t));
proc->id = get_next_pid(); /* Set its PID */
proc->group = proc->id; /* Set the GID */
proc->name = default_name; /* Use the default name */
proc->description = NULL; /* No description */

View File

@ -163,6 +163,11 @@ static int sys_sbrk(int size) {
return ret;
}
static int sys_getpid() {
/* The user actually wants the pid of the originating thread (which can be us). */
return current_process->group;
}
static int execve(const char * filename, char *const argv[], char *const envp[]) {
validate((void *)argv);
validate((void *)filename);
@ -489,7 +494,7 @@ static uintptr_t syscalls[] = {
(uintptr_t)&gettimeofday,
(uintptr_t)&execve,
(uintptr_t)&fork, /* 8 */
(uintptr_t)&getpid,
(uintptr_t)&sys_getpid,
(uintptr_t)&sys_sbrk,
(uintptr_t)&getgraphicsaddress,
(uintptr_t)&kbd_mode, /* 12 */

View File

@ -29,6 +29,8 @@ clone_directory(
page_directory_t * dir = (page_directory_t *)kvmalloc_p(sizeof(page_directory_t), &phys);
/* Clear it out */
memset(dir, 0, sizeof(page_directory_t));
dir->ref_count = 1;
/* Calculate the physical address offset */
uintptr_t offset = (uintptr_t)dir->physical_tables - (uintptr_t)dir;
/* And store it... */
@ -56,22 +58,26 @@ clone_directory(
/*
* Free a directory and its tables
*/
void free_directory(page_directory_t * dir) {
uint32_t i;
for (i = 0; i < 1024; ++i) {
if (!dir->tables[i] || (uintptr_t)dir->tables[i] == (uintptr_t)0xFFFFFFFF) {
continue;
}
if (kernel_directory->tables[i] != dir->tables[i]) {
for (uint32_t j = 0; j < 1024; ++j) {
if (dir->tables[i]->pages[j].frame) {
free_frame(&(dir->tables[i]->pages[j]));
}
void release_directory(page_directory_t * dir) {
dir->ref_count--;
if (dir->ref_count < 1) {
uint32_t i;
for (i = 0; i < 1024; ++i) {
if (!dir->tables[i] || (uintptr_t)dir->tables[i] == (uintptr_t)0xFFFFFFFF) {
continue;
}
if (kernel_directory->tables[i] != dir->tables[i]) {
for (uint32_t j = 0; j < 1024; ++j) {
if (dir->tables[i]->pages[j].frame) {
free_frame(&(dir->tables[i]->pages[j]));
}
}
free(dir->tables[i]);
}
free(dir->tables[i]);
}
free(dir);
}
free(dir);
}
void reap_process(process_t * proc) {
@ -80,7 +86,7 @@ void reap_process(process_t * proc) {
list_free(proc->signal_queue);
free(proc->signal_queue);
free((void *)(proc->image.stack - KERNEL_STACK_SIZE));
free_directory(proc->thread.page_directory);
release_directory(proc->thread.page_directory);
free((void *)(proc->fds.entries));
shm_release_all(proc);
@ -238,7 +244,7 @@ fork() {
* memory space with the given pointer as its new stack.
*/
uint32_t
clone(uintptr_t stack_top, uintptr_t stack_old) {
clone(uintptr_t new_stack, uintptr_t thread_func, uintptr_t arg) {
unsigned int magic = TASK_MAGIC;
uintptr_t esp, ebp, eip;
@ -255,6 +261,7 @@ clone(uintptr_t stack_top, uintptr_t stack_old) {
assert(new_proc && "Could not allocate a new process!");
/* Set the new process' page directory to the original process' */
set_process_environment(new_proc, directory);
directory->ref_count++;
/* Read the instruction pointer */
eip = read_eip();
@ -282,6 +289,19 @@ clone(uintptr_t stack_top, uintptr_t stack_old) {
uintptr_t offset = ((uintptr_t)current_process->syscall_registers - o_stack);
new_proc->syscall_registers = (struct regs *)(n_stack + offset);
/* Set the gid */
new_proc->group = current_process->group;
/* Push arg, bogus return address onto the new thread's stack */
new_stack -= sizeof(uintptr_t);
*((uintptr_t *)new_stack) = arg;
new_stack -= sizeof(uintptr_t);
*((uintptr_t *)new_stack) = THREAD_RETURN;
/* Set esp, ebp, and eip for the new thread */
new_proc->syscall_registers->esp = new_stack;
new_proc->syscall_registers->ebp = new_stack;
new_proc->syscall_registers->eip = thread_func;
/* Set the new process instruction pointer (to the return from read_eip) */
new_proc->thread.eip = eip;
@ -291,7 +311,7 @@ clone(uintptr_t stack_top, uintptr_t stack_old) {
/* Return the child PID */
return new_proc->id;
} else {
assert(magic == TASK_MAGIC && "Bad process fork magic (child clone)!");
assert(magic == TASK_MAGIC && "Bad process clone magic (child clone)!");
/* Child fork is complete, return */
return 0;
}