Vhex-kernel/src/kernel/scheduler/process/create.c

120 lines
3.4 KiB
C

#include <kernel/process.h>
#include <kernel/util/unistd_32.h>
#include <kernel/memory.h>
#include <kernel/util/debug.h>
#include <kernel/util/string.h>
struct process *process_create(const char *name)
{
extern struct process *process_current;
extern struct dentry *vfs_root_node;
struct process *process;
pid_t process_pid;
// Check error
if (name == NULL)
return (NULL);
// Try to find free slot.
process_pid = process_alloc(&process);
if (process == NULL)
{
kvram_clear();
printk(0, 0, "proc_error: alloc error !");
kvram_display();
DBG_WAIT;
return (NULL);
}
// Initialize user stack
process->memory.stack.size.user = PROCESS_USER_STACK_SIZE;
process->memory.stack.user = (uint32_t)pm_alloc(process->memory.stack.size.user);
if (process->memory.stack.user == 0x00000000)
{
kvram_clear();
printk(0, 0, "proc_error: user stack error !");
kvram_display();
DBG_WAIT;
process_free(process);
return (NULL);
}
process->context.reg[15] = process->memory.stack.user + process->memory.stack.size.user;
// Initialize kernel stack
process->memory.stack.size.kernel = PROCESS_KERNEL_STACK_SIZE;
process->memory.stack.kernel = (uint32_t)pm_alloc(process->memory.stack.size.kernel);
if (process->memory.stack.kernel == 0x00000000)
{
kvram_clear();
printk(0, 0, "proc_error: kernel stack error !");
kvram_display();
DBG_WAIT;
pm_free((void *)process->memory.stack.user);
process_free(process);
return (NULL);
}
process->stack.kernel = process->memory.stack.kernel + process->memory.stack.size.kernel;
// initialize "exit" part.
uint8_t callexit[6] = {
0b11000011, __NR_exit, // trapa #__NR_exit
0b10110000, 0b00000100, // bsr PC + 2 - 4
0b00000000, 0b00001001 // nop
};
process->memory.exit.size = 6;
process->memory.exit.start = (uint32_t)(pm_alloc(process->memory.exit.size));
if (process->memory.exit.start == 0x00000000)
{
pm_free((void *)process->memory.stack.user);
pm_free((void *)process->memory.stack.kernel);
process_free(process);
return (NULL);
}
process->context.pr = process->memory.exit.start;
memcpy((void *)process->memory.exit.start, callexit, 6);
// Set process name.
strncpy(process->name, name, PROCESS_NAME_LENGHT);
// Initialize context.
for (int i = 0 ; i < 15 ; i = i + 1)
process->context.reg[i] = 0x00000000;
// Initialize "special" registers.
process->context.gbr = 0x00000000;
process->context.macl = 0x00000000;
process->context.mach = 0x00000000;
process->context.ssr = 0x40000000; // <- force privilegied mode !
process->context.spc = 0x00000000;
// Initialise file cache
for (int i = 0 ; i < PROCESS_NB_OPEN_FILE ; i = i + 1)
{
process->opfile[i].status = PROCESS_FILE_SLOT_UNUSED;
process->opfile[i].file.private = NULL;
process->opfile[i].file.file_op = NULL;
process->opfile[i].file.permission = 0;
process->opfile[i].file.cursor = 0;
}
process->working_dir = vfs_root_node;
// DEBUG !
kvram_clear();
printk(0, 0, "proc_create: success !");
printk(0, 1, "user stack: %p", process->context.reg[15]);
printk(0, 2, "kernel stack: %p", process->memory.stack.kernel);
kvram_display();
DBG_WAIT;
// Link new process with his parent.
// @Note:
// But de not link praent with new
// process to avoid crash with sheduler.
// The new process will be visible only
// when it is registered by the sheduler.
process->parent = process_current;
process->child = NULL;
process->next = NULL;
return (process);
}