79,6 → 79,13 |
|
static task_id_t task_counter = 0; |
|
/** |
* Points to the binary image used as the program loader. All non-initial |
* tasks are created from this executable image. |
*/ |
void *program_loader = NULL; |
|
|
/** Initialize tasks |
* |
* Initialize kernel tasks support. |
235,32 → 242,21 |
|
/** Create new task with 1 thread and run it |
* |
* @param program_addr Address of program executable image. |
* @param name Program name. |
* @param as Address space containing a binary program image. |
* @param entry_addr Program entry-point address in program address space. |
* @param name Program name. |
* |
* @return Task of the running program or NULL on error. |
*/ |
task_t *task_run_program(void *program_addr, char *name) |
task_t *task_create_from_as(as_t *as, uintptr_t entry_addr, char *name) |
{ |
as_t *as; |
as_area_t *a; |
unsigned int rc; |
thread_t *t; |
task_t *task; |
uspace_arg_t *kernel_uarg; |
|
as = as_create(0); |
ASSERT(as); |
|
rc = elf_load((elf_header_t *) program_addr, as); |
if (rc != EE_OK) { |
as_destroy(as); |
return NULL; |
} |
|
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
kernel_uarg->uspace_entry = |
(void *) ((elf_header_t *) program_addr)->e_entry; |
kernel_uarg->uspace_entry = (void *) entry_addr; |
kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
kernel_uarg->uspace_thread_function = NULL; |
kernel_uarg->uspace_thread_arg = NULL; |
283,11 → 279,87 |
"uinit", false); |
ASSERT(t); |
|
thread_ready(t); |
|
return task; |
} |
|
/** Parse an executable image in the physical memory. |
* |
* If the image belongs to a program loader, it is registered as such, |
* (and *task is set to NULL). Otherwise a task is created from the |
* executable image. The task is returned in *task. |
* |
* @param program_addr Address of program executable image. |
* @param name Program name. |
* @param task Where to store the pointer to the newly created task. |
* |
* @return EOK on success or negative error code. |
*/ |
int task_parse_initial(void *program_addr, char *name, task_t **task) |
{ |
as_t *as; |
unsigned int rc; |
|
as = as_create(0); |
ASSERT(as); |
|
rc = elf_load((elf_header_t *) program_addr, as, 0); |
if (rc != EE_OK) { |
as_destroy(as); |
*task = NULL; |
if (rc != EE_LOADER) |
return ENOTSUP; |
|
/* Register image as the program loader */ |
ASSERT(program_loader == NULL); |
program_loader = program_addr; |
return EOK; |
} |
|
*task = task_create_from_as(as, ((elf_header_t *) program_addr)->e_entry, |
name); |
|
return EOK; |
} |
|
/** Create a task from the program loader image. |
* |
* @param program_addr Address of program executable image. |
* @param name Program name. |
* |
* @return Task of the running program or NULL on error. |
*/ |
task_t *task_create_from_loader(char *name) |
{ |
as_t *as; |
unsigned int rc; |
|
as = as_create(0); |
ASSERT(as); |
|
rc = elf_load((elf_header_t *) program_loader, as, ELD_F_LOADER); |
if (rc != EE_OK) { |
as_destroy(as); |
return NULL; |
} |
|
return task_create_from_as( |
as, ((elf_header_t *) program_loader)->e_entry, name); |
} |
|
/** Make task ready. |
* |
* Switch task's thread to the ready state. |
* |
* @param ta Task to make ready. |
*/ |
void task_ready(task_t *t) |
{ |
thread_t *th; |
|
th = list_get_instance(t->th_head.next, thread_t, th_link); |
thread_ready(th); |
} |
|
/** Syscall for reading task ID from userspace. |
* |
* @param uspace_task_id Userspace address of 8-byte buffer where to store |
305,6 → 377,44 |
sizeof(TASK->taskid)); |
} |
|
/** Syscall for creating a new task from userspace. |
* |
* Creates a new task from the program loader image and stores its |
* task id into the provided buffer. |
* |
* @param uspace_task_id Userspace address of 8-byte buffer where to store |
* current task ID. |
* |
* @return 0 on success or an error code from @ref errno.h. |
*/ |
unative_t sys_task_spawn(task_id_t *uspace_task_id) |
{ |
task_t *t; |
task_id_t fake_id; |
int rc; |
|
/* Before we even try creating the task, see if we can write the id */ |
rc = (unative_t) copy_to_uspace(uspace_task_id, &fake_id, |
sizeof(fake_id)); |
if (rc != 0) |
return rc; |
|
t = task_create_from_loader("loader"); |
|
/* No need to aquire lock before task_ready() */ |
rc = (unative_t) copy_to_uspace(uspace_task_id, &t->taskid, |
sizeof(t->taskid)); |
if (rc != 0) { |
/* Ooops */ |
task_kill(t->taskid); |
return rc; |
} |
|
task_ready(t); |
|
return EOK; |
} |
|
/** Find task structure corresponding to task ID. |
* |
* The tasks_lock must be already held by the caller of this function |