forwarding arguments to the new tasks
This commit is contained in:
parent
ed29ee444a
commit
2d9ba6ae70
6 changed files with 127 additions and 29 deletions
|
@ -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);
|
||||
|
|
119
kernel/tasks.c
119
kernel/tasks.c
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Reference in a new issue