diff --git a/include/l4/generic/resource.h b/include/l4/generic/resource.h index 68d4abc..8beef1d 100644 --- a/include/l4/generic/resource.h +++ b/include/l4/generic/resource.h @@ -44,7 +44,7 @@ container_head_init(struct container_head *chead) /* Hash table for all existing tasks */ struct ktcb_list { struct link list; - struct mutex list_lock; + struct spinlock list_lock; int count; }; diff --git a/include/l4/generic/tcb.h b/include/l4/generic/tcb.h index 0b2051c..c662ac7 100644 --- a/include/l4/generic/tcb.h +++ b/include/l4/generic/tcb.h @@ -80,7 +80,8 @@ struct ktcb { enum task_state state; struct link task_list; /* Global task list. */ - struct ktcb_list task_dead; /* List of dead children */ + struct link task_dead_list; /* List of dead children */ + struct mutex task_dead_mutex; /* Dead children list mutex */ /* UTCB related, see utcb.txt in docs */ unsigned long utcb_address; /* Virtual ref to task's utcb area */ @@ -156,7 +157,6 @@ void tcb_delete(struct ktcb *tcb); void ktcb_list_add(struct ktcb *new, struct ktcb_list *ktcb_list); -void __ktcb_list_add_nolock(struct ktcb *new, struct ktcb_list *ktcb_list); void init_ktcb_list(struct ktcb_list *ktcb_list); void task_update_utcb(struct ktcb *task); int tcb_check_and_lazy_map_utcb(struct ktcb *task); diff --git a/src/api/thread.c b/src/api/thread.c index 5b05ddb..1ee748c 100644 --- a/src/api/thread.c +++ b/src/api/thread.c @@ -184,29 +184,29 @@ void thread_destroy_current(void) struct ktcb *task, *n; /* Signal death to all threads under control of this pager */ - mutex_lock(&curcont->ktcb_list.list_lock); + spin_lock(&curcont->ktcb_list.list_lock); list_foreach_removable_struct(task, n, &curcont->ktcb_list.list, task_list) { if (task->tid == current->tid || task->pagerid != current->tid) continue; - mutex_unlock(&curcont->ktcb_list.list_lock); + spin_unlock(&curcont->ktcb_list.list_lock); /* Here we wait for each to die */ thread_suspend(task, TASK_EXITING); - mutex_lock(&curcont->ktcb_list.list_lock); + spin_lock(&curcont->ktcb_list.list_lock); } - mutex_unlock(&curcont->ktcb_list.list_lock); + spin_unlock(&curcont->ktcb_list.list_lock); /* Destroy all children */ - mutex_lock(¤t->task_dead.list_lock); + mutex_lock(¤t->task_dead_mutex); list_foreach_removable_struct(task, n, - ¤t->task_dead.list, + ¤t->task_dead_list, task_list) { tcb_delete(task); } - mutex_unlock(¤t->task_dead.list_lock); + mutex_unlock(¤t->task_dead_mutex); /* Destroy self */ sched_die_sync(); diff --git a/src/arch/arm/exception.c b/src/arch/arm/exception.c index 853fa6d..c4a1959 100644 --- a/src/arch/arm/exception.c +++ b/src/arch/arm/exception.c @@ -308,6 +308,7 @@ void dump_undef_abort(u32 undef_addr) { dprintk("Undefined instruction at address: ", undef_addr); printascii("Halting system...\n"); + BUG(); } extern int current_irq_nest_count; diff --git a/src/generic/scheduler.c b/src/generic/scheduler.c index ddfa314..7f92c7c 100644 --- a/src/generic/scheduler.c +++ b/src/generic/scheduler.c @@ -262,6 +262,7 @@ void tcb_delete_schedule(void) */ void sched_die_pager(void) { + printk("Pager (%d) Exiting...\n", current->tid); /* Remove from its list, callers get -ESRCH */ tcb_remove(current); @@ -301,7 +302,7 @@ void sched_die_pager(void) */ void sched_die_child(void) { - int err; + int locked; /* * Find pager, he _must_ be there because he never @@ -309,9 +310,10 @@ void sched_die_child(void) */ struct ktcb *pager = tcb_find(current->pagerid); - /* Lock its task_dead queue */ - if ((err = mutex_lock(&pager->task_dead.list_lock)) < 0) - return err; + do { + /* Busy spin without disabling preemption */ + locked = mutex_trylock(&pager->task_dead_mutex); + } while (!locked); /* Remove from container task list, * callers get -ESRCH */ @@ -335,7 +337,7 @@ void sched_die_child(void) * Add self to pager's dead tasks list, * to be deleted by pager */ - __ktcb_list_add_nolock(current, &pager->task_dead); + list_insert(¤t->task_list, &pager->task_dead_list); /* Now quit the scheduler */ preempt_disable(); @@ -356,21 +358,17 @@ void sched_die_child(void) * Unlock task_dead queue, * pager can safely delete us */ - mutex_unlock(&pager->task_dead.list_lock); + mutex_unlock(&pager->task_dead_mutex); schedule(); BUG(); } void sched_die_sync(void) { - /* - * Infinitely retry if mutexes get interrupted - */ - while (1) - if (current->tid == current->pagerid) - sched_die_pager(); - else - sched_die_child(); + if (current->tid == current->pagerid) + sched_die_pager(); + else + sched_die_child(); } /* @@ -397,17 +395,6 @@ void sched_suspend_sync(void) BUG_ON(scheduler.prio_total < 0); preempt_enable(); - /* - * Async wake up any waiting pagers - * - * If we're not a pager, then a pager must have - * signalled us to suspend, and it must have been - * waiting for us to wake it up when we suspend. - * We do it here. - * - * If though, we _are_ a pager that is suspending, - * we silently do so. Noone is waiting us. - */ if (current->pagerid != current->tid) wake_up(¤t->wqh_pager, 0); @@ -426,17 +413,6 @@ void sched_suspend_async(void) /* This will make sure we yield soon */ preempt_enable(); - /* - * Async wake up any waiting pagers - * - * If we're not a pager, then a pager must have - * signalled us to suspend, and it must have been - * waiting for us to wake it up when we suspend. - * We do it here. - * - * If though, we _are_ a pager that is suspending, - * we silently do so. Noone is waiting us. - */ if (current->pagerid != current->tid) wake_up_task(tcb_find(current->pagerid), 0); diff --git a/src/generic/tcb.c b/src/generic/tcb.c index 42b2bc6..bc6832d 100644 --- a/src/generic/tcb.c +++ b/src/generic/tcb.c @@ -20,7 +20,7 @@ void init_ktcb_list(struct ktcb_list *ktcb_list) { memset(ktcb_list, 0, sizeof(*ktcb_list)); - mutex_init(&ktcb_list->list_lock); + spin_lock_init(&ktcb_list->list_lock); link_init(&ktcb_list->list); } @@ -30,8 +30,8 @@ void tcb_init(struct ktcb *new) link_init(&new->task_list); mutex_init(&new->thread_control_lock); - init_ktcb_list(&new->task_dead); - + mutex_init(&new->task_dead_mutex); + link_init(&new->task_dead_list); cap_list_init(&new->cap_list); /* Initialise task's scheduling state and parameters. */ @@ -104,14 +104,14 @@ struct ktcb *tcb_find_by_space(l4id_t spid) { struct ktcb *task; - mutex_lock(&curcont->ktcb_list.list_lock); + spin_lock(&curcont->ktcb_list.list_lock); list_foreach_struct(task, &curcont->ktcb_list.list, task_list) { if (task->space->spid == spid) { - mutex_unlock(&curcont->ktcb_list.list_lock); + spin_unlock(&curcont->ktcb_list.list_lock); return task; } } - mutex_unlock(&curcont->ktcb_list.list_lock); + spin_unlock(&curcont->ktcb_list.list_lock); return 0; } @@ -122,51 +122,44 @@ struct ktcb *tcb_find(l4id_t tid) if (current->tid == tid) return current; - mutex_lock(&curcont->ktcb_list.list_lock); + spin_lock(&curcont->ktcb_list.list_lock); list_foreach_struct(task, &curcont->ktcb_list.list, task_list) { if (task->tid == tid) { - mutex_unlock(&curcont->ktcb_list.list_lock); + spin_unlock(&curcont->ktcb_list.list_lock); return task; } } - mutex_unlock(&curcont->ktcb_list.list_lock); + spin_unlock(&curcont->ktcb_list.list_lock); return 0; } void ktcb_list_add(struct ktcb *new, struct ktcb_list *ktcb_list) { - mutex_lock(&ktcb_list->list_lock); - BUG_ON(!list_empty(&new->task_list)); - BUG_ON(!++ktcb_list->count); - list_insert(&new->task_list, &ktcb_list->list); - mutex_unlock(&ktcb_list->list_lock); -} - -void __ktcb_list_add_nolock(struct ktcb *new, struct ktcb_list *ktcb_list) -{ + spin_lock(&ktcb_list->list_lock); BUG_ON(!list_empty(&new->task_list)); BUG_ON(!++ktcb_list->count); list_insert(&new->task_list, &ktcb_list->list); + spin_unlock(&ktcb_list->list_lock); } void tcb_add(struct ktcb *new) { struct container *c = new->container; - mutex_lock(&c->ktcb_list.list_lock); + spin_lock(&c->ktcb_list.list_lock); BUG_ON(!list_empty(&new->task_list)); BUG_ON(!++c->ktcb_list.count); list_insert(&new->task_list, &c->ktcb_list.list); - mutex_unlock(&c->ktcb_list.list_lock); + spin_unlock(&c->ktcb_list.list_lock); } void tcb_remove(struct ktcb *new) { - mutex_lock(&curcont->ktcb_list.list_lock); + spin_lock(&curcont->ktcb_list.list_lock); BUG_ON(list_empty(&new->task_list)); BUG_ON(--curcont->ktcb_list.count < 0); list_remove_init(&new->task_list); - mutex_unlock(&curcont->ktcb_list.list_lock); + spin_unlock(&curcont->ktcb_list.list_lock); } /* Offsets for ktcb fields that are accessed from assembler */ diff --git a/src/lib/mutex.c b/src/lib/mutex.c index 4cd0eb5..8b39ba2 100644 --- a/src/lib/mutex.c +++ b/src/lib/mutex.c @@ -132,7 +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); + printk("XXXXXXXXXXXXXXXX (%d) Interrupted\n", current->tid); current->flags &= ~TASK_INTERRUPTED; return -EINTR; }