/branches/network/kernel/generic/src/proc/scheduler.c |
---|
451,7 → 451,7 |
/* |
* Entering state is unexpected. |
*/ |
panic("tid%" PRIu64 ": unexpected state %s\n", |
panic("tid%" PRIu64 ": unexpected state %s.", |
THREAD->tid, thread_states[THREAD->state]); |
break; |
} |
/branches/network/kernel/generic/src/proc/task.c |
---|
52,6 → 52,7 |
#include <print.h> |
#include <errno.h> |
#include <func.h> |
#include <string.h> |
#include <syscall/copy.h> |
/** Spinlock protecting the tasks_tree AVL tree. */ |
130,7 → 131,7 |
/** Create new task with no threads. |
* |
* @param as Task's address space. |
* @param name Symbolic name. |
* @param name Symbolic name (a copy is made). |
* |
* @return New task's structure. |
* |
148,7 → 149,10 |
spinlock_initialize(&ta->lock, "task_ta_lock"); |
list_initialize(&ta->th_head); |
ta->as = as; |
ta->name = name; |
memcpy(ta->name, name, TASK_NAME_BUFLEN); |
ta->name[TASK_NAME_BUFLEN - 1] = '\0'; |
atomic_set(&ta->refcount, 0); |
atomic_set(&ta->lifecount, 0); |
ta->context = CONTEXT; |
156,6 → 160,17 |
ta->capabilities = 0; |
ta->cycles = 0; |
#ifdef CONFIG_UDEBUG |
/* Init debugging stuff */ |
udebug_task_init(&ta->udebug); |
/* Init kbox stuff */ |
ipc_answerbox_init(&ta->kb.box, ta); |
ta->kb.thread = NULL; |
mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE); |
ta->kb.finished = false; |
#endif |
ipc_answerbox_init(&ta->answerbox, ta); |
for (i = 0; i < IPC_MAX_PHONES; i++) |
ipc_phone_init(&ta->phones[i]); |
235,6 → 250,35 |
sizeof(TASK->taskid)); |
} |
/** Syscall for setting the task name. |
* |
* The name simplifies identifying the task in the task list. |
* |
* @param name The new name for the task. (typically the same |
* as the command used to execute it). |
* |
* @return 0 on success or an error code from @ref errno.h. |
*/ |
unative_t sys_task_set_name(const char *uspace_name, size_t name_len) |
{ |
int rc; |
char namebuf[TASK_NAME_BUFLEN]; |
/* Cap length of name and copy it from userspace. */ |
if (name_len > TASK_NAME_BUFLEN - 1) |
name_len = TASK_NAME_BUFLEN - 1; |
rc = copy_from_uspace(namebuf, uspace_name, name_len); |
if (rc != 0) |
return (unative_t) rc; |
namebuf[name_len] = '\0'; |
strncpy(TASK->name, namebuf, TASK_NAME_BUFLEN); |
return EOK; |
} |
/** Find task structure corresponding to task ID. |
* |
* The tasks_lock must be already held by the caller of this function and |
353,13 → 397,13 |
order(task_get_accounting(t), &cycles, &suffix); |
#ifdef __32_BITS__ |
printf("%-6" PRIu64 " %-10s %-3" PRIu32 " %10p %10p %9" PRIu64 |
printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %10p %10p %9" PRIu64 |
"%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles, |
suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls)); |
#endif |
#ifdef __64_BITS__ |
printf("%-6" PRIu64 " %-10s %-3" PRIu32 " %18p %18p %9" PRIu64 |
printf("%-6" PRIu64 " %-12s %-3" PRIu32 " %18p %18p %9" PRIu64 |
"%c %7ld %6ld", t->taskid, t->name, t->context, t, t->as, cycles, |
suffix, atomic_get(&t->refcount), atomic_get(&t->active_calls)); |
#endif |
386,7 → 430,7 |
#ifdef __32_BITS__ |
printf("taskid name ctx address as " |
"cycles threads calls callee\n"); |
printf("------ ---------- --- ---------- ---------- " |
printf("------ ------------ --- ---------- ---------- " |
"---------- ------- ------ ------>\n"); |
#endif |
393,7 → 437,7 |
#ifdef __64_BITS__ |
printf("taskid name ctx address as " |
"cycles threads calls callee\n"); |
printf("------ ---------- --- ------------------ ------------------ " |
printf("------ ------------ --- ------------------ ------------------ " |
"---------- ------- ------ ------>\n"); |
#endif |
/branches/network/kernel/generic/src/proc/program.c |
---|
67,9 → 67,10 |
* |
* @param as Address space containing a binary program image. |
* @param entry_addr Program entry-point address in program address space. |
* @param name Name to set for the program's task. |
* @param p Buffer for storing program information. |
*/ |
void program_create(as_t *as, uintptr_t entry_addr, program_t *p) |
void program_create(as_t *as, uintptr_t entry_addr, char *name, program_t *p) |
{ |
as_area_t *a; |
uspace_arg_t *kernel_uarg; |
81,7 → 82,7 |
kernel_uarg->uspace_thread_arg = NULL; |
kernel_uarg->uspace_uarg = NULL; |
p->task = task_create(as, "app"); |
p->task = task_create(as, name); |
ASSERT(p->task); |
/* |
106,6 → 107,7 |
* executable image. The task is returned in *task. |
* |
* @param image_addr Address of an executable program image. |
* @param name Name to set for the program's task. |
* @param p Buffer for storing program info. If image_addr |
* points to a loader image, p->task will be set to |
* NULL and EOK will be returned. |
112,7 → 114,7 |
* |
* @return EOK on success or negative error code. |
*/ |
int program_create_from_image(void *image_addr, program_t *p) |
int program_create_from_image(void *image_addr, char *name, program_t *p) |
{ |
as_t *as; |
unsigned int rc; |
136,7 → 138,7 |
return EOK; |
} |
program_create(as, ((elf_header_t *) image_addr)->e_entry, p); |
program_create(as, ((elf_header_t *) image_addr)->e_entry, name, p); |
return EOK; |
} |
144,9 → 146,11 |
/** Create a task from the program loader image. |
* |
* @param p Buffer for storing program info. |
* @param name Name to set for the program's task. |
* |
* @return EOK on success or negative error code. |
*/ |
int program_create_loader(program_t *p) |
int program_create_loader(program_t *p, char *name) |
{ |
as_t *as; |
unsigned int rc; |
167,7 → 171,8 |
return ENOENT; |
} |
program_create(as, ((elf_header_t *) program_loader)->e_entry, p); |
program_create(as, ((elf_header_t *) program_loader)->e_entry, |
name, p); |
return EOK; |
} |
185,48 → 190,37 |
/** Syscall for creating a new loader instance from userspace. |
* |
* Creates a new task from the program loader image, connects a phone |
* to it and stores the phone id into the provided buffer. |
* Creates a new task from the program loader image and sets |
* the task name. |
* |
* @param uspace_phone_id Userspace address where to store the phone id. |
* @param name Name to set on the new task (typically the same |
* as the command used to execute it). |
* |
* @return 0 on success or an error code from @ref errno.h. |
*/ |
unative_t sys_program_spawn_loader(int *uspace_phone_id) |
unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len) |
{ |
program_t p; |
int fake_id; |
int rc; |
int phone_id; |
char namebuf[TASK_NAME_BUFLEN]; |
fake_id = 0; |
/* Cap length of name and copy it from userspace. */ |
/* Before we even try creating the task, see if we can write the id */ |
rc = (unative_t) copy_to_uspace(uspace_phone_id, &fake_id, |
sizeof(fake_id)); |
if (name_len > TASK_NAME_BUFLEN - 1) |
name_len = TASK_NAME_BUFLEN - 1; |
rc = copy_from_uspace(namebuf, uspace_name, name_len); |
if (rc != 0) |
return rc; |
return (unative_t) rc; |
phone_id = phone_alloc(); |
if (phone_id < 0) |
return ELIMIT; |
namebuf[name_len] = '\0'; |
rc = program_create_loader(&p); |
/* Spawn the new task. */ |
rc = program_create_loader(&p, namebuf); |
if (rc != 0) |
return rc; |
phone_connect(phone_id, &p.task->answerbox); |
/* No need to aquire lock before task_ready() */ |
rc = (unative_t) copy_to_uspace(uspace_phone_id, &phone_id, |
sizeof(phone_id)); |
if (rc != 0) { |
/* Ooops */ |
ipc_phone_hangup(&TASK->phones[phone_id]); |
task_kill(p.task->taskid); |
return rc; |
} |
// FIXME: control the capabilities |
cap_set(p.task, cap_get(TASK)); |
/branches/network/kernel/generic/src/proc/tasklet.c |
---|
51,7 → 51,7 |
tasklet_list = malloc(sizeof(tasklet_descriptor_t *) * config.cpu_count, 0); |
if (!tasklet_list) |
panic("Error initializing tasklets"); |
panic("Error initializing tasklets."); |
for (i = 0; i < config.cpu_count; i++) |
tasklet_list[i] = NULL; |
/branches/network/kernel/generic/src/proc/thread.c |
---|
102,7 → 102,7 |
thread_id_t last_tid = 0; |
static slab_cache_t *thread_slab; |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
slab_cache_t *fpu_context_slab; |
#endif |
161,7 → 161,7 |
/* call the architecture-specific part of the constructor */ |
thr_constructor_arch(t); |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
#ifdef CONFIG_FPU_LAZY |
t->saved_fpu_context = NULL; |
#else |
173,7 → 173,7 |
t->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags); |
if (!t->kstack) { |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
if (t->saved_fpu_context) |
slab_free(fpu_context_slab, t->saved_fpu_context); |
#endif |
180,6 → 180,10 |
return -1; |
} |
#ifdef CONFIG_UDEBUG |
mutex_initialize(&t->udebug.lock, MUTEX_PASSIVE); |
#endif |
return 0; |
} |
192,7 → 196,7 |
thr_destructor_arch(t); |
frame_free(KA2PA(t->kstack)); |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
if (t->saved_fpu_context) |
slab_free(fpu_context_slab, t->saved_fpu_context); |
#endif |
211,7 → 215,7 |
thread_slab = slab_cache_create("thread_slab", sizeof(thread_t), 0, |
thr_constructor, thr_destructor, 0); |
#ifdef ARCH_HAS_FPU |
#ifdef CONFIG_FPU |
fpu_context_slab = slab_cache_create("fpu_slab", sizeof(fpu_context_t), |
FPU_CONTEXT_ALIGN, NULL, NULL, 0); |
#endif |
275,7 → 279,7 |
* guarantee that the task won't cease to exist during the |
* call. The task's lock may not be held. |
* @param flags Thread flags. |
* @param name Symbolic name. |
* @param name Symbolic name (a copy is made). |
* @param uncounted Thread's accounting doesn't affect accumulated task |
* accounting. |
* |
312,6 → 316,7 |
interrupts_restore(ipl); |
memcpy(t->name, name, THREAD_NAME_BUFLEN); |
t->name[THREAD_NAME_BUFLEN - 1] = '\0'; |
t->thread_code = func; |
t->thread_arg = arg; |
347,6 → 352,11 |
avltree_node_initialize(&t->threads_tree_node); |
t->threads_tree_node.key = (uintptr_t) t; |
#ifdef CONFIG_UDEBUG |
/* Init debugging stuff */ |
udebug_thread_initialize(&t->udebug); |
#endif |
/* might depend on previous initialization */ |
thread_create_arch(t); |
409,12 → 419,17 |
ipl_t ipl; |
/* |
* Attach to the current task. |
* Attach to the specified task. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&task->lock); |
atomic_inc(&task->refcount); |
/* Must not count kbox thread into lifecount */ |
if (t->flags & THREAD_FLAG_USPACE) |
atomic_inc(&task->lifecount); |
list_append(&t->th_link, &task->th_head); |
spinlock_unlock(&task->lock); |
437,14 → 452,19 |
{ |
ipl_t ipl; |
if (THREAD->flags & THREAD_FLAG_USPACE) { |
#ifdef CONFIG_UDEBUG |
/* Generate udebug THREAD_E event */ |
udebug_thread_e_event(); |
#endif |
if (atomic_predec(&TASK->lifecount) == 0) { |
/* |
* We are the last thread in the task that still has not exited. |
* With the exception of the moment the task was created, new |
* threads can only be created by threads of the same task. |
* We are the last userspace thread in the task that |
* still has not exited. With the exception of the |
* moment the task was created, new userspace threads |
* can only be created by threads of the same task. |
* We are safe to perform cleanup. |
*/ |
if (THREAD->flags & THREAD_FLAG_USPACE) { |
ipc_cleanup(); |
futex_cleanup(); |
LOG("Cleanup of task %" PRIu64" completed.", TASK->taskid); |
689,7 → 709,7 |
* |
*/ |
unative_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name, |
thread_id_t *uspace_thread_id) |
size_t name_len, thread_id_t *uspace_thread_id) |
{ |
thread_t *t; |
char namebuf[THREAD_NAME_BUFLEN]; |
696,10 → 716,15 |
uspace_arg_t *kernel_uarg; |
int rc; |
rc = copy_from_uspace(namebuf, uspace_name, THREAD_NAME_BUFLEN); |
if (name_len > THREAD_NAME_BUFLEN - 1) |
name_len = THREAD_NAME_BUFLEN - 1; |
rc = copy_from_uspace(namebuf, uspace_name, name_len); |
if (rc != 0) |
return (unative_t) rc; |
namebuf[name_len] = '\0'; |
/* |
* In case of failure, kernel_uarg will be deallocated in this function. |
* In case of success, kernel_uarg will be freed in uinit(). |
738,7 → 763,18 |
return (unative_t) rc; |
} |
} |
#ifdef CONFIG_UDEBUG |
/* |
* Generate udebug THREAD_B event and attach the thread. |
* This must be done atomically (with the debug locks held), |
* otherwise we would either miss some thread or receive |
* THREAD_B events for threads that already existed |
* and could be detected with THREAD_READ before. |
*/ |
udebug_thread_b_event_attach(t, TASK); |
#else |
thread_attach(t, TASK); |
#endif |
thread_ready(t); |
return 0; |