From a6c61e05b9e346a5c4bdc4b0affd329649cc57ed Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Thu, 29 Oct 2009 22:44:58 +0200 Subject: [PATCH] l4_exit() works with a reasonable sched_die_sync() Next: Killing other tasks more cleanly, and waiting on children --- conts/test/main.c | 44 ++++++++++++++++++++++- conts/test/src/captest.c | 3 +- include/l4/generic/scheduler.h | 1 + include/l4/generic/tcb.h | 11 +++--- src/api/cap.c | 2 ++ src/api/thread.c | 2 +- src/generic/container.c | 4 +-- src/generic/scheduler.c | 64 ++++++++++++++++++++++++++++++++++ src/generic/tcb.c | 6 ++-- 9 files changed, 121 insertions(+), 16 deletions(-) diff --git a/conts/test/main.c b/conts/test/main.c index 486baf8..0bd28b2 100644 --- a/conts/test/main.c +++ b/conts/test/main.c @@ -8,13 +8,55 @@ #include #include #include +#include +#include +#include + +int exit_test_thread(void *arg) +{ + l4_exit(0); + return 0; +} + +int exit_test(void) +{ + int ret; + struct task_ids ids; + + /* Create and run a new thread */ + if ((ret = thread_create(exit_test_thread, 0, + TC_SHARE_SPACE | TC_AS_PAGER, + &ids)) < 0) { + printf("Top-level simple_pager creation failed.\n"); + goto out_err; + } + + /* Wait on it */ + if ((ret = l4_thread_control(THREAD_WAIT, &ids)) >= 0) + printf("Success. Paged child returned %d\n", ret); + else + printf("Error. Wait on (%d) failed. err = %d\n", + ids.tid, ret); + + return 0; + +out_err: + BUG(); +} int main(void) { printf("%s: Container %s started\n", __CONTAINER__, __CONTAINER_NAME__); - capability_test(); + //capability_test(); + + //exit_test(); + + /* Now quit to demo self-paging quit */ + l4_exit(0); + /* Now quit by null pointer */ + // *((int *)0) = 5; return 0; } diff --git a/conts/test/src/captest.c b/conts/test/src/captest.c index b534a19..5a7a068 100644 --- a/conts/test/src/captest.c +++ b/conts/test/src/captest.c @@ -85,8 +85,7 @@ int capability_test(void) */ if ((err = thread_create(simple_pager_thread, &TEST_MUST_FAIL, - TC_SHARE_SPACE | - TC_AS_PAGER, &ids)) < 0) { + TC_SHARE_SPACE, &ids)) < 0) { printf("Top-level simple_pager creation failed.\n"); goto out_err; } diff --git a/include/l4/generic/scheduler.h b/include/l4/generic/scheduler.h index c339000..1bb0c59 100644 --- a/include/l4/generic/scheduler.h +++ b/include/l4/generic/scheduler.h @@ -60,6 +60,7 @@ 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_die_sync(void); void sched_suspend_sync(void); void sched_suspend_async(void); void sched_resume_sync(struct ktcb *task); diff --git a/include/l4/generic/tcb.h b/include/l4/generic/tcb.h index 972801c..9e049e1 100644 --- a/include/l4/generic/tcb.h +++ b/include/l4/generic/tcb.h @@ -64,6 +64,9 @@ struct ktcb { l4id_t tid; /* Global thread id */ l4id_t tgid; /* Global thread group id */ + /* Other related threads */ + l4id_t pagerid; + /* Flags to indicate various task status */ unsigned int flags; @@ -73,11 +76,9 @@ struct ktcb { /* Lock for blocking thread state modifications via a syscall */ struct mutex thread_control_lock; - /* Other related threads */ - l4id_t pagerid; - u32 ts_need_resched; /* Scheduling flag */ enum task_state state; + struct link task_list; /* Global task list. */ /* UTCB related, see utcb.txt in docs */ @@ -102,9 +103,7 @@ struct ktcb { struct pager *pager; /* Capability lists */ - struct cap_list cap_list; /* Own private capabilities */ - struct cap_list tgroup_cap_list; /* Caps shared with thread group */ - struct cap_list pager_cap_list; /* Caps shared with paged children */ + struct cap_list cap_list; /* Own private capabilities */ /* Fields for ipc rendezvous */ struct waitqueue_head wqh_recv; diff --git a/src/api/cap.c b/src/api/cap.c index bc0be45..61fa89a 100644 --- a/src/api/cap.c +++ b/src/api/cap.c @@ -68,6 +68,7 @@ int capability_share(unsigned int share_flags) cap_list_move(&curcont->cap_list, ¤t->cap_list); break; +#if 0 case CAP_SHARE_CHILD: /* * Move own capabilities to paged-children @@ -97,6 +98,7 @@ int capability_share(unsigned int share_flags) ¤t->cap_list); break; } +#endif default: return -EINVAL; } diff --git a/src/api/thread.c b/src/api/thread.c index 2a72125..bd3e7e2 100644 --- a/src/api/thread.c +++ b/src/api/thread.c @@ -200,7 +200,7 @@ void thread_destroy_current(void) /* Indicate we want to become zombie on suspend */ current->flags |= TASK_EXITING; - sched_suspend_sync(); + sched_die_sync(); } /* Runs a thread for the first time */ diff --git a/src/generic/container.c b/src/generic/container.c index b26c416..cb5452f 100644 --- a/src/generic/container.c +++ b/src/generic/container.c @@ -144,8 +144,8 @@ int init_pager(struct pager *pager, page_align_up(pager->memsize), MAP_USR_DEFAULT_FLAGS, TASK_PGD(task)); - /* Move capability list from dummy to task's cap list */ - cap_list_move(&task->cap_list, ¤t->cap_list); + /* Move capability list from dummy to task's space cap list */ + cap_list_move(&task->space->cap_list, ¤t->cap_list); /* Initialize task scheduler parameters */ sched_init_task(task, TASK_PRIO_PAGER); diff --git a/src/generic/scheduler.c b/src/generic/scheduler.c index 6b2cee0..94d4bfd 100644 --- a/src/generic/scheduler.c +++ b/src/generic/scheduler.c @@ -226,6 +226,70 @@ void sched_resume_async(struct ktcb *task) RQ_ADD_FRONT); } +#if 0 +/* FIXME: Disables preemption for unbounded time !!! */ +void tcb_delete_schedule(void) +{ + /* We lock all possible locks to do with */ + address_space_lock(); + + /* + * Lock ktcb mutex cache so that nobody can get me + * during this period + */ + mutex_lock(&kernel_resources.ktcb_cache.lock); + tcb_delete(current); + + preempt_disable(); + + sched_rq_remove_task(current); + current->state = TASK_INACTIVE; + scheduler.prio_total -= current->priority; + BUG_ON(scheduler.prio_total < 0); + + ktcb_list_unlock(); + address_space_list_unlock(); + + preempt_enable(); + schedule(); +} +#endif + +void sched_die_sync(void) +{ + /* Remove from its list, callers get -ESRCH */ + tcb_remove(current); + + /* + * If there are any sleepers on any of the task's + * waitqueues, we need to wake those tasks up. + */ + wake_up_all(¤t->wqh_send, 0); + wake_up_all(¤t->wqh_recv, 0); + + /* + * We're a self-paging thread. We're gonna + * delete ourself and disappear from the + * system as soon as we schedule + */ + preempt_disable(); + + /* + * TOO LONG! + */ + tcb_delete(current); + + sched_rq_remove_task(current); + current->state = TASK_INACTIVE; + scheduler.prio_total -= current->priority; + BUG_ON(scheduler.prio_total < 0); + + /* As soon as we schedule, we're gone */ + preempt_enable(); + schedule(); + BUG(); +} + /* * NOTE: Could do these as sched_prepare_suspend() * + schedule() or need_resched = 1 diff --git a/src/generic/tcb.c b/src/generic/tcb.c index 1abc930..123a210 100644 --- a/src/generic/tcb.c +++ b/src/generic/tcb.c @@ -31,8 +31,6 @@ void tcb_init(struct ktcb *new) mutex_init(&new->thread_control_lock); cap_list_init(&new->cap_list); - cap_list_init(&new->tgroup_cap_list); - cap_list_init(&new->pager_cap_list); /* Initialise task's scheduling state and parameters. */ sched_init_task(new, TASK_PRIO_NORMAL); @@ -71,8 +69,8 @@ void tcb_delete(struct ktcb *tcb) BUG_ON(tcb->wqh_send.sleepers > 0); BUG_ON(tcb->wqh_recv.sleepers > 0); BUG_ON(!list_empty(&tcb->task_list)); - BUG_ON(!list_empty(&tcb->rq_list)); - BUG_ON(tcb->rq); + BUG_ON(!list_empty(&tcb->rq_list) && tcb != current); + BUG_ON(tcb->rq && tcb != current); BUG_ON(tcb->nlocks); BUG_ON(tcb->waiting_on); BUG_ON(tcb->wq);