#include "sched.h"
#include "proc.h"
#include "alloc_proc.h"
#include "idle.h"
#include "proc_struct.h"
#include <fd.h>
#include <resolve.h>
#include <node.h>
#include <stat_struct.h>
#include <vm.h>
#include <string_table.h>
#include <it_stack_structs.h>
#include <asm.h>
#include <errno.h>
#include <consts.h>
#include <enums.h>
#include <i386.h>
#include <stddef.h>
extern int end;
void _start_init();
static void init_file_descrs(struct file_descr_struct *file_descr_table[])
{
struct file_descr_struct **file_descr;
for (file_descr = file_descr_table; file_descr < file_descr_table + OPEN_MAX; file_descr++)
*file_descr = NULL;
}
static void dup_file_descrs(struct file_descr_struct *const src[], struct file_descr_struct *dest[])
{
struct file_descr_struct *const *file_descr1;
struct file_descr_struct **file_descr2;
file_descr2 = dest;
for (file_descr1 = src; file_descr1 < src + OPEN_MAX; file_descr1++) {
if ((*file_descr2 = *file_descr1))
fd_dup(*file_descr2);
file_descr2++;
}
}
static void init_idle()
{
static char idle_name[] = "<idle>\0";
static const struct string_table_struct idle_cmdline = {1, idle_name, sizeof idle_name};
proc_table_init();
proc_list_init();
proc_tree_init();
proc_group_init();
idle->state = PS_IDLE;
idle->cmdline = idle_cmdline;
sched_init();
}
static int setup_init(struct proc_struct *init)
{
int retval;
if ((retval = vm_copy(NULL, &init->vm, init->page_directory)) < 0)
goto error;
if ((retval = vm_map_mem(&init->vm, PAGE_SIZE, PAGE_ALIGN((unsigned long)&end))) < 0)
goto error_vm_free;
init->brk = (unsigned long)&end;
if (vm_map_anon(&init->vm, USER_STACK_TOP - PAGE_SIZE, PAGE_SIZE, PROT_RDWR, 1, "stack") < 0)
goto error_vm_free;
return 0;
error_vm_free:
vm_free(&init->vm);
error:
return retval;
}
static int init_init(struct proc_struct *init)
{
int retval;
int intr;
disable_intr(intr);
proc_table_add(init);
proc_list_add(init);
proc_tree_add(init, idle);
if ((retval = proc_create_proc_group(init)) < 0)
goto error_proc_tree_remove;
init->state = PS_RUNNING;
init->did_exec = 0;
status_init(init);
if ((retval = string_table_init_from_string(&init->cmdline, "<init>")) < 0)
goto error_proc_group_remove;
init->wd = root;
node_hold(init->wd);
if ((retval = setup_init(init)) < 0)
goto error_release_wd;
init_file_descrs(init->file_descr_table);
signal_init(init, 1);
sleep_init(init);
sched_add(init);
restore_intr(intr);
return 0;
error_release_wd:
node_release(init->wd);
string_table_destroy(&init->cmdline);
error_proc_group_remove:
proc_group_remove(init);
error_proc_tree_remove:
proc_tree_remove(init);
proc_list_remove(init);
proc_table_remove(init);
restore_intr(intr);
return retval;
}
static int clone_proc(struct proc_struct *child)
{
int retval;
int intr;
disable_intr(intr);
proc_table_add(child);
proc_list_add(child);
proc_tree_add(child, current);
proc_group_add(child, current->group);
child->state = PS_RUNNING;
child->did_exec = 0;
status_init(child);
if ((retval = string_table_clone(¤t->cmdline, &child->cmdline)) < 0)
goto error_proc_group_remove;
child->wd = current->wd;
node_hold(child->wd);
if ((retval = vm_copy(¤t->vm, &child->vm, child->page_directory)) < 0)
goto error_release_wd;
child->brk = current->brk;
dup_file_descrs(current->file_descr_table, child->file_descr_table);
signal_init(child, 0);
sleep_init(child);
sched_add(child);
restore_intr(intr);
return 0;
error_release_wd:
node_release(child->wd);
string_table_destroy(&child->cmdline);
error_proc_group_remove:
proc_group_remove(child);
proc_tree_remove(child);
proc_list_remove(child);
proc_table_remove(child);
restore_intr(intr);
return retval;
}
void proc_init()
{
alloc_proc_init();
init_idle();
}
void proc_print_info()
{
alloc_proc_print_info();
}
int spawn_init()
{
int retval;
struct registers_struct registers;
struct interrupted_instruction_struct start_instruction;
struct proc_struct *init;
registers.ebx = 0;
registers.ecx = 0;
registers.edx = 0;
registers.esi = 0;
registers.edi = 0;
registers.ebp = 0;
start_instruction.eip = (unsigned long)_start_init;
start_instruction.eflags = 0x200;
start_instruction.esp = USER_STACK_TOP;
if ((retval = alloc_proc(®isters, &start_instruction, &init)) < 0)
goto error;
if ((retval = init_init(init)) < 0)
goto error_free_init;
return 0;
error_free_init:
free_proc(init);
error:
return retval;
}
int fork(const struct registers_struct *registers, const struct interrupted_instruction_struct *interrupted_instruction)
{
int retval;
struct proc_struct *child;
if ((retval = alloc_proc(registers, interrupted_instruction, &child)) < 0)
goto error;
if ((retval = clone_proc(child)) < 0)
goto error_free_proc;
return child->id;
error_free_proc:
free_proc(child);
error:
return retval;
}
void change_set_proc_group(struct proc_group_struct *proc_group)
{
int intr;
disable_intr(intr);
if (proc_group == current->group)
goto restore;
proc_change_set_proc_group(current, proc_group);
restore:
restore_intr(intr);
}
int change_create_proc_group()
{
int intr;
int retval;
disable_intr(intr);
retval = proc_change_create_proc_group(current);
restore_intr(intr);
return retval;
}
int change_set_child_proc_group(struct proc_struct *child, struct proc_group_struct *proc_group)
{
int intr;
if (child->did_exec)
return -EACCES;
disable_intr(intr);
if (proc_group == child->group)
goto restore;
proc_change_set_proc_group(child, proc_group);
restore:
restore_intr(intr);
return 0;
}
int change_create_child_proc_group(struct proc_struct *child)
{
int intr;
int retval;
if (child->did_exec)
return -EACCES;
disable_intr(intr);
retval = proc_change_create_proc_group(child);
restore_intr(intr);
return retval;
}
int change_wd(const char *fs_path)
{
int retval;
struct file_struct *file;
struct stat_struct statbuf;
if ((retval = resolve(fs_path, &file)) < 0)
goto end;
if ((retval = stat_node(file, &statbuf)) < 0)
goto release;
if (statbuf.type != FT_DIR) {
retval = -ENOTDIR;
goto release;
}
node_release(current->wd);
current->wd = file;
node_hold(current->wd);
retval = 0;
release:
node_release(file);
end:
return retval;
}