#include "proc_struct.h"
#include <kmalloc.h>
#include <printk.h>
#include <gdt.h>
#include <system.h>
#include <system_data_structs.h>
#include <it_stack_structs.h>
#include <asm.h>
#include <errno.h>
#include <i386.h>
#include <stddef.h>
static struct task_table_entry {
struct task_table_entry *next_free;
} task_table[NR_TASKS];
static struct task_table_entry *first_free;
static struct proc_struct _idle;
struct proc_struct *const idle = &_idle;
static void init_task_table()
{
struct task_table_entry *entry;
entry = first_free = task_table + 1;
while (entry != task_table + (NR_TASKS - 1)) {
entry->next_free = entry + 1;
entry++;
}
entry->next_free = NULL;
}
static void print_task_table_info()
{
printk("Task table size: %d\n", NR_TASKS);
}
static unsigned int alloc_task_nr()
{
struct task_table_entry *entry;
if (!(entry = first_free))
return 0;
first_free = first_free->next_free;
return entry - task_table;
}
static void free_task_nr(unsigned int task_nr)
{
struct task_table_entry *entry;
entry = task_table + task_nr;
entry->next_free = first_free;
first_free = entry;
}
static void init_idle_task()
{
struct tss_data_struct tss_data;
get_pdbr(idle->page_directory);
tss_data.pdbr = (unsigned long)idle->page_directory;
tss_data.ldt = 0;
tss_data.ss0 = 0;
tss_data.esp0 = 0;
tss_data.ss1 = 0;
tss_data.esp1 = 0;
tss_data.ss2 = 0;
tss_data.esp2 = 0;
tss_data.trap = 0;
tss_data.iomap_base = 0;
set_tss(&idle->tss, &tss_data);
gdt_set_tss_descr(0, &idle->tss);
idle->tss_sel = get_tss_sel(0);
lldt(0);
ltr(idle->tss_sel);
}
static int init_task(struct proc_struct *proc, const struct registers_struct *registers, const struct interrupted_instruction_struct *start_instruction)
{
int retval;
unsigned int task_nr;
struct tss_data_struct tss_data;
if (!(task_nr = alloc_task_nr())) {
retval = -EAGAIN;
goto error;
}
if (!(proc->kernel_stack = kmalloc(KERNEL_STACK_SIZE))) {
retval = -ENOMEM;
goto error_free_task;
}
if (!(proc->page_directory = kmalloc(PAGE_SIZE))) {
retval = -ENOMEM;
goto error_free_kernel_stack;
}
tss_data.pdbr = (unsigned long)proc->page_directory;
tss_data.ldt = 0;
tss_data.ss0 = KERNEL_DATA_SEL;
tss_data.esp0 = (unsigned long)(proc->kernel_stack + KERNEL_STACK_SIZE);
tss_data.ss1 = 0;
tss_data.esp1 = 0;
tss_data.ss2 = 0;
tss_data.esp2 = 0;
tss_data.trap = 0;
tss_data.iomap_base = sizeof (struct tss_struct);
tss_data.eax = 0;
tss_data.ebx = registers->ebx;
tss_data.ecx = registers->ecx;
tss_data.edx = registers->edx;
tss_data.ebp = registers->ebp;
tss_data.esp = start_instruction->esp;
tss_data.esi = registers->esi;
tss_data.edi = registers->edi;
tss_data.cs = USER_CODE_SEL;
tss_data.ds = USER_DATA_SEL;
tss_data.es = USER_DATA_SEL;
tss_data.fs = USER_DATA_SEL;
tss_data.gs = USER_DATA_SEL;
tss_data.ss = USER_DATA_SEL;
tss_data.eflags = start_instruction->eflags;
tss_data.eip = start_instruction->eip;
tss_data.previous = 0;
set_tss(&proc->tss, &tss_data);
gdt_set_tss_descr(task_nr, &proc->tss);
proc->tss_sel = get_tss_sel(task_nr);
return 0;
error_free_kernel_stack:
kfree(proc->kernel_stack, KERNEL_STACK_SIZE);
error_free_task:
free_task_nr(task_nr);
error:
return retval;
}
static void destroy_task(struct proc_struct *proc)
{
unsigned int task_nr;
task_nr = get_task_nr(proc->tss_sel);
kfree(proc->page_directory, PAGE_SIZE);
kfree(proc->kernel_stack, KERNEL_STACK_SIZE);
free_task_nr(task_nr);
}
void alloc_proc_init()
{
init_task_table();
init_idle_task();
}
void alloc_proc_print_info()
{
print_task_table_info();
}
int alloc_proc(const struct registers_struct *registers, const struct interrupted_instruction_struct *start_instruction, struct proc_struct **proc)
{
int retval;
if (!(*proc = kmalloc(sizeof (struct proc_struct)))) {
retval = -ENOMEM;
goto error;
}
if ((retval = init_task(*proc, registers, start_instruction)) < 0)
goto error_kfree;
return 0;
error_kfree:
kfree(*proc, sizeof (struct proc_struct));
error:
return retval;
}
void free_proc(struct proc_struct *proc)
{
destroy_task(proc);
kfree(proc, sizeof (struct proc_struct));
}