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) {