l4_exit() works with a reasonable sched_die_sync()

Next: Killing other tasks more cleanly, and waiting on children
This commit is contained in:
Bahadir Balban
2009-10-29 22:44:58 +02:00
parent 73a27f2269
commit a6c61e05b9
9 changed files with 121 additions and 16 deletions
+43 -1
View File
@@ -8,13 +8,55 @@
#include <capability.h> #include <capability.h>
#include <thread.h> #include <thread.h>
#include <tests.h> #include <tests.h>
#include <l4lib/arch/syslib.h>
#include <l4lib/arch/syscalls.h>
#include <l4/api/space.h>
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) int main(void)
{ {
printf("%s: Container %s started\n", printf("%s: Container %s started\n",
__CONTAINER__, __CONTAINER_NAME__); __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; return 0;
} }
+1 -2
View File
@@ -85,8 +85,7 @@ int capability_test(void)
*/ */
if ((err = thread_create(simple_pager_thread, if ((err = thread_create(simple_pager_thread,
&TEST_MUST_FAIL, &TEST_MUST_FAIL,
TC_SHARE_SPACE | TC_SHARE_SPACE, &ids)) < 0) {
TC_AS_PAGER, &ids)) < 0) {
printf("Top-level simple_pager creation failed.\n"); printf("Top-level simple_pager creation failed.\n");
goto out_err; goto out_err;
} }
+1
View File
@@ -60,6 +60,7 @@ extern struct scheduler scheduler;
void sched_init_runqueue(struct runqueue *rq); void sched_init_runqueue(struct runqueue *rq);
void sched_init_task(struct ktcb *task, int priority); void sched_init_task(struct ktcb *task, int priority);
void sched_prepare_sleep(void); void sched_prepare_sleep(void);
void sched_die_sync(void);
void sched_suspend_sync(void); void sched_suspend_sync(void);
void sched_suspend_async(void); void sched_suspend_async(void);
void sched_resume_sync(struct ktcb *task); void sched_resume_sync(struct ktcb *task);
+5 -6
View File
@@ -64,6 +64,9 @@ struct ktcb {
l4id_t tid; /* Global thread id */ l4id_t tid; /* Global thread id */
l4id_t tgid; /* Global thread group id */ l4id_t tgid; /* Global thread group id */
/* Other related threads */
l4id_t pagerid;
/* Flags to indicate various task status */ /* Flags to indicate various task status */
unsigned int flags; unsigned int flags;
@@ -73,11 +76,9 @@ struct ktcb {
/* Lock for blocking thread state modifications via a syscall */ /* Lock for blocking thread state modifications via a syscall */
struct mutex thread_control_lock; struct mutex thread_control_lock;
/* Other related threads */
l4id_t pagerid;
u32 ts_need_resched; /* Scheduling flag */ u32 ts_need_resched; /* Scheduling flag */
enum task_state state; enum task_state state;
struct link task_list; /* Global task list. */ struct link task_list; /* Global task list. */
/* UTCB related, see utcb.txt in docs */ /* UTCB related, see utcb.txt in docs */
@@ -102,9 +103,7 @@ struct ktcb {
struct pager *pager; struct pager *pager;
/* Capability lists */ /* Capability lists */
struct cap_list cap_list; /* Own private capabilities */ 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 */
/* Fields for ipc rendezvous */ /* Fields for ipc rendezvous */
struct waitqueue_head wqh_recv; struct waitqueue_head wqh_recv;
+2
View File
@@ -68,6 +68,7 @@ int capability_share(unsigned int share_flags)
cap_list_move(&curcont->cap_list, cap_list_move(&curcont->cap_list,
&current->cap_list); &current->cap_list);
break; break;
#if 0
case CAP_SHARE_CHILD: case CAP_SHARE_CHILD:
/* /*
* Move own capabilities to paged-children * Move own capabilities to paged-children
@@ -97,6 +98,7 @@ int capability_share(unsigned int share_flags)
&current->cap_list); &current->cap_list);
break; break;
} }
#endif
default: default:
return -EINVAL; return -EINVAL;
} }
+1 -1
View File
@@ -200,7 +200,7 @@ void thread_destroy_current(void)
/* Indicate we want to become zombie on suspend */ /* Indicate we want to become zombie on suspend */
current->flags |= TASK_EXITING; current->flags |= TASK_EXITING;
sched_suspend_sync(); sched_die_sync();
} }
/* Runs a thread for the first time */ /* Runs a thread for the first time */
+2 -2
View File
@@ -144,8 +144,8 @@ int init_pager(struct pager *pager,
page_align_up(pager->memsize), page_align_up(pager->memsize),
MAP_USR_DEFAULT_FLAGS, TASK_PGD(task)); MAP_USR_DEFAULT_FLAGS, TASK_PGD(task));
/* Move capability list from dummy to task's cap list */ /* Move capability list from dummy to task's space cap list */
cap_list_move(&task->cap_list, &current->cap_list); cap_list_move(&task->space->cap_list, &current->cap_list);
/* Initialize task scheduler parameters */ /* Initialize task scheduler parameters */
sched_init_task(task, TASK_PRIO_PAGER); sched_init_task(task, TASK_PRIO_PAGER);
+64
View File
@@ -226,6 +226,70 @@ void sched_resume_async(struct ktcb *task)
RQ_ADD_FRONT); 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(&current->wqh_send, 0);
wake_up_all(&current->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() * NOTE: Could do these as sched_prepare_suspend()
* + schedule() or need_resched = 1 * + schedule() or need_resched = 1
+2 -4
View File
@@ -31,8 +31,6 @@ void tcb_init(struct ktcb *new)
mutex_init(&new->thread_control_lock); mutex_init(&new->thread_control_lock);
cap_list_init(&new->cap_list); 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. */ /* Initialise task's scheduling state and parameters. */
sched_init_task(new, TASK_PRIO_NORMAL); 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_send.sleepers > 0);
BUG_ON(tcb->wqh_recv.sleepers > 0); BUG_ON(tcb->wqh_recv.sleepers > 0);
BUG_ON(!list_empty(&tcb->task_list)); BUG_ON(!list_empty(&tcb->task_list));
BUG_ON(!list_empty(&tcb->rq_list)); BUG_ON(!list_empty(&tcb->rq_list) && tcb != current);
BUG_ON(tcb->rq); BUG_ON(tcb->rq && tcb != current);
BUG_ON(tcb->nlocks); BUG_ON(tcb->nlocks);
BUG_ON(tcb->waiting_on); BUG_ON(tcb->waiting_on);
BUG_ON(tcb->wq); BUG_ON(tcb->wq);