OSDI Microbenchmarks
[akaros.git] / kern / src / process.c
index f479677..d176b65 100644 (file)
@@ -256,13 +256,6 @@ int fake_proc_alloc(struct proc **pp, struct proc *parent, uint32_t vcoreid)
        error_t r;
        struct proc *p;
 
-       /* So we can call this anytime we want to run a vcore, including vcore0,
-        * which is the true_proc / parent.  Probably horribly broken. */
-       if (!vcoreid) {
-               *pp = parent;
-               return 0;
-       }
-
        if (!(p = kmem_cache_alloc(proc_cache, 0)))
                return -ENOMEM;
 
@@ -284,8 +277,14 @@ int fake_proc_alloc(struct proc **pp, struct proc *parent, uint32_t vcoreid)
        // p->syscallbackring = not happening
        p->true_proc = parent;
        p->vcoreid = vcoreid;
-       /* map us to the true parent vcoremap */
+       /* there is a slight race on the old vcore mapping.  for a brief period, it
+        * is unmapped, but still tracked by the parent.  it's between the unmapping
+        * and the freeing (where the vcore_procs[i] is cleared, which we need to
+        * hold on to until the fake_proc has abandoned core.  a brief spin should
+        * be okay. */
+       spin_on(parent->vcore_procs[vcoreid]);
        assert(!parent->vcore_procs[vcoreid]);
+       /* map us to the true parent vcoremap */
        parent->vcore_procs[vcoreid] = p;
        parent->env_refcnt++;
 
@@ -429,7 +428,7 @@ static void __proc_free(struct proc *p)
                        for (int j = 0; p->vcore_procs[i]; j++) {
                                cpu_relax();
                                if (j == 10000) {
-                                       printd("Core %d stalled while waiting on peep %d\n",
+                                       printk("Core %d stalled while waiting on peep %d\n",
                                               core_id(), i);
                                        //send_kernel_message(p->procinfo->vcoremap[i].pcoreid,
                                        //                    __death, 0, 0, 0, KMSG_ROUTINE);
@@ -470,6 +469,16 @@ static void __proc_free(struct proc *p)
 
        /* Dealloc the struct proc */
        kmem_cache_free(proc_cache, p);
+
+#ifdef __CONFIG_OSDI__ /* for experiment coordination */
+       extern struct proc *mgr_p1, *mgr_p2;
+       /* Signal to the monitor we're done */
+       if (p == mgr_p1)
+               mgr_p1 = 0;
+       if (p == mgr_p2)
+               mgr_p2 = 0;
+       printk("[T]:004:E:%llu\n", read_tsc());
+#endif /* __CONFIG_EXPER_TRADPROC__ */
 }
 
 /* Whether or not actor can control target.  Note we currently don't need
@@ -639,8 +648,10 @@ static void __proc_startcore(struct proc *p, trapframe_t *tf)
         * different context.
         * for now, we load this silly state here. (TODO) (HSS)
         * We also need this to be per trapframe, and not per process...
-        */
-       env_pop_ancillary_state(p);
+        * For now / OSDI, only load it when in _S mode.  _M mode was handled in
+        * __startcore.  */
+       if (p->state == PROC_RUNNING_S)
+               env_pop_ancillary_state(p);
        env_pop_tf(tf);
 }
 
@@ -841,7 +852,7 @@ void proc_yield(struct proc *SAFE p, bool being_nice)
                return;
 
 #ifdef __CONFIG_EXPER_TRADPROC__
-       if (p->state == (PROC_RUNNING_M | PROC_DYING))
+       if (p->state & (PROC_RUNNING_M | PROC_DYING))
                return;
 #endif /* __CONFIG_EXPER_TRADPROC__ */
 
@@ -861,7 +872,7 @@ void proc_yield(struct proc *SAFE p, bool being_nice)
        switch (p->state) {
                case (PROC_RUNNING_S):
                        p->env_tf= *current_tf;
-                       env_push_ancillary_state(p);
+                       env_push_ancillary_state(p); // TODO: (HSS)
                        __proc_set_state(p, PROC_RUNNABLE_S);
                        schedule_proc(p);
                        break;
@@ -1212,8 +1223,6 @@ bool __proc_give_cores(struct proc *SAFE p, uint32_t *pcorelist, size_t num)
                        // add new items to the vcoremap
 #ifdef __CONFIG_EXPER_TRADPROC__
                        __proc_set_state(p, PROC_RUNNING_M);
-                       // want an extra one since res_req jacked on on our transition
-                       p->env_refcnt++;
 #endif /* __CONFIG_EXPER_TRADPROC__ */
                        __seq_start_write(&p->procinfo->coremap_seqctr);
                        for (int i = 0; i < num; i++) {
@@ -1371,7 +1380,7 @@ bool __proc_take_allcores(struct proc *SAFE p, amr_t message,
        __seq_start_write(&p->procinfo->coremap_seqctr);
 #ifdef __CONFIG_EXPER_TRADPROC__
        /* Decref each child, so they will free themselves when they unmap */
-       for (int i = 1; i < MAX_NUM_CPUS; i++) {
+       for (int i = 0; i < MAX_NUM_CPUS; i++) {
                if (p->vcore_procs[i])
                        proc_decref(p->vcore_procs[i], 1);
        }
@@ -1683,19 +1692,23 @@ void print_allpids(void)
 void print_proc_info(pid_t pid)
 {
        int j = 0;
-       struct proc *p = pid2proc(pid);
+       /* Doing this without the incref! careful! (avoiding deadlocks) TODO (REF)*/
+       //struct proc *p = pid2proc(pid);
+       spin_lock(&pid_hash_lock);
+       struct proc *p = hashtable_search(pid_hash, (void*)pid);
+       spin_unlock(&pid_hash_lock);
        // not concerned with a race on the state...
        if (!p) {
                printk("Bad PID.\n");
                return;
        }
        spinlock_debug(&p->proc_lock);
-       spin_lock(&p->proc_lock);
+       //spin_lock(&p->proc_lock); // No locking!!
        printk("struct proc: %p\n", p);
        printk("PID: %d\n", p->pid);
        printk("PPID: %d\n", p->ppid);
        printk("State: 0x%08x\n", p->state);
-       printk("Refcnt: %d\n", p->env_refcnt - 1); // don't report our ref
+       printk("Refcnt: %d\n", p->env_refcnt);
        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);
@@ -1709,9 +1722,31 @@ void print_proc_info(pid_t pid)
        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);
+#ifdef __CONFIG_EXPER_TRADPROC__
+       void print_chain(struct proc *p)
+       {
+               if (!is_real_proc(p)) {
+                       printk("P is not a true_proc, parent is %p\n", p->true_proc);
+                       print_chain(p);
+               } else {
+                       printk("P is a true_proc\n");
+                       for (int i = 0; i < p->procinfo->num_vcores; i++) {
+                               printk("%p's child %d is %p\n", p, i, p->vcore_procs[i]);
+                               if (p->vcore_procs[i])
+                                       for (int j = 0; j < MAX_NUM_CPUS; j++)
+                                               if (p->vcore_procs[i]->vcore_procs[j])
+                                                       printk("Crap, child %p has its own child %p!!\n",
+                                                              p->vcore_procs[i],
+                                                              p->vcore_procs[i]->vcore_procs[j]);
+                       }
+               }
+       }
+       print_chain(p);
+#endif /* __CONFIG_EXPER_TRADPROC__ */
        /* No one cares, and it clutters the terminal */
        //printk("Vcore 0's Last Trapframe:\n");
        //print_trapframe(&p->env_tf);
-       spin_unlock(&p->proc_lock);
-       proc_decref(p, 1); /* decref for the pid2proc reference */
+       /* no locking / unlocking or refcnting */
+       // spin_unlock(&p->proc_lock);
+       // proc_decref(p, 1); /* decref for the pid2proc reference */
 }