mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Simultaneous exit/thread_destroy working
Reiterating again to simplify: Working: - Pager issues destroy, client also issues exit they work in sync. Missing - Pager killing itself - Pager killing all children while killing itself - Pager waiting on children
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
int exit_test_thread(void *arg)
|
||||
{
|
||||
l4_thread_switch(0);
|
||||
l4_exit(0);
|
||||
return 0;
|
||||
}
|
||||
@@ -38,11 +39,11 @@ int exit_test(void)
|
||||
/* Kill it */
|
||||
printf("Killing Thread (%d).\n", ids.tid);
|
||||
if ((ret = l4_thread_control(THREAD_DESTROY, &ids)) < 0)
|
||||
printf("Error: Killing Thread (%d)\n", ids.tid);
|
||||
printf("Error: Killing Thread (%d), err = %d\n", ids.tid, ret);
|
||||
else
|
||||
printf("Success: Killed Thread (%d)\n", ids.tid);
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
/* Wait on it */
|
||||
|
||||
@@ -61,7 +61,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_pager_exit(void);
|
||||
void sched_exit_pager(void);
|
||||
void sched_exit_sync(void);
|
||||
void sched_suspend_sync(void);
|
||||
void sched_suspend_async(void);
|
||||
|
||||
@@ -36,6 +36,7 @@ enum task_state {
|
||||
TASK_INACTIVE = 0,
|
||||
TASK_SLEEPING = 1,
|
||||
TASK_RUNNABLE = 2,
|
||||
TASK_DEAD = 3,
|
||||
};
|
||||
|
||||
#define TASK_ID_INVALID -1
|
||||
|
||||
@@ -28,8 +28,8 @@ int sys_thread_switch(void)
|
||||
* doing, and take action on the signal provided. Currently this
|
||||
* may be a suspension or an exit signal.
|
||||
*/
|
||||
int thread_signal_sync(struct ktcb *task, unsigned int flags,
|
||||
unsigned int task_state)
|
||||
int thread_signal(struct ktcb *task, unsigned int flags,
|
||||
unsigned int task_state)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -42,7 +42,7 @@ int thread_signal_sync(struct ktcb *task, unsigned int flags,
|
||||
/* Wake it up if it's sleeping */
|
||||
wake_up_task(task, WAKEUP_INTERRUPT | WAKEUP_SYNC);
|
||||
|
||||
/* Wait until task suspends itself */
|
||||
/* Wait until task switches to desired state */
|
||||
WAIT_EVENT(&task->wqh_pager,
|
||||
task->state == task_state, ret);
|
||||
|
||||
@@ -51,7 +51,36 @@ int thread_signal_sync(struct ktcb *task, unsigned int flags,
|
||||
|
||||
int thread_suspend(struct ktcb *task)
|
||||
{
|
||||
return thread_signal_sync(task, TASK_SUSPENDING, TASK_INACTIVE);
|
||||
return thread_signal(task, TASK_SUSPENDING, TASK_INACTIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Put them in TASK_DEAD so that a suspended exiting thread
|
||||
* does not run again if issued THREAD_RUN
|
||||
*/
|
||||
int thread_destroy(struct ktcb *task)
|
||||
{
|
||||
if (task == current) {
|
||||
if (current->tid == current->pagerid)
|
||||
sched_exit_pager();
|
||||
else
|
||||
sched_suspend_sync();
|
||||
return 0;
|
||||
}
|
||||
|
||||
thread_suspend(task);
|
||||
|
||||
tcb_remove(task);
|
||||
|
||||
/* Wake up waiters */
|
||||
wake_up_all(¤t->wqh_send, 0);
|
||||
wake_up_all(¤t->wqh_recv, 0);
|
||||
|
||||
BUG_ON(task->wqh_pager.sleepers > 0);
|
||||
BUG_ON(task->state != TASK_INACTIVE);
|
||||
|
||||
tcb_delete(task);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_clear_thread(struct ktcb *tcb)
|
||||
@@ -113,57 +142,6 @@ int thread_recycle(struct ktcb *task)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int thread_destroy(struct ktcb *task)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* If we're a self-destructing pager */
|
||||
if (task == current &&
|
||||
current->tid == current->pagerid) {
|
||||
struct ktcb *child, *n;
|
||||
|
||||
/* Make all children exit synchronously */
|
||||
spin_lock(&curcont->ktcb_list.list_lock);
|
||||
list_foreach_removable_struct(child, n,
|
||||
&curcont->ktcb_list.list,
|
||||
task_list) {
|
||||
if (child->pagerid == current->tid &&
|
||||
child != current) {
|
||||
spin_unlock(&curcont->ktcb_list.list_lock);
|
||||
|
||||
/* Its a bug since nobody can interrupt us */
|
||||
BUG_ON(thread_signal_sync(child, TASK_EXITING,
|
||||
TASK_INACTIVE) < 0);
|
||||
spin_lock(&curcont->ktcb_list.list_lock);
|
||||
}
|
||||
}
|
||||
spin_unlock(&curcont->ktcb_list.list_lock);
|
||||
|
||||
/* Delete all exited children */
|
||||
spin_lock(¤t->child_exit_list.list_lock);
|
||||
printk("(%d) To delete %d children\n", current->tid, current->child_exit_list.count);
|
||||
list_foreach_removable_struct(child, n,
|
||||
¤t->child_exit_list.list,
|
||||
task_list) {
|
||||
list_remove(&child->task_list);
|
||||
tcb_delete(child);
|
||||
}
|
||||
spin_unlock(¤t->child_exit_list.list_lock);
|
||||
|
||||
/* Destroy yourself */
|
||||
sched_pager_exit();
|
||||
BUG();
|
||||
}
|
||||
|
||||
if ((ret = thread_signal_sync(task, TASK_EXITING, TASK_INACTIVE)) < 0)
|
||||
return ret;
|
||||
|
||||
ktcb_list_remove(task, ¤t->child_exit_list);
|
||||
tcb_delete(task);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Runs a thread for the first time */
|
||||
int thread_start(struct ktcb *task)
|
||||
{
|
||||
|
||||
@@ -229,7 +229,7 @@ void sched_resume_async(struct ktcb *task)
|
||||
* A self-paging thread deletes itself,
|
||||
* schedules and disappears from the system.
|
||||
*/
|
||||
void sched_pager_exit(void)
|
||||
void sched_exit_pager(void)
|
||||
{
|
||||
// printk("Pager (%d) Exiting...\n", current->tid);
|
||||
/* Remove from its list, callers get -ESRCH */
|
||||
@@ -269,13 +269,6 @@ void sched_exit_sync(void)
|
||||
{
|
||||
struct ktcb *pager = tcb_find(current->pagerid);
|
||||
|
||||
/* Quit global list */
|
||||
tcb_remove(current);
|
||||
|
||||
/* Wake up waiters */
|
||||
wake_up_all(¤t->wqh_send, 0);
|
||||
wake_up_all(¤t->wqh_recv, 0);
|
||||
|
||||
/* Go to exit list */
|
||||
ktcb_list_add(current, &pager->child_exit_list);
|
||||
|
||||
@@ -285,8 +278,8 @@ void sched_exit_sync(void)
|
||||
wake_up(¤t->wqh_pager, 0);
|
||||
|
||||
sched_rq_remove_task(current);
|
||||
current->state = TASK_INACTIVE;
|
||||
current->flags &= ~TASK_SUSPENDING;
|
||||
current->state = TASK_DEAD;
|
||||
current->flags &= ~TASK_EXITING;
|
||||
preempt_enable();
|
||||
|
||||
/* Quit */
|
||||
@@ -294,16 +287,6 @@ void sched_exit_sync(void)
|
||||
BUG();
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* Instead of sched_suspend_sync()
|
||||
* call sched_die_sync() on killer suspends:
|
||||
* (e.g. if also kill flag set, call sched_die_sync instead)
|
||||
* and handle dying on its own and dying over a pager
|
||||
* in there. (e.g. put yourself in a task_dead queue, take
|
||||
* care of pager calling destroy on you, calling wait on you etc.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: Could do these as sched_prepare_suspend()
|
||||
* + schedule() or need_resched = 1
|
||||
@@ -328,12 +311,10 @@ void sched_suspend_async(void)
|
||||
sched_rq_remove_task(current);
|
||||
current->state = TASK_INACTIVE;
|
||||
current->flags &= ~TASK_SUSPENDING;
|
||||
|
||||
/* This will make sure we yield soon */
|
||||
preempt_enable();
|
||||
|
||||
if (current->pagerid != current->tid)
|
||||
wake_up_task(tcb_find(current->pagerid), 0);
|
||||
wake_up(¤t->wqh_pager, 0);
|
||||
|
||||
need_resched = 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user