From ee7621b2dfac2b8b928e24aa86e3f6fa92096922 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Fri, 30 Oct 2009 18:28:45 +0200 Subject: [PATCH] Some more progress with debugging pager exits --- conts/posix/mm0/main.c | 3 +-- src/arch/arm/exception.c | 7 ++++++- src/generic/container.c | 18 ++++++++++++++---- src/generic/scheduler.c | 20 ++++++++++++++------ src/generic/space.c | 7 ++++++- src/generic/tcb.c | 3 ++- src/glue/arm/init.c | 6 ------ src/lib/mutex.c | 5 +++++ src/lib/wait.c | 4 ++-- 9 files changed, 50 insertions(+), 23 deletions(-) diff --git a/conts/posix/mm0/main.c b/conts/posix/mm0/main.c index 9cd0157..3c1ee2d 100644 --- a/conts/posix/mm0/main.c +++ b/conts/posix/mm0/main.c @@ -140,14 +140,13 @@ void handle_requests(void) break; } case L4_IPC_TAG_EXIT: { - /* Zombie test for kernel struct task_ids ids; l4_getid(&ids); printf("\n%s: Destroying self (%d), along with any tasks.\n", __TASKNAME__, self_tid()); l4_thread_control(THREAD_DESTROY, &ids); - */ + /* An exiting task has no receive phase */ sys_exit(sender, (int)mr[0]); return; diff --git a/src/arch/arm/exception.c b/src/arch/arm/exception.c index 750392f..853fa6d 100644 --- a/src/arch/arm/exception.c +++ b/src/arch/arm/exception.c @@ -123,7 +123,12 @@ void fault_ipc_to_pager(u32 faulty_pc, u32 fsr, u32 far) "returned error (%d). Suspend and exiting thread.\n", current->tid, err); BUG_ON(current->nlocks); - sched_die_sync(); + + /* Declare our exit, currently only used by bug_on checks */ + current->flags |= TASK_EXITING; + /* Try to die forever */ + while (1) + sched_die_sync(); } } diff --git a/src/generic/container.c b/src/generic/container.c index cb5452f..a939af9 100644 --- a/src/generic/container.c +++ b/src/generic/container.c @@ -102,7 +102,8 @@ int init_pager(struct pager *pager, address_space_attach(task, space); } else { /* Otherwise allocate conventionally */ - task->space = address_space_create(0); + space = address_space_create(0); + address_space_attach(task, space); } /* Initialize ktcb */ @@ -115,6 +116,13 @@ int init_pager(struct pager *pager, task->tgid = task->tid; task->container = cont; + /* + * Setup dummy container pointer so that curcont works, + * and add the address space to container space list + */ + current->container = cont; + address_space_add(task->space); + /* Initialize uninitialized capability fields while on dummy */ list_foreach_struct(cap, ¤t->cap_list.caps, list) { /* Initialize owner */ @@ -156,7 +164,6 @@ int init_pager(struct pager *pager, /* Container list that keeps all tasks */ tcb_add(task); - return 0; } @@ -169,16 +176,19 @@ int container_init_pagers(struct kernel_resources *kres, { struct container *cont; struct pager *pager; + int first = 1; list_foreach_struct(cont, &kres->containers.list, list) { for (int i = 0; i < cont->npagers; i++) { pager = &cont->pager[i]; /* First pager initializes specially */ - if (i == 0) + if (first) { init_pager(pager, cont, current_pgd); - else + first = 0; + } else { init_pager(pager, cont, 0); + } } } diff --git a/src/generic/scheduler.c b/src/generic/scheduler.c index 2cd0be9..ddfa314 100644 --- a/src/generic/scheduler.c +++ b/src/generic/scheduler.c @@ -301,6 +301,8 @@ void sched_die_pager(void) */ void sched_die_child(void) { + int err; + /* * Find pager, he _must_ be there because he never * quits before quitting us @@ -308,7 +310,8 @@ void sched_die_child(void) struct ktcb *pager = tcb_find(current->pagerid); /* Lock its task_dead queue */ - mutex_lock(&pager->task_dead.list_lock); + if ((err = mutex_lock(&pager->task_dead.list_lock)) < 0) + return err; /* Remove from container task list, * callers get -ESRCH */ @@ -332,7 +335,7 @@ void sched_die_child(void) * Add self to pager's dead tasks list, * to be deleted by pager */ - ktcb_list_add(current, &pager->task_dead); + __ktcb_list_add_nolock(current, &pager->task_dead); /* Now quit the scheduler */ preempt_disable(); @@ -354,15 +357,20 @@ void sched_die_child(void) * pager can safely delete us */ mutex_unlock(&pager->task_dead.list_lock); + schedule(); BUG(); } void sched_die_sync(void) { - if (current->tid == current->pagerid) - sched_die_pager(); - else - sched_die_child(); + /* + * Infinitely retry if mutexes get interrupted + */ + while (1) + if (current->tid == current->pagerid) + sched_die_pager(); + else + sched_die_child(); } /* diff --git a/src/generic/space.c b/src/generic/space.c index 5aa2d28..db5d033 100644 --- a/src/generic/space.c +++ b/src/generic/space.c @@ -68,7 +68,12 @@ void address_space_add(struct address_space *space) void address_space_remove(struct address_space *space) { spin_lock(&curcont->space_list.list_lock); - BUG_ON(list_empty(&space->list)); + + /* + * If current is quitting as the last task of this space, + * its tcb may already be removed, and this is fine + */ + BUG_ON(list_empty(&space->list) && space != current->space); BUG_ON(--curcont->space_list.count < 0); list_remove_init(&space->list); spin_unlock(&curcont->space_list.list_lock); diff --git a/src/generic/tcb.c b/src/generic/tcb.c index 9feda57..42b2bc6 100644 --- a/src/generic/tcb.c +++ b/src/generic/tcb.c @@ -70,7 +70,8 @@ void tcb_delete(struct ktcb *tcb) BUG_ON(tcb->wqh_pager.sleepers > 0); 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->task_list) && + !(tcb->flags & TASK_EXITING)); BUG_ON(!list_empty(&tcb->rq_list) && tcb != current); BUG_ON(tcb->rq && tcb != current); BUG_ON(tcb->nlocks); diff --git a/src/glue/arm/init.c b/src/glue/arm/init.c index a225619..56c6302 100644 --- a/src/glue/arm/init.c +++ b/src/glue/arm/init.c @@ -283,12 +283,6 @@ void init_finalize(struct kernel_resources *kres) */ kip.utcb = (u32)current->utcb_address; - /* - * Added the first pager's space area to - * the address space list of the related container - */ - address_space_add(current->space); - /* * Start the scheduler, jumping to task */ diff --git a/src/lib/mutex.c b/src/lib/mutex.c index f6cd0c0..4cd0eb5 100644 --- a/src/lib/mutex.c +++ b/src/lib/mutex.c @@ -117,6 +117,7 @@ int mutex_lock(struct mutex *mutex) * undeterministic as to how many retries will result in success. * We may need to add priority-based locking. */ + printk("Thread (%d) locking (%p) nlocks: %d\n", current->tid, mutex, current->nlocks); for (;;) { spin_lock(&mutex->wqh.slock); if (!__mutex_lock(&mutex->lock)) { /* Could not lock, sleep. */ @@ -131,6 +132,7 @@ int mutex_lock(struct mutex *mutex) /* Did we wake up normally or get interrupted */ if (current->flags & TASK_INTERRUPTED) { + printk("Thread (%d) interrupted on mutex sleep\n", current->tid); current->flags &= ~TASK_INTERRUPTED; return -EINTR; } @@ -140,11 +142,14 @@ int mutex_lock(struct mutex *mutex) } } spin_unlock(&mutex->wqh.slock); + printk("Thread (%d) locked (%p) nlocks: %d\n", current->tid, mutex, current->nlocks); return 0; } static inline void mutex_unlock_common(struct mutex *mutex, int sync) { + struct ktcb *c = current; if (c); + printk("Thread (%d) unlocking (%p) nlocks: %d\n", c->tid, mutex, c->nlocks); spin_lock(&mutex->wqh.slock); __mutex_unlock(&mutex->lock); current->nlocks--; diff --git a/src/lib/wait.c b/src/lib/wait.c index 9fecc9c..c587525 100644 --- a/src/lib/wait.c +++ b/src/lib/wait.c @@ -38,7 +38,7 @@ void task_unset_wqh(struct ktcb *task) /* * Initiate wait on current task that * has already been placed in a waitqueue - * + * * NOTE: This enables preemption and wait_on_prepare() * should be called first. */ @@ -63,7 +63,7 @@ int wait_on_prepared_wait(void) * Do all preparations to sleep but return without sleeping. * This is useful if the task needs to get in the waitqueue before * it releases a lock. - * + * * NOTE: This disables preemption and it should be enabled by a * call to wait_on_prepared_wait() - the other function of the pair. */