Vcore list initialization. (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 12 Sep 2011 22:57:50 +0000 (15:57 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:06 +0000 (17:36 -0700)
There are three lists: active, bulk_preempted, and inactive/yielded.  We
don't use them in this commit; we just get them in place.  They have a
few purposes.  In the long run, it'll help the kernel with bulk
preemption.  For now, it will help with quickly finding a new vcore (no
more scanning from vcore0).  In the middle run, event FALLBACK will be
able to find a destination quickly.

kern/include/env.h
kern/include/process.h
kern/include/ros/procinfo.h
kern/include/sys/queue.h
kern/src/process.c

index c0f43dc..55df6e6 100644 (file)
@@ -20,6 +20,9 @@
 #include <mm.h>
 #include <vfs.h>
 
 #include <mm.h>
 #include <vfs.h>
 
+/* List def for the three vcore lists */
+TAILQ_HEAD(vcore_tailq, vcore);
+
 // TODO: clean this up.
 struct proc {
        TAILQ_ENTRY(proc) proc_link NOINIT;     // Free list link pointers
 // TODO: clean this up.
 struct proc {
        TAILQ_ENTRY(proc) proc_link NOINIT;     // Free list link pointers
@@ -34,6 +37,10 @@ struct proc {
        struct kref p_kref;             /* Refcnt */
        uint32_t env_flags;
        uintptr_t env_entry;
        struct kref p_kref;             /* Refcnt */
        uint32_t env_flags;
        uintptr_t env_entry;
+       /* Lists of vcores */
+       struct vcore_tailq online_vcs;
+       struct vcore_tailq bulk_preempted_vcs;
+       struct vcore_tailq inactive_vcs;
 
        /* Cache color map: bitmap of the cache colors currently allocated to this
         * process */
 
        /* Cache color map: bitmap of the cache colors currently allocated to this
         * process */
index 7000e05..4f399ff 100644 (file)
@@ -87,8 +87,10 @@ void proc_notify(struct proc *p, uint32_t vcoreid);
 
 /* Vcoremap info: */
 uint32_t proc_get_vcoreid(struct proc *SAFE p, uint32_t pcoreid);
 
 /* Vcoremap info: */
 uint32_t proc_get_vcoreid(struct proc *SAFE p, uint32_t pcoreid);
-/* TODO: make this an inline once we gut the Env crap */
+/* TODO: make all of these inline once we gut the Env crap */
 bool vcore_is_mapped(struct proc *p, uint32_t vcoreid);
 bool vcore_is_mapped(struct proc *p, uint32_t vcoreid);
+uint32_t vcore2vcoreid(struct proc *p, struct vcore *vc);
+struct vcore *vcoreid2vcore(struct proc *p, uint32_t vcoreid);
 
 /* Process core management.  Only call these if you are RUNNING_M or RUNNABLE_M.
  * These all adjust the vcoremap and take appropriate actions (like __startcore
 
 /* Process core management.  Only call these if you are RUNNING_M or RUNNABLE_M.
  * These all adjust the vcoremap and take appropriate actions (like __startcore
index 91a0dcb..99cfc1d 100644 (file)
 #define PROCINFO_MAX_ARGP 32
 #define PROCINFO_ARGBUF_SIZE 3072
 
 #define PROCINFO_MAX_ARGP 32
 #define PROCINFO_ARGBUF_SIZE 3072
 
+#ifdef ROS_KERNEL
+#include <sys/queue.h>
+#endif /* ROS_KERNEL */
 
 /* Not necessary to expose all of this, but it doesn't hurt, and is convenient
 
 /* Not necessary to expose all of this, but it doesn't hurt, and is convenient
- * for the kernel. */
+ * for the kernel.  Need to do some acrobatics for the TAILQ_ENTRY. */
+struct vcore;
 struct vcore {
 struct vcore {
+#ifdef ROS_KERNEL
+       TAILQ_ENTRY(vcore)      list;
+#else /* userspace */
+       void                            *dummy_ptr1;
+       void                            *dummy_ptr2;
+#endif /* ROS_KERNEL */
        uint32_t                        pcoreid;
        bool                            valid;
        bool                            preempt_served;
        uint32_t                        pcoreid;
        bool                            valid;
        bool                            preempt_served;
index 841032a..b602f9d 100644 (file)
  *
  */
 #ifdef QUEUE_MACRO_DEBUG
  *
  */
 #ifdef QUEUE_MACRO_DEBUG
+/* ROS has TAILQ-sized elements in a vcore, exposed to userspace via the
+ * vcoremap.  If you have QM tracing turned on, you'll mess it up. */
+#error "Don't use sys/queue QUEUE_MACRO_DEBUG without dealing with the vcoremap"
 /* Store the last 2 places the queue element or head was altered */
 struct qm_trace {
        char * lastfile;
 /* Store the last 2 places the queue element or head was altered */
 struct qm_trace {
        char * lastfile;
index afa5a50..4262ee1 100644 (file)
@@ -184,6 +184,8 @@ struct proc *pid2proc(pid_t pid)
  * any process related function. */
 void proc_init(void)
 {
  * any process related function. */
 void proc_init(void)
 {
+       /* Catch issues with the vcoremap and TAILQ_ENTRY sizes */
+       static_assert(sizeof(TAILQ_ENTRY(vcore)) == sizeof(void*) * 2);
        proc_cache = kmem_cache_create("proc", sizeof(struct proc),
                     MAX(HW_CACHE_ALIGN, __alignof__(struct proc)), 0, 0, 0);
        /* Init PID mask and hash.  pid 0 is reserved. */
        proc_cache = kmem_cache_create("proc", sizeof(struct proc),
                     MAX(HW_CACHE_ALIGN, __alignof__(struct proc)), 0, 0, 0);
        /* Init PID mask and hash.  pid 0 is reserved. */
@@ -238,8 +240,8 @@ void proc_init(void)
        atomic_init(&num_envs, 0);
 }
 
        atomic_init(&num_envs, 0);
 }
 
-void
-proc_init_procinfo(struct proc* p)
+/* Be sure you init'd the vcore lists before calling this. */
+void proc_init_procinfo(struct proc* p)
 {
        memset(&p->procinfo->vcoremap, 0, sizeof(p->procinfo->vcoremap));
        memset(&p->procinfo->pcoremap, 0, sizeof(p->procinfo->pcoremap));
 {
        memset(&p->procinfo->vcoremap, 0, sizeof(p->procinfo->vcoremap));
        memset(&p->procinfo->pcoremap, 0, sizeof(p->procinfo->pcoremap));
@@ -255,6 +257,12 @@ proc_init_procinfo(struct proc* p)
 #else
        p->procinfo->max_vcores = MAX(1,num_cpus-num_mgmtcores);
 #endif /* __CONFIG_DISABLE_SMT__ */
 #else
        p->procinfo->max_vcores = MAX(1,num_cpus-num_mgmtcores);
 #endif /* __CONFIG_DISABLE_SMT__ */
+       /* For now, we'll go up to the max num_cpus (at runtime).  In the future,
+        * there may be cases where we can have more vcores than num_cpus, but for
+        * now we'll leave it like this. */
+       for (int i = 0; i < num_cpus; i++) {
+               TAILQ_INSERT_TAIL(&p->inactive_vcs, &p->procinfo->vcoremap[i], list);
+       }
 }
 
 /* Allocates and initializes a process, with the given parent.  Currently
 }
 
 /* Allocates and initializes a process, with the given parent.  Currently
@@ -299,7 +307,11 @@ error_t proc_alloc(struct proc **pp, struct proc *parent)
        memset(&p->env_ancillary_state, 0, sizeof(p->env_ancillary_state));
        memset(&p->env_tf, 0, sizeof(p->env_tf));
        TAILQ_INIT(&p->vm_regions); /* could init this in the slab */
        memset(&p->env_ancillary_state, 0, sizeof(p->env_ancillary_state));
        memset(&p->env_tf, 0, sizeof(p->env_tf));
        TAILQ_INIT(&p->vm_regions); /* could init this in the slab */
-
+       /* Initialize the vcore lists, we'll build the inactive list so that it includes
+        * all vcores when we initialize procinfo.  Do this before initing procinfo. */
+       TAILQ_INIT(&p->online_vcs);
+       TAILQ_INIT(&p->bulk_preempted_vcs);
+       TAILQ_INIT(&p->inactive_vcs);
        /* Initialize the contents of the e->procinfo structure */
        proc_init_procinfo(p);
        /* Initialize the contents of the e->procdata structure */
        /* Initialize the contents of the e->procinfo structure */
        proc_init_procinfo(p);
        /* Initialize the contents of the e->procdata structure */
@@ -1057,12 +1069,23 @@ uint32_t proc_get_vcoreid(struct proc *SAFE p, uint32_t pcoreid)
        }
 }
 
        }
 }
 
-/* TODO: make this a static inline when we gut the env crap */
+/* TODO: make all of these static inlines when we gut the env crap */
 bool vcore_is_mapped(struct proc *p, uint32_t vcoreid)
 {
        return p->procinfo->vcoremap[vcoreid].valid;
 }
 
 bool vcore_is_mapped(struct proc *p, uint32_t vcoreid)
 {
        return p->procinfo->vcoremap[vcoreid].valid;
 }
 
+/* Can do this, or just create a new field and save it in the vcoremap */
+uint32_t vcore2vcoreid(struct proc *p, struct vcore *vc)
+{
+       return (vc - p->procinfo->vcoremap);
+}
+
+struct vcore *vcoreid2vcore(struct proc *p, uint32_t vcoreid)
+{
+       return &p->procinfo->vcoremap[vcoreid];
+}
+
 /* Gives process p the additional num cores listed in pcorelist.  You must be
  * RUNNABLE_M or RUNNING_M before calling this.  If you're RUNNING_M, this will
  * startup your new cores at the entry point with their virtual IDs (or restore
 /* Gives process p the additional num cores listed in pcorelist.  You must be
  * RUNNABLE_M or RUNNING_M before calling this.  If you're RUNNING_M, this will
  * startup your new cores at the entry point with their virtual IDs (or restore
@@ -1567,6 +1590,7 @@ void print_proc_info(pid_t pid)
 {
        int j = 0;
        struct proc *p = pid2proc(pid);
 {
        int j = 0;
        struct proc *p = pid2proc(pid);
+       struct vcore *vc_i;
        if (!p) {
                printk("Bad PID.\n");
                return;
        if (!p) {
                printk("Bad PID.\n");
                return;
@@ -1581,13 +1605,23 @@ void print_proc_info(pid_t pid)
        printk("Flags: 0x%08x\n", p->env_flags);
        printk("CR3(phys): 0x%08x\n", p->env_cr3);
        printk("Num Vcores: %d\n", p->procinfo->num_vcores);
        printk("Flags: 0x%08x\n", p->env_flags);
        printk("CR3(phys): 0x%08x\n", p->env_cr3);
        printk("Num Vcores: %d\n", p->procinfo->num_vcores);
-       printk("Vcoremap:\n");
+       printk("Vcoremap (old style):\n");
        for (int i = 0; i < p->procinfo->num_vcores; i++) {
                j = get_busy_vcoreid(p, j);
                printk("\tVcore %d: Pcore %d\n", j, get_pcoreid(p, j));
                j++;
        }
        for (int i = 0; i < p->procinfo->num_vcores; i++) {
                j = get_busy_vcoreid(p, j);
                printk("\tVcore %d: Pcore %d\n", j, get_pcoreid(p, j));
                j++;
        }
-       printk("Resources:\n");
+       printk("Vcore Lists:\n----------------------\n");
+       printk("Online:\n");
+       TAILQ_FOREACH(vc_i, &p->online_vcs, list)
+               printk("\tVcore %d -> Pcore %d\n", vcore2vcoreid(p, vc_i), vc_i->pcoreid);
+       printk("Bulk Preempted:\n");
+       TAILQ_FOREACH(vc_i, &p->bulk_preempted_vcs, list)
+               printk("\tVcore %d\n", vcore2vcoreid(p, vc_i));
+       printk("Inactive / Yielded:\n");
+       TAILQ_FOREACH(vc_i, &p->inactive_vcs, list)
+               printk("\tVcore %d\n", vcore2vcoreid(p, vc_i));
+       printk("Resources:\n------------------------\n");
        for (int i = 0; i < MAX_NUM_RESOURCES; i++)
                printk("\tRes type: %02d, amt wanted: %08d, amt granted: %08d\n", i,
                       p->resources[i].amt_wanted, p->resources[i].amt_granted);
        for (int i = 0; i < MAX_NUM_RESOURCES; i++)
                printk("\tRes type: %02d, amt wanted: %08d, amt granted: %08d\n", i,
                       p->resources[i].amt_wanted, p->resources[i].amt_granted);