/kernel/trunk/generic/include/proc/thread.h |
---|
72,6 → 72,8 |
/** Lock protecting thread structure. |
* |
* Protects the whole thread structure except list links above. |
* Must be acquired before T.lock for each T of type task_t. |
* |
*/ |
SPINLOCK_DECLARE(lock); |
96,13 → 98,7 |
bool in_copy_from_uspace; |
/** True if this thread is executing copy_to_uspace(). False otherwise. */ |
bool in_copy_to_uspace; |
/** |
* If true, the thread will not go to sleep at all and will |
* call thread_exit() before returning to userspace. |
*/ |
bool interrupted; |
bool detached; /**< If true, thread_join_timeout() cannot be used on this thread. */ |
waitq_t join_wq; /**< Waitq for thread_join_timeout(). */ |
/kernel/trunk/generic/include/proc/task.h |
---|
40,22 → 40,12 |
/** Task structure. */ |
struct task { |
/** Task lock. |
* |
* Must be acquired before threads_lock and thread lock of any of its threads. |
*/ |
SPINLOCK_DECLARE(lock); |
char *name; |
link_t th_head; /**< List of threads contained in this task. */ |
as_t *as; /**< Address space. */ |
task_id_t taskid; /**< Unique identity of task */ |
/** If this is true, new threads can become part of the task. */ |
bool accept_new_threads; |
count_t refcount; /**< Number of references (i.e. threads). */ |
cap_t capabilities; /**< Task capabilities. */ |
/* IPC stuff */ |
80,12 → 70,9 |
extern void task_init(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_find_by_id(task_id_t id); |
extern int task_kill(task_id_t id); |
#ifndef task_create_arch |
extern void task_create_arch(task_t *t); |
#endif |
/kernel/trunk/generic/src/proc/task.c |
---|
47,7 → 47,6 |
#include <memstr.h> |
#include <print.h> |
#include <elf.h> |
#include <errno.h> |
#include <syscall/copy.h> |
#ifndef LOADED_PROG_STACK_PAGES_NO |
58,8 → 57,6 |
btree_t tasks_btree; |
static task_id_t task_counter = 0; |
static void ktask_cleanup(void *); |
/** Initialize tasks |
* |
* Initialize kernel tasks support. |
97,10 → 94,7 |
ta->as = as; |
ta->name = name; |
ta->refcount = 0; |
ta->capabilities = 0; |
ta->accept_new_threads = true; |
ipc_answerbox_init(&ta->answerbox); |
for (i=0; i < IPC_MAX_PHONES;i++) |
133,14 → 127,6 |
return ta; |
} |
/** Destroy task. |
* |
* @param t Task to be destroyed. |
*/ |
void task_destroy(task_t *t) |
{ |
} |
/** Create new task with 1 thread and run it |
* |
* @param program_addr Address of program executable image. |
221,60 → 207,6 |
return (task_t *) btree_search(&tasks_btree, (btree_key_t) id, &leaf); |
} |
/** Kill task. |
* |
* @param id ID of the task to be killed. |
* |
* @return 0 on success or an error code from errno.h |
*/ |
int task_kill(task_id_t id) |
{ |
ipl_t ipl; |
task_t *ta; |
thread_t *t; |
link_t *cur; |
ipl = interrupts_disable(); |
spinlock_lock(&tasks_lock); |
if (!(ta = task_find_by_id(id))) { |
spinlock_unlock(&tasks_lock); |
interrupts_restore(ipl); |
return ENOENT; |
} |
spinlock_lock(&ta->lock); |
ta->refcount++; |
spinlock_unlock(&ta->lock); |
t = thread_create(ktask_cleanup, NULL, ta, 0, "ktask_cleanup"); |
spinlock_lock(&ta->lock); |
ta->refcount--; |
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
thread_t *thr; |
bool sleeping = false; |
thr = list_get_instance(cur, thread_t, th_link); |
if (thr == t) |
continue; |
spinlock_lock(&thr->lock); |
thr->interrupted = true; |
if (thr->state == Sleeping) |
sleeping = true; |
spinlock_unlock(&thr->lock); |
if (sleeping) |
waitq_interrupt_sleep(thr); |
} |
thread_ready(t); |
return 0; |
} |
/** Print task list */ |
void task_print_list(void) |
{ |
311,15 → 243,3 |
spinlock_unlock(&tasks_lock); |
interrupts_restore(ipl); |
} |
/** Kernel thread used to cleanup the task. */ |
void ktask_cleanup(void *arg) |
{ |
/* |
* TODO: |
* Wait until it is save to cleanup the task (i.e. all other threads exit) |
* and do the cleanup (e.g. close IPC communication and release used futexes). |
* When this thread exits, the task refcount drops to zero and the task structure is |
* cleaned. |
*/ |
} |
/kernel/trunk/generic/src/proc/thread.c |
---|
233,8 → 233,6 |
*/ |
void thread_destroy(thread_t *t) |
{ |
bool destroy_task = false; |
ASSERT(t->state == Exiting); |
ASSERT(t->task); |
ASSERT(t->cpu); |
244,26 → 242,19 |
t->cpu->fpu_owner=NULL; |
spinlock_unlock(&t->cpu->lock); |
spinlock_unlock(&t->lock); |
spinlock_lock(&threads_lock); |
btree_remove(&threads_btree, (btree_key_t) ((__address ) t), NULL); |
spinlock_unlock(&threads_lock); |
/* |
* Detach from the containing task. |
*/ |
spinlock_lock(&t->task->lock); |
list_remove(&t->th_link); |
if (--t->task->refcount == 0) { |
t->task->accept_new_threads = false; |
destroy_task = true; |
} |
spinlock_unlock(&t->task->lock); |
spinlock_unlock(&t->task->lock); |
if (destroy_task) |
task_destroy(t->task); |
spinlock_unlock(&t->lock); |
spinlock_lock(&threads_lock); |
btree_remove(&threads_btree, (btree_key_t) ((__address ) t), NULL); |
spinlock_unlock(&threads_lock); |
slab_free(thread_slab, t); |
} |
328,8 → 319,7 |
t->in_copy_from_uspace = false; |
t->in_copy_to_uspace = false; |
t->interrupted = false; |
t->detached = false; |
waitq_initialize(&t->join_wq); |
341,19 → 331,6 |
t->fpu_context_engaged = 0; |
/* |
* Attach to the containing task. |
*/ |
spinlock_lock(&task->lock); |
if (!task->accept_new_threads) { |
spinlock_unlock(&task->lock); |
slab_free(thread_slab, t); |
return NULL; |
} |
list_append(&t->th_link, &task->th_head); |
task->refcount++; |
spinlock_unlock(&task->lock); |
/* |
* Register this thread in the system-wide list. |
*/ |
ipl = interrupts_disable(); |
361,6 → 338,13 |
btree_insert(&threads_btree, (btree_key_t) ((__address) t), (void *) t, NULL); |
spinlock_unlock(&threads_lock); |
/* |
* Attach to the containing task. |
*/ |
spinlock_lock(&task->lock); |
list_append(&t->th_link, &task->th_head); |
spinlock_unlock(&task->lock); |
interrupts_restore(ipl); |
return t; |
/kernel/trunk/generic/src/synch/waitq.c |
---|
311,12 → 311,6 |
*/ |
spinlock_lock(&THREAD->lock); |
if (THREAD->interrupted) { |
spinlock_unlock(&THREAD->lock); |
spinlock_unlock(&wq->lock); |
return ESYNCH_INTERRUPTED; |
} |
if (flags & SYNCH_FLAGS_INTERRUPTIBLE) { |
/* |
* Set context that will be restored if the sleep |
/kernel/trunk/generic/src/syscall/syscall.c |
---|
90,26 → 90,10 |
__native syscall_handler(__native a1, __native a2, __native a3, |
__native a4, __native id) |
{ |
__native rc; |
ipl_t ipl; |
bool exit = false; |
if (id < SYSCALL_END) |
rc = syscall_table[id](a1,a2,a3,a4); |
return syscall_table[id](a1,a2,a3,a4); |
else |
panic("Undefined syscall %d", id); |
ipl = interrupts_disable(); |
spinlock_lock(&THREAD->lock); |
if (THREAD->interrupted) |
exit = true; |
spinlock_unlock(&THREAD->lock); |
interrupts_restore(ipl); |
if (exit) |
thread_exit(); |
return rc; |
} |
syshandler_t syscall_table[SYSCALL_END] = { |