From 89d49ef4951833f62cde2a4874fd0496ffc194dd Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Fri, 23 Oct 2009 02:36:12 +0300 Subject: [PATCH] Lots of fixes, notion of pager hierarchy, fixed tgroup capability checking Notion of pager hierarchy introduced using the existing but unused pagerid field. Thread creation now has two more flags TC_AS_PAGER and TC_SHARE_PAGER. The former sets creator as pager, the latter sets creator's pager as pager. Thread group capability sharing now correctly carries shared capabilities to the thread group leader's tgr_cap_list list, and this list is checked during capability checking. --- include/l4/api/capability.h | 1 + include/l4/api/thread.h | 3 ++- include/l4/generic/tcb.h | 4 ++-- src/api/capability.c | 2 +- src/api/thread.c | 38 +++++++++++++++++++++++++++---------- src/generic/capability.c | 6 +++++- src/generic/container.c | 1 + src/generic/tcb.c | 4 ++++ 8 files changed, 44 insertions(+), 15 deletions(-) diff --git a/include/l4/api/capability.h b/include/l4/api/capability.h index 883b1a4..5368daf 100644 --- a/include/l4/api/capability.h +++ b/include/l4/api/capability.h @@ -14,5 +14,6 @@ #define CAP_SHARE_SPACE 1 #define CAP_SHARE_CONTAINER 2 #define CAP_SHARE_GROUP 4 +#define CAP_SHARE_PAGED 8 /* All that we are pager of */ #endif /* __API_CAPABILITY_H__ */ diff --git a/include/l4/api/thread.h b/include/l4/api/thread.h index f885abc..fea9274 100644 --- a/include/l4/api/thread.h +++ b/include/l4/api/thread.h @@ -9,7 +9,7 @@ #define THREAD_DESTROY 0x0004 #define THREAD_RECYCLE 0x0005 -#define THREAD_CREATE_MASK 0x03F0 +#define THREAD_CREATE_MASK 0x07F0 #define TC_SHARE_CAPS 0x0010 /* Share all thread capabilities */ #define TC_SHARE_UTCB 0x0020 /* Share utcb location (same space */ #define TC_SHARE_GROUP 0x0040 /* Share thread group id */ @@ -17,5 +17,6 @@ #define TC_COPY_SPACE 0x0100 /* New thread, copy given space */ #define TC_NEW_SPACE 0x0200 /* New thread, new space */ #define TC_SHARE_PAGER 0x0400 /* New thread, shared pager */ +#define TC_AS_PAGER 0x0800 /* Set new thread as child */ #endif /* __THREAD_H__ */ diff --git a/include/l4/generic/tcb.h b/include/l4/generic/tcb.h index 19babdc..4376088 100644 --- a/include/l4/generic/tcb.h +++ b/include/l4/generic/tcb.h @@ -60,10 +60,9 @@ struct ktcb { struct link rq_list; struct runqueue *rq; - /* Thread information */ + /* Thread Id information (See space for space id) */ l4id_t tid; /* Global thread id */ l4id_t tgid; /* Global thread group id */ - /* See space for space id */ /* Flags to indicate various task status */ unsigned int flags; @@ -105,6 +104,7 @@ struct ktcb { /* Capability lists */ struct cap_list cap_list; struct cap_list tgr_cap_list; + struct cap_list pager_cap_list; /* Fields for ipc rendezvous */ struct waitqueue_head wqh_recv; diff --git a/src/api/capability.c b/src/api/capability.c index cd0617d..1c50e77 100644 --- a/src/api/capability.c +++ b/src/api/capability.c @@ -68,7 +68,7 @@ int capability_share(unsigned int share_flags) struct ktcb *tgr_leader; BUG_ON(!(tgr_leader = tcb_find(current->tgid))); - cap_list_move(&tgr_leader->cap_list, + cap_list_move(&tgr_leader->tgr_cap_list, ¤t->cap_list); break; } diff --git a/src/api/thread.c b/src/api/thread.c index ff831e3..50e1d26 100644 --- a/src/api/thread.c +++ b/src/api/thread.c @@ -191,7 +191,8 @@ void task_destroy_current(void) list_foreach_removable_struct(task, n, &curcont->ktcb_list.list, task_list) { - if (task->tid == current->tid) + if (task->tid == current->tid || + task->pagerid != current->tid) continue; spin_unlock(&curcont->ktcb_list.list_lock); task_suspend(task, TASK_EXITING); @@ -342,7 +343,7 @@ out: int thread_create(struct task_ids *ids, unsigned int flags) { struct ktcb *new; - struct ktcb *parent = 0; + struct ktcb *orig = 0; int err; /* Clear flags to just include creation flags */ @@ -353,6 +354,10 @@ int thread_create(struct task_ids *ids, unsigned int flags) & TC_COPY_SPACE & TC_NEW_SPACE) || !flags) return -EINVAL; + /* Can't have multiple pager specifiers */ + if (flags & TC_SHARE_PAGER & TC_AS_PAGER) + return -EINVAL; + /* Can't request shared utcb or tgid without shared space */ if (!(flags & TC_SHARE_SPACE)) { if ((flags & TC_SHARE_UTCB) || @@ -370,28 +375,41 @@ int thread_create(struct task_ids *ids, unsigned int flags) /* Obtain parent thread if there is one */ if (flags & TC_SHARE_SPACE || flags & TC_COPY_SPACE) { - if (!(parent = tcb_find(ids->tid))) { + if (!(orig = tcb_find(ids->tid))) { err = -EINVAL; goto out_err; } } /* - * Setup container-generic fields from current task + * Note this is a kernel-level relationship + * between the creator and the new thread. * - * NOTE: If a new container is created, this needs - * to assign the new pager and container + * Any higher layer may define parent/child + * relationships between orig and new separately. + */ + if (flags & TC_AS_PAGER) + new->pagerid = current->tid; + else if (flags & TC_SHARE_PAGER) + new->pagerid = current->pagerid; + else + new->pagerid = new->tid; + + /* + * Setup container-generic fields from current task */ - new->pagerid = current->pagerid; - new->pager = current->pager; new->container = current->container; /* Set up new thread context by using parent ids and flags */ - thread_setup_new_ids(ids, flags, new, parent); - arch_setup_new_thread(new, parent, flags); + thread_setup_new_ids(ids, flags, new, orig); + arch_setup_new_thread(new, orig, flags); tcb_add(new); + //printk("%s: %d created: %d, %d, %d \n", + // __FUNCTION__, current->tid, ids->tid, + // ids->tgid, ids->spid); + return 0; out_err: diff --git a/src/generic/capability.c b/src/generic/capability.c index b2d7ef0..a7a56a6 100644 --- a/src/generic/capability.c +++ b/src/generic/capability.c @@ -81,6 +81,7 @@ struct capability *capability_find_by_rtype(struct ktcb *task, unsigned int rtype) { struct capability *cap; + struct ktcb *tgleader; /* Search task's own list */ list_foreach_struct(cap, &task->cap_list.caps, list) @@ -92,8 +93,11 @@ struct capability *capability_find_by_rtype(struct ktcb *task, if (cap_rtype(cap) == rtype) return cap; + /* Find group leader */ + BUG_ON(!(tgleader = tcb_find(task->tgid))); + /* Search thread group list */ - list_foreach_struct(cap, &task->tgr_cap_list.caps, list) + list_foreach_struct(cap, &tgleader->tgr_cap_list.caps, list) if (cap_rtype(cap) == rtype) return cap; diff --git a/src/generic/container.c b/src/generic/container.c index 77b1d4a..b26c416 100644 --- a/src/generic/container.c +++ b/src/generic/container.c @@ -112,6 +112,7 @@ int init_pager(struct pager *pager, pager->tcb = task; task->pager = pager; task->pagerid = task->tid; + task->tgid = task->tid; task->container = cont; /* Initialize uninitialized capability fields while on dummy */ diff --git a/src/generic/tcb.c b/src/generic/tcb.c index 6a5aa9b..61592e6 100644 --- a/src/generic/tcb.c +++ b/src/generic/tcb.c @@ -32,6 +32,7 @@ void tcb_init(struct ktcb *new) cap_list_init(&new->cap_list); cap_list_init(&new->tgr_cap_list); + cap_list_init(&new->pager_cap_list); /* Initialise task's scheduling state and parameters. */ sched_init_task(new, TASK_PRIO_NORMAL); @@ -117,6 +118,9 @@ struct ktcb *tcb_find(l4id_t tid) { struct ktcb *task; + if (current->tid == tid) + return current; + spin_lock(&curcont->ktcb_list.list_lock); list_foreach_struct(task, &curcont->ktcb_list.list, task_list) { if (task->tid == tid) {