mirror of
https://github.com/drasko/codezero.git
synced 2026-02-27 09:13:13 +01:00
Some not-very-well working progress on grouply exit.
Going to start from scratch.
This commit is contained in:
@@ -44,7 +44,7 @@ container_head_init(struct container_head *chead)
|
|||||||
/* Hash table for all existing tasks */
|
/* Hash table for all existing tasks */
|
||||||
struct ktcb_list {
|
struct ktcb_list {
|
||||||
struct link list;
|
struct link list;
|
||||||
struct mutex list_lock;
|
struct spinlock list_lock;
|
||||||
int count;
|
int count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,8 @@ struct ktcb {
|
|||||||
enum task_state state;
|
enum task_state state;
|
||||||
|
|
||||||
struct link task_list; /* Global task list. */
|
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 */
|
/* UTCB related, see utcb.txt in docs */
|
||||||
unsigned long utcb_address; /* Virtual ref to task's utcb area */
|
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(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 init_ktcb_list(struct ktcb_list *ktcb_list);
|
||||||
void task_update_utcb(struct ktcb *task);
|
void task_update_utcb(struct ktcb *task);
|
||||||
int tcb_check_and_lazy_map_utcb(struct ktcb *task);
|
int tcb_check_and_lazy_map_utcb(struct ktcb *task);
|
||||||
|
|||||||
@@ -184,29 +184,29 @@ void thread_destroy_current(void)
|
|||||||
struct ktcb *task, *n;
|
struct ktcb *task, *n;
|
||||||
|
|
||||||
/* Signal death to all threads under control of this pager */
|
/* 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,
|
list_foreach_removable_struct(task, n,
|
||||||
&curcont->ktcb_list.list,
|
&curcont->ktcb_list.list,
|
||||||
task_list) {
|
task_list) {
|
||||||
if (task->tid == current->tid ||
|
if (task->tid == current->tid ||
|
||||||
task->pagerid != current->tid)
|
task->pagerid != current->tid)
|
||||||
continue;
|
continue;
|
||||||
mutex_unlock(&curcont->ktcb_list.list_lock);
|
spin_unlock(&curcont->ktcb_list.list_lock);
|
||||||
|
|
||||||
/* Here we wait for each to die */
|
/* Here we wait for each to die */
|
||||||
thread_suspend(task, TASK_EXITING);
|
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 */
|
/* Destroy all children */
|
||||||
mutex_lock(¤t->task_dead.list_lock);
|
mutex_lock(¤t->task_dead_mutex);
|
||||||
list_foreach_removable_struct(task, n,
|
list_foreach_removable_struct(task, n,
|
||||||
¤t->task_dead.list,
|
¤t->task_dead_list,
|
||||||
task_list) {
|
task_list) {
|
||||||
tcb_delete(task);
|
tcb_delete(task);
|
||||||
}
|
}
|
||||||
mutex_unlock(¤t->task_dead.list_lock);
|
mutex_unlock(¤t->task_dead_mutex);
|
||||||
|
|
||||||
/* Destroy self */
|
/* Destroy self */
|
||||||
sched_die_sync();
|
sched_die_sync();
|
||||||
|
|||||||
@@ -308,6 +308,7 @@ void dump_undef_abort(u32 undef_addr)
|
|||||||
{
|
{
|
||||||
dprintk("Undefined instruction at address: ", undef_addr);
|
dprintk("Undefined instruction at address: ", undef_addr);
|
||||||
printascii("Halting system...\n");
|
printascii("Halting system...\n");
|
||||||
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int current_irq_nest_count;
|
extern int current_irq_nest_count;
|
||||||
|
|||||||
@@ -262,6 +262,7 @@ void tcb_delete_schedule(void)
|
|||||||
*/
|
*/
|
||||||
void sched_die_pager(void)
|
void sched_die_pager(void)
|
||||||
{
|
{
|
||||||
|
printk("Pager (%d) Exiting...\n", current->tid);
|
||||||
/* Remove from its list, callers get -ESRCH */
|
/* Remove from its list, callers get -ESRCH */
|
||||||
tcb_remove(current);
|
tcb_remove(current);
|
||||||
|
|
||||||
@@ -301,7 +302,7 @@ void sched_die_pager(void)
|
|||||||
*/
|
*/
|
||||||
void sched_die_child(void)
|
void sched_die_child(void)
|
||||||
{
|
{
|
||||||
int err;
|
int locked;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find pager, he _must_ be there because he never
|
* 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);
|
struct ktcb *pager = tcb_find(current->pagerid);
|
||||||
|
|
||||||
/* Lock its task_dead queue */
|
do {
|
||||||
if ((err = mutex_lock(&pager->task_dead.list_lock)) < 0)
|
/* Busy spin without disabling preemption */
|
||||||
return err;
|
locked = mutex_trylock(&pager->task_dead_mutex);
|
||||||
|
} while (!locked);
|
||||||
|
|
||||||
/* Remove from container task list,
|
/* Remove from container task list,
|
||||||
* callers get -ESRCH */
|
* callers get -ESRCH */
|
||||||
@@ -335,7 +337,7 @@ void sched_die_child(void)
|
|||||||
* Add self to pager's dead tasks list,
|
* Add self to pager's dead tasks list,
|
||||||
* to be deleted by pager
|
* 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 */
|
/* Now quit the scheduler */
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
@@ -356,21 +358,17 @@ void sched_die_child(void)
|
|||||||
* Unlock task_dead queue,
|
* Unlock task_dead queue,
|
||||||
* pager can safely delete us
|
* pager can safely delete us
|
||||||
*/
|
*/
|
||||||
mutex_unlock(&pager->task_dead.list_lock);
|
mutex_unlock(&pager->task_dead_mutex);
|
||||||
schedule();
|
schedule();
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sched_die_sync(void)
|
void sched_die_sync(void)
|
||||||
{
|
{
|
||||||
/*
|
if (current->tid == current->pagerid)
|
||||||
* Infinitely retry if mutexes get interrupted
|
sched_die_pager();
|
||||||
*/
|
else
|
||||||
while (1)
|
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);
|
BUG_ON(scheduler.prio_total < 0);
|
||||||
preempt_enable();
|
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)
|
if (current->pagerid != current->tid)
|
||||||
wake_up(¤t->wqh_pager, 0);
|
wake_up(¤t->wqh_pager, 0);
|
||||||
|
|
||||||
@@ -426,17 +413,6 @@ void sched_suspend_async(void)
|
|||||||
/* This will make sure we yield soon */
|
/* This will make sure we yield soon */
|
||||||
preempt_enable();
|
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)
|
if (current->pagerid != current->tid)
|
||||||
wake_up_task(tcb_find(current->pagerid), 0);
|
wake_up_task(tcb_find(current->pagerid), 0);
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
void init_ktcb_list(struct ktcb_list *ktcb_list)
|
void init_ktcb_list(struct ktcb_list *ktcb_list)
|
||||||
{
|
{
|
||||||
memset(ktcb_list, 0, sizeof(*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);
|
link_init(&ktcb_list->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,8 +30,8 @@ void tcb_init(struct ktcb *new)
|
|||||||
link_init(&new->task_list);
|
link_init(&new->task_list);
|
||||||
mutex_init(&new->thread_control_lock);
|
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);
|
cap_list_init(&new->cap_list);
|
||||||
|
|
||||||
/* Initialise task's scheduling state and parameters. */
|
/* Initialise task's scheduling state and parameters. */
|
||||||
@@ -104,14 +104,14 @@ struct ktcb *tcb_find_by_space(l4id_t spid)
|
|||||||
{
|
{
|
||||||
struct ktcb *task;
|
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) {
|
list_foreach_struct(task, &curcont->ktcb_list.list, task_list) {
|
||||||
if (task->space->spid == spid) {
|
if (task->space->spid == spid) {
|
||||||
mutex_unlock(&curcont->ktcb_list.list_lock);
|
spin_unlock(&curcont->ktcb_list.list_lock);
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&curcont->ktcb_list.list_lock);
|
spin_unlock(&curcont->ktcb_list.list_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,51 +122,44 @@ struct ktcb *tcb_find(l4id_t tid)
|
|||||||
if (current->tid == tid)
|
if (current->tid == tid)
|
||||||
return current;
|
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) {
|
list_foreach_struct(task, &curcont->ktcb_list.list, task_list) {
|
||||||
if (task->tid == tid) {
|
if (task->tid == tid) {
|
||||||
mutex_unlock(&curcont->ktcb_list.list_lock);
|
spin_unlock(&curcont->ktcb_list.list_lock);
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&curcont->ktcb_list.list_lock);
|
spin_unlock(&curcont->ktcb_list.list_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ktcb_list_add(struct ktcb *new, struct ktcb_list *ktcb_list)
|
void ktcb_list_add(struct ktcb *new, struct ktcb_list *ktcb_list)
|
||||||
{
|
{
|
||||||
mutex_lock(&ktcb_list->list_lock);
|
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);
|
|
||||||
mutex_unlock(&ktcb_list->list_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __ktcb_list_add_nolock(struct ktcb *new, struct ktcb_list *ktcb_list)
|
|
||||||
{
|
|
||||||
BUG_ON(!list_empty(&new->task_list));
|
BUG_ON(!list_empty(&new->task_list));
|
||||||
BUG_ON(!++ktcb_list->count);
|
BUG_ON(!++ktcb_list->count);
|
||||||
list_insert(&new->task_list, &ktcb_list->list);
|
list_insert(&new->task_list, &ktcb_list->list);
|
||||||
|
spin_unlock(&ktcb_list->list_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcb_add(struct ktcb *new)
|
void tcb_add(struct ktcb *new)
|
||||||
{
|
{
|
||||||
struct container *c = new->container;
|
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(!list_empty(&new->task_list));
|
||||||
BUG_ON(!++c->ktcb_list.count);
|
BUG_ON(!++c->ktcb_list.count);
|
||||||
list_insert(&new->task_list, &c->ktcb_list.list);
|
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)
|
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(list_empty(&new->task_list));
|
||||||
BUG_ON(--curcont->ktcb_list.count < 0);
|
BUG_ON(--curcont->ktcb_list.count < 0);
|
||||||
list_remove_init(&new->task_list);
|
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 */
|
/* Offsets for ktcb fields that are accessed from assembler */
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ int mutex_lock(struct mutex *mutex)
|
|||||||
|
|
||||||
/* Did we wake up normally or get interrupted */
|
/* Did we wake up normally or get interrupted */
|
||||||
if (current->flags & TASK_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;
|
current->flags &= ~TASK_INTERRUPTED;
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user