Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3000 → Rev 3001

/branches/dynload/kernel/generic/src/proc/task.c
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