From 850c645d777c5d516d46333bb30af096950d1397 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Sat, 31 Oct 2009 23:13:19 +0200 Subject: [PATCH] Exiting tasks use EXITING signal and change states to TASK_DEAD --- include/l4/api/thread.h | 1 + include/l4/generic/cap-types.h | 1 + include/l4/generic/scheduler.h | 1 - scripts/kernel/generate_kernel_cinfo.py | 2 +- src/api/thread.c | 22 +++++++++++++++++++--- src/arch/arm/exception.c | 8 ++++++++ src/generic/capability.c | 5 +++++ src/generic/scheduler.c | 16 ++++++++++++++++ src/glue/arm/systable.c | 3 +++ 9 files changed, 54 insertions(+), 5 deletions(-) diff --git a/include/l4/api/thread.h b/include/l4/api/thread.h index 2b25188..095c713 100644 --- a/include/l4/api/thread.h +++ b/include/l4/api/thread.h @@ -7,6 +7,7 @@ #define THREAD_SUSPEND 0x0002 #define THREAD_DESTROY 0x0003 #define THREAD_RECYCLE 0x0004 +#define THREAD_WAIT 0x0005 #define THREAD_CREATE_MASK 0x0FF0 #define TC_SHARE_CAPS 0x0010 /* Share all thread capabilities */ diff --git a/include/l4/generic/cap-types.h b/include/l4/generic/cap-types.h index c84dd31..d818acb 100644 --- a/include/l4/generic/cap-types.h +++ b/include/l4/generic/cap-types.h @@ -50,6 +50,7 @@ #define CAP_TCTRL_RUN (1 << 2) #define CAP_TCTRL_SUSPEND (1 << 3) #define CAP_TCTRL_RECYCLE (1 << 4) +#define CAP_TCTRL_WAIT (1 << 5) /* Exchange registers capability */ #define CAP_EXREGS_RW_PAGER (1 << 0) diff --git a/include/l4/generic/scheduler.h b/include/l4/generic/scheduler.h index b1e2d7b..3f79237 100644 --- a/include/l4/generic/scheduler.h +++ b/include/l4/generic/scheduler.h @@ -61,7 +61,6 @@ extern struct scheduler scheduler; void sched_init_runqueue(struct runqueue *rq); void sched_init_task(struct ktcb *task, int priority); void sched_prepare_sleep(void); -void sched_exit_pager(void); void sched_exit_sync(void); void sched_suspend_sync(void); void sched_suspend_async(void); diff --git a/scripts/kernel/generate_kernel_cinfo.py b/scripts/kernel/generate_kernel_cinfo.py index 12c7918..dcc9a54 100755 --- a/scripts/kernel/generate_kernel_cinfo.py +++ b/scripts/kernel/generate_kernel_cinfo.py @@ -110,7 +110,7 @@ cap_all_others = \ \t\t\t\t.type = CAP_TYPE_TCTRL | CAP_RTYPE_CONTAINER, \t\t\t\t.access = CAP_TCTRL_CREATE | CAP_TCTRL_DESTROY \t\t\t\t | CAP_TCTRL_SUSPEND | CAP_TCTRL_RUN -\t\t\t\t | CAP_TCTRL_RECYCLE, +\t\t\t\t | CAP_TCTRL_RECYCLE | CAP_TCTRL_WAIT, \t\t\t\t.start = 0, .end = 0, .size = 0, \t\t\t}, \t\t\t[%d] = { diff --git a/src/api/thread.c b/src/api/thread.c index f39aa39..c5511bb 100644 --- a/src/api/thread.c +++ b/src/api/thread.c @@ -54,6 +54,12 @@ int thread_suspend(struct ktcb *task) return thread_signal(task, TASK_SUSPENDING, TASK_INACTIVE); } +int thread_exit(struct ktcb *task) +{ + + return thread_signal(task, TASK_EXITING, TASK_DEAD); +} + static inline int TASK_IS_CHILD(struct ktcb *task) { return (((task) != current) && @@ -62,7 +68,7 @@ static inline int TASK_IS_CHILD(struct ktcb *task) int thread_destroy_child(struct ktcb *task) { - thread_suspend(task); + thread_exit(task); tcb_remove(task); @@ -71,7 +77,7 @@ int thread_destroy_child(struct ktcb *task) wake_up_all(&task->wqh_recv, WAKEUP_INTERRUPT); BUG_ON(task->wqh_pager.sleepers > 0); - BUG_ON(task->state != TASK_INACTIVE); + BUG_ON(task->state != TASK_DEAD); tcb_delete(task); return 0; @@ -100,7 +106,12 @@ void thread_destroy_self() { thread_destroy_children(); - sched_suspend_sync(); + sched_exit_sync(); +} + +int thread_wait(struct ktcb *task) +{ + return 0; } int thread_destroy(struct ktcb *task) @@ -177,6 +188,8 @@ int thread_start(struct ktcb *task) if (!mutex_trylock(&task->thread_control_lock)) return -EAGAIN; + /* FIXME: Refuse to run dead tasks */ + /* Notify scheduler of task resume */ sched_resume_async(task); @@ -404,6 +417,9 @@ int sys_thread_control(unsigned int flags, struct task_ids *ids) case THREAD_RECYCLE: ret = thread_recycle(task); break; + case THREAD_WAIT: + ret = thread_wait(task); + break; default: ret = -EINVAL; diff --git a/src/arch/arm/exception.c b/src/arch/arm/exception.c index 03e95b2..8998cae 100644 --- a/src/arch/arm/exception.c +++ b/src/arch/arm/exception.c @@ -282,7 +282,11 @@ void data_abort_handler(u32 faulted_pc, u32 fsr, u32 far) if (current->flags & TASK_SUSPENDING) { BUG_ON(current->nlocks); sched_suspend_sync(); + } else if (current->flags & TASK_EXITING) { + BUG_ON(current->nlocks); + sched_exit_sync(); } + return; error: @@ -311,7 +315,11 @@ void prefetch_abort_handler(u32 faulted_pc, u32 fsr, u32 far, u32 lr) if (current->flags & TASK_SUSPENDING) { BUG_ON(current->nlocks); sched_suspend_sync(); + } else if (current->flags & TASK_EXITING) { + BUG_ON(current->nlocks); + sched_exit_sync(); } + return; error: diff --git a/src/generic/capability.c b/src/generic/capability.c index 0c67d43..614a4af 100644 --- a/src/generic/capability.c +++ b/src/generic/capability.c @@ -437,6 +437,11 @@ struct capability *cap_match_thread(struct capability *cap, if (!(cap->access & CAP_TCTRL_RECYCLE)) return 0; break; + case THREAD_WAIT: + if (!(cap->access & CAP_TCTRL_WAIT)) + return 0; + break; + default: /* We refuse to accept anything else */ return 0; diff --git a/src/generic/scheduler.c b/src/generic/scheduler.c index 0997a3a..a9826fa 100644 --- a/src/generic/scheduler.c +++ b/src/generic/scheduler.c @@ -225,6 +225,22 @@ void sched_resume_async(struct ktcb *task) RQ_ADD_FRONT); } + +/* Same as suspend, task state and flags are different */ +void sched_exit_sync(void) +{ + preempt_disable(); + sched_rq_remove_task(current); + current->state = TASK_DEAD; + current->flags &= ~TASK_EXITING; + preempt_enable(); + + if (current->pagerid != current->tid) + wake_up(¤t->wqh_pager, 0); + + schedule(); +} + /* * NOTE: Could do these as sched_prepare_suspend() * + schedule() or need_resched = 1 diff --git a/src/glue/arm/systable.c b/src/glue/arm/systable.c index 83a61ce..542251d 100644 --- a/src/glue/arm/systable.c +++ b/src/glue/arm/systable.c @@ -170,6 +170,9 @@ int syscall(syscall_context_t *regs, unsigned long swi_addr) if (current->flags & TASK_SUSPENDING) { BUG_ON(current->nlocks); sched_suspend_sync(); + } else if (current->flags & TASK_EXITING) { + BUG_ON(current->nlocks); + sched_exit_sync(); } return ret;