- add the support of the system call execve

This commit is contained in:
Stefan Lankes 2011-03-07 20:26:55 +01:00
parent fc407a3eda
commit d201c4d1bc
3 changed files with 49 additions and 3 deletions

View file

@ -70,6 +70,9 @@ void NORETURN sys_exit(int);
/* system call to create a new child process */
int sys_fork(void);
/* system call to execute a program */
int sys_execve(const char* fname, char** argv, char** env);
#ifdef __cplusplus
}
#endif

View file

@ -76,7 +76,14 @@ int syscall_handler(uint32_t sys_nr, ...)
ret = wait(status);
break;
}
case __NR_fstat:
case __NR_execve: {
const char* name = va_arg(vl, const char*);
char** argv = va_arg(vl, char**);
char** env = va_arg(vl, char**);
ret = sys_execve(name, argv, env);
break;
}
default:
kputs("invalid system call\n");
ret = -ENOSYS;

View file

@ -191,6 +191,7 @@ int sys_fork(void)
spinlock_init(&task_table[i].vma_lock);
// copy VMA list
spinlock_lock(&per_core(current_task)->vma_lock);
child = &task_table[i].vma_list;
parent = per_core(current_task)->vma_list;
tmp = NULL;
@ -210,6 +211,7 @@ int sys_fork(void)
tmp = *child;
child = &((*child)->next);
}
spinlock_unlock(&per_core(current_task)->vma_lock);
mailbox_wait_msg_init(&task_table[i].inbox);
memset(task_table[i].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS);
@ -239,10 +241,9 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* arg)
return create_task(id, ep, arg);
}
static int STDCALL user_entry(void* arg)
static int load_task(vfs_node_t* node)
{
uint32_t i, addr, npages, flags, stack = 0;
vfs_node_t* node = (vfs_node_t*) arg;
elf_header_t header;
elf_program_header_t prog_header;
//elf_section_header_t sec_header;
@ -370,6 +371,11 @@ invalid:
return -EINVAL;
}
static int STDCALL user_entry(void* arg)
{
return load_task((vfs_node_t*) arg);
}
int create_user_task(tid_t* id, size_t sz, const char* fname, int argc, char** argv)
{
vfs_node_t* node;
@ -381,6 +387,36 @@ int create_user_task(tid_t* id, size_t sz, const char* fname, int argc, char** a
return create_task(id, user_entry, node);
}
int sys_execve(const char* fname, char** argv, char** env)
{
vfs_node_t* node;
vma_t* tmp;
node = findnode_fs((char*) fname);
if (!node || !(node->type == FS_FILE))
return -EINVAL;
spinlock_lock(&(per_core(current_task)->vma_lock));
// remove old program
while((tmp = per_core(current_task)->vma_list) != NULL) {
kfree((void*) tmp->start, tmp->end - tmp->start + 1);
per_core(current_task)->vma_list = tmp->next;
kfree((void*) tmp, sizeof(vma_t));
}
spinlock_unlock(&(per_core(current_task)->vma_lock));
/*
* we use a trap gate to enter the kernel
* => eflags are not changed
* => interrupts are enabled
* => we could directly load the new task
*/
return load_task(node);
}
tid_t wait(int32_t* result)
{
wait_msg_t tmp = { -1, -1};