Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3000 → Rev 3001

/branches/dynload/kernel/generic/include/proc/task.h
112,15 → 112,21
SPINLOCK_EXTERN(tasks_lock);
extern avltree_t tasks_tree;
 
extern void *program_loader;
 
extern void task_init(void);
extern void task_done(void);
extern task_t *task_create(as_t *as, char *name);
extern void task_destroy(task_t *t);
extern task_t *task_run_program(void *program_addr, char *name);
extern task_t *task_create_from_as(as_t *as, uintptr_t entry_addr, char *name);
extern int task_parse_initial(void *program_addr, char *name, task_t **task);
extern task_t *task_create_from_loader(char *name);
extern void task_ready(task_t *t);
extern task_t *task_find_by_id(task_id_t id);
extern int task_kill(task_id_t id);
extern uint64_t task_get_accounting(task_t *t);
 
 
extern void cap_set(task_t *t, cap_t caps);
extern cap_t cap_get(task_t *t);
 
133,6 → 139,7
#endif
 
extern unative_t sys_task_get_id(task_id_t *uspace_task_id);
extern unative_t sys_task_spawn(task_id_t *uspace_task_id);
 
#endif
 
/branches/dynload/kernel/generic/include/lib/elf.h
114,7 → 114,8
#define EE_MEMORY 2 /* Cannot allocate address space */
#define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */
#define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */
#define EE_IRRECOVERABLE 5
#define EE_LOADER 5 /* The image is actually a program loader */
#define EE_IRRECOVERABLE 6
 
/**
* ELF section types
338,6 → 339,10
 
extern char *elf_error(unsigned int rc);
 
/* Interpreter string used to recognize the program loader */
#define ELF_INTERP_ZSTR "kernel"
#define ELF_INTERP_ZLEN sizeof(ELF_INTERP_ZSTR)
 
#endif
 
/** @}
/branches/dynload/kernel/generic/include/mm/as.h
300,8 → 300,14
extern mem_backend_t elf_backend;
extern mem_backend_t phys_backend;
 
extern unsigned int elf_load(elf_header_t *header, as_t *as);
/**
* This flags is passed when running the loader, otherwise elf_load()
* would return with a EE_LOADER error code.
*/
#define ELD_F_LOADER 1
 
extern unsigned int elf_load(elf_header_t *header, as_t *as, int flags);
 
/* Address space area related syscalls. */
extern unative_t sys_as_area_create(uintptr_t address, size_t size, int flags);
extern unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags);
/branches/dynload/kernel/generic/include/syscall/syscall.h
42,6 → 42,7
SYS_THREAD_EXIT,
SYS_THREAD_GET_ID,
SYS_TASK_GET_ID,
SYS_TASK_SPAWN,
SYS_FUTEX_SLEEP,
SYS_FUTEX_WAKEUP,
SYS_AS_AREA_CREATE,
/branches/dynload/kernel/generic/src/main/kinit.c
157,7 → 157,10
count_t i;
for (i = 0; i < init.cnt; i++) {
/*
* Run user tasks, load RAM disk images.
* Parse initial images
* - Run user tasks
* - load RAM disk images.
* - register program loader
*/
if (init.tasks[i].addr % FRAME_SIZE) {
165,19 → 168,27
continue;
}
 
task_t *utask = task_run_program((void *) init.tasks[i].addr,
"uspace");
task_t *utask;
int rc = task_parse_initial((void *) init.tasks[i].addr,
"uspace", &utask);
if (utask) {
if (rc == 0 && utask) {
/* Make the task ready */
task_ready(utask);
 
/*
* Set capabilities to init userspace tasks.
*/
cap_set(utask, CAP_CAP | CAP_MEM_MANAGER |
CAP_IO_MANAGER | CAP_PREEMPT_CONTROL | CAP_IRQ_REG);
 
if (!ipc_phone_0)
ipc_phone_0 = &utask->answerbox;
} else if (rc == 0) {
/* It was the program loader and was registered */
} else {
/* RAM disk image */
int rd = init_rd((rd_header *) init.tasks[i].addr,
init.tasks[i].size);
/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
/branches/dynload/kernel/generic/src/lib/elf.c
57,7 → 57,7
};
 
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf,
as_t *as);
as_t *as, int flags);
static int section_header(elf_section_header_t *entry, elf_header_t *elf,
as_t *as);
static int load_segment(elf_segment_header_t *entry, elf_header_t *elf,
67,9 → 67,10
*
* @param header Pointer to ELF header in memory
* @param as Created and properly mapped address space
* @param flags A combination of ELD_F_*
* @return EE_OK on success
*/
unsigned int elf_load(elf_header_t *header, as_t * as)
unsigned int elf_load(elf_header_t *header, as_t * as, int flags)
{
int i, rc;
 
106,7 → 107,7
 
seghdr = &((elf_segment_header_t *)(((uint8_t *) header) +
header->e_phoff))[i];
rc = segment_header(seghdr, header, as);
rc = segment_header(seghdr, header, as, flags);
if (rc != EE_OK)
return rc;
}
147,8 → 148,10
* @return EE_OK on success, error code otherwise.
*/
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf,
as_t *as)
as_t *as, int flags)
{
char *interp;
 
switch (entry->p_type) {
case PT_NULL:
case PT_PHDR:
158,6 → 161,14
break;
case PT_DYNAMIC:
case PT_INTERP:
interp = (char *)elf + entry->p_offset;
if (memcmp(interp, ELF_INTERP_ZSTR, ELF_INTERP_ZLEN) != 0) {
return EE_UNSUPPORTED;
}
if ((flags & ELD_F_LOADER) == 0) {
return EE_LOADER;
}
break;
case PT_SHLIB:
case PT_NOTE:
case PT_LOPROC:
/branches/dynload/kernel/generic/src/syscall/syscall.c
128,6 → 128,7
(syshandler_t) sys_thread_exit,
(syshandler_t) sys_thread_get_id,
(syshandler_t) sys_task_get_id,
(syshandler_t) sys_task_spawn,
/* Synchronization related syscalls. */
(syshandler_t) sys_futex_sleep_timeout,