forwarding arguments to the new tasks

This commit is contained in:
Stefan Lankes 2011-03-08 23:12:38 +01:00
parent ed29ee444a
commit 2d9ba6ae70
6 changed files with 127 additions and 29 deletions

View file

@ -37,8 +37,8 @@ int multitasking_init(void);
/* create a kernel task. */
int create_kernel_task(tid_t*, entry_point_t, void*);
/* create a user level task. if sz is zero, the task with the default stack size will be created */
int create_user_task(tid_t* id, size_t sz, const char* filename, int argc, char** argv);
/* create a user level task. */
int create_user_task(tid_t* id, const char* filename, char** argv);
/* until a child task is terminated, the current task is block */
tid_t wait(int32_t* result);

View file

@ -241,13 +241,28 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* arg)
return create_task(id, ep, arg);
}
static int load_task(vfs_node_t* node)
#define MAX_ARGS (PAGE_SIZE - 2*sizeof(int) - sizeof(vfs_node_t*))
typedef struct {
vfs_node_t* node;
int argc;
int envc;
char buffer[MAX_ARGS];
} load_args_t;
static int load_task(load_args_t* largs)
{
uint32_t i, addr, npages, flags, stack = 0;
uint32_t i, offset, idx;
uint32_t addr, npages, flags, stack = 0;
elf_header_t header;
elf_program_header_t prog_header;
//elf_section_header_t sec_header;
vfs_node_t* node;
if (!largs)
return -EINVAL;
node = largs->node;
if (!node)
return -EINVAL;
@ -361,7 +376,34 @@ static int load_task(vfs_node_t* node)
return -ENOMEM;
}
jump_to_user_code(header.entry, stack+DEFAULT_STACK_SIZE-64);
// push strings on the stack
offset = DEFAULT_STACK_SIZE-MAX_ARGS-8;
memcpy((void*) (stack+offset), largs->buffer, MAX_ARGS);
idx = offset;
// push argv on the stack
offset -= largs->argc * sizeof(char*);
i = 0;
while(i<largs->argc) {
((char**) (stack+offset))[i] = (char*) (stack+idx);
i++;
while((i<largs->argc) && ((char*) stack)[idx] != '\0')
idx++;
idx++;
}
// push pointer to argv
offset -= sizeof(char**);
*((char***) (stack+offset)) = (char**) (stack + offset + sizeof(char**));
// push argc on the stack
offset -= sizeof(int);
*((int*) (stack+offset)) = largs->argc;
kfree(largs, sizeof(load_args_t));
jump_to_user_code(header.entry, stack+offset);
return 0;
@ -373,29 +415,88 @@ invalid:
static int STDCALL user_entry(void* arg)
{
return load_task((vfs_node_t*) arg);
return load_task((load_args_t*) arg);
}
int create_user_task(tid_t* id, size_t sz, const char* fname, int argc, char** argv)
int create_user_task(tid_t* id, const char* fname, char** argv)
{
vfs_node_t* node;
int argc = 0;
size_t i, buffer_size = 0;
load_args_t* load_args = NULL;
char *dest, *src;
node = findnode_fs((char*) fname);
if (!node || !(node->type == FS_FILE))
return -EINVAL;
return create_task(id, user_entry, node);
// determine buffer size of argv
if (argv) {
while (argv[argc]) {
buffer_size += (strlen(argv[argc]) + 1);
argc++;
}
}
if (argc <= 0)
return -EINVAL;
if (buffer_size >= MAX_ARGS)
return -EINVAL;
load_args = kmalloc(sizeof(load_args_t));
if (BUILTIN_EXPECT(!load_args, 0))
return -ENOMEM;
load_args->node = node;
load_args->argc = argc;
load_args->envc = 0;
dest = load_args->buffer;
for (i=0; i<argc; i++) {
src = argv[i];
while ((*dest++ = *src++) != 0);
}
return create_task(id, user_entry, load_args);
}
int sys_execve(const char* fname, char** argv, char** env)
{
vfs_node_t* node;
vma_t* tmp;
size_t i, buffer_size = 0;
load_args_t* load_args = NULL;
char *dest, *src;
int ret, argc = 0;
node = findnode_fs((char*) fname);
if (!node || !(node->type == FS_FILE))
return -EINVAL;
// determine buffer size of argv
if (argv) {
while (argv[argc]) {
buffer_size += (strlen(argv[argc]) + 1);
argc++;
}
}
if (argc <= 0)
return -EINVAL;
if (buffer_size >= MAX_ARGS)
return -EINVAL;
load_args = kmalloc(sizeof(load_args_t));
if (BUILTIN_EXPECT(!load_args, 0))
return -ENOMEM;
load_args->node = node;
load_args->argc = argc;
load_args->envc = 0;
dest = load_args->buffer;
for (i=0; i<argc; i++) {
src = argv[i];
while ((*dest++ = *src++) != 0);
}
spinlock_lock(&(per_core(current_task)->vma_lock));
// remove old program
@ -414,7 +515,11 @@ int sys_execve(const char* fname, char** argv, char** env)
* => we could directly load the new task
*/
return load_task(node);
ret = load_task(load_args);
kfree(load_args, sizeof(load_args_t));
return ret;
}
tid_t wait(int32_t* result)

View file

@ -102,7 +102,7 @@ static int STDCALL join_test(void* arg)
int test_init(void)
{
char* argv[1] = {"dummy"};
char* argv[] = {"/bin/tests", NULL};
sem_init(&producing, 1);
sem_init(&consuming, 0);
@ -112,8 +112,8 @@ int test_init(void)
//create_kernel_task(NULL, join_test, NULL);
//create_kernel_task(NULL, producer, NULL);
//create_kernel_task(NULL, consumer, NULL);
//create_user_task(NULL, 8192, "/bin/hello", 1, argv);
create_user_task(NULL, 8192, "/bin/tests", 1, argv);
//create_user_task(NULL, "/bin/hello", 1, argv);
create_user_task(NULL, "/bin/tests", argv);
return 0;
}

View file

@ -27,8 +27,12 @@ extern int errno;
int main(int argc, char** argv)
{
int i;
char str[] = "Hello World!!!\n";
for(i=0; i<argc; i++)
printf("argv[%i] = %s\n", i, argv[i]);
write(1, str, strlen(str));
printf("Hello from printf!!!\n");

View file

@ -29,14 +29,17 @@ extern int errno;
int main(int argc, char** argv)
{
int status = 0;
int i, status = 0;
pid_t pid;
printf("Create child process...\n");
for(i=0; i<argc; i++)
printf("argv[%i] = %s\n", i, argv[i]);
pid = fork();
if (pid == 0) { // child
char* args[] = {"/bin/hello", (char*) 0};
char* args[] = {"/bin/hello", "one", "two", "three", NULL};
printf("Hello from child process!\n");
execve("/bin/hello", args, environ);

View file

@ -17,10 +17,6 @@
; This file is part of MetalSVM.
[BITS 32]
SECTION .data
cmdline DB "cmdline", 0
argv DD 0, 0
SECTION .text
global _start
extern main
@ -50,20 +46,10 @@ L2:
; call init function
call __do_global_ctors
; build argc/argv pair and then push
; them onto the stack...
mov [argv+0], DWORD cmdline
mov eax, [esp+4]
mov [argv+4], eax
push argv
push 2
; arguments are already on the stack
; call the user's function
call main
; remove argc/argv pair
add esp, 8
; call exit from the C library so atexit gets called, and the
; C++ destructors get run. This calls our exit routine below
; when it's done.