Proactively clears current_tf
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 5 Nov 2010 23:37:16 +0000 (16:37 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:56 +0000 (17:35 -0700)
We don't want this accidentally left valid when we are done with it
(reasons will be clearer in later patches).

Also changes abandon_core() to just abandon, but not implicitly
smp_idle().

kern/src/kthread.c
kern/src/process.c
kern/src/resource.c
kern/src/smp.c

index c800c7e..e45f9ee 100644 (file)
@@ -69,7 +69,9 @@ void sleep_on(struct semaphore *sem)
         * we want to leave, we'll need to do that in smp_idle() or elsewhere in the
         * code. */
        kthread->proc = current;
+       /* TODO: this will change in a commit or two */
        kthread->proc_tf = current_tf;
+       current_tf = 0; /* don't want this *pointer* to persist past the block */
        if (kthread->proc)
                kref_get(&kthread->proc->kref, 1);
        /* Save the context, toggle blocking for the reactivation */
@@ -100,6 +102,7 @@ unwind_sleep_prep:
        printd("Didn't sleep, unwinding...\n");
        /* Restore the core's current and default stacktop */
        current = kthread->proc;                        /* arguably unnecessary */
+       set_current_tf(kthread->proc_tf);
        if (kthread->proc)
                kref_put(&kthread->proc->kref);
        set_stack_top(kthread->stacktop);
@@ -137,17 +140,19 @@ void restart_kthread(struct kthread *kthread)
        /* Set the spare stuff (current kthread, current (not kthread) stacktop) */
        pcpui->spare = kthread;
        kthread->stacktop = current_stacktop;
-       /* We need to load the new cr3 if we want another new (or no) process */
-       if (current != kthread->proc) {
+       if (current) {
+               /* __launch_kthread() should have abandoned if it was diff */
+               assert(current == kthread->proc);
+               /* no longer need this ref, current holds it */
+               kref_put(&kthread->proc->kref);
+
+       } else {
+               /* ref gets transfered (or it was 0 (no ref held)) */
+               current = kthread->proc;
                if (kthread->proc)
                        lcr3(kthread->proc->env_cr3);
-               else
-                       lcr3(boot_cr3);
        }
-       /* If there's a proc current already, we'll lose that ref no matter what. */
-       if (current)
-               kref_put(&current->kref);
-       current = kthread->proc;
+       /* TODO: (CTF) change me when we use async syscalls */
        if (kthread->proc_tf)
                set_current_tf(kthread->proc_tf);
        /* Finally, restart our thread */
@@ -192,6 +197,7 @@ void __launch_kthread(struct trapframe *tf, uint32_t srcid, void *a0, void *a1,
                        /* Wrap up / yield the current _S proc, which calls schedule_proc */
                        __proc_yield_s(cur_proc, tf);
                        spin_unlock(&cur_proc->proc_lock);
+                       abandon_core();
                } else {
                        /* possible to get here if there is only one _S proc that blocked */
                        //assert(cur_proc->state == PROC_RUNNING_M);
index 9909030..c72a72b 100644 (file)
@@ -559,6 +559,8 @@ static void __proc_startcore(struct proc *p, trapframe_t *tf)
         * __startcore.  */
        if (p->state == PROC_RUNNING_S)
                env_pop_ancillary_state(p);
+       /* Clear the current_tf, since it is no longer used */
+       current_tf = 0;
        env_pop_tf(tf);
 }
 
@@ -782,7 +784,7 @@ void proc_yield(struct proc *SAFE p, bool being_nice)
 
        switch (p->state) {
                case (PROC_RUNNING_S):
-                       __proc_yield_s(p, current_tf);
+                       __proc_yield_s(p, current_tf);  /* current_tf 0'd in abandon core */
                        break;
                case (PROC_RUNNING_M):
                        printd("[K] Process %d (%p) is yielding on vcore %d\n", p->pid, p,
@@ -822,6 +824,7 @@ void proc_yield(struct proc *SAFE p, bool being_nice)
        /* Clean up the core and idle.  For mgmt cores, they will ultimately call
         * manager, which will call schedule() and will repick the yielding proc. */
        abandon_core();
+       smp_idle();
 }
 
 /* If you expect to notify yourself, cleanup state and process_routine_kmsg() */
@@ -1311,9 +1314,10 @@ void __unmap_vcore(struct proc *p, uint32_t vcoreid)
  * process's context. */
 void abandon_core(void)
 {
-       if (current)
+       if (current) {
+               current_tf = 0;
                __abandon_core();
-       smp_idle();
+       }
 }
 
 /* Will send a TLB shootdown message to every vcore in the main address space
@@ -1462,6 +1466,7 @@ void __preempt(trapframe_t *tf, uint32_t srcid, void *a0, void *a1, void *a2)
        __seq_start_write(&vcpd->preempt_tf_valid);
        __unmap_vcore(p, vcoreid);
        abandon_core();
+       smp_idle();
 }
 
 /* Kernel message handler to clean up the core when a process is dying.
@@ -1479,6 +1484,7 @@ void __death(trapframe_t *tf, uint32_t srcid, void *SNT a0, void *SNT a1,
                __unmap_vcore(current, vcoreid);
        }
        abandon_core();
+       smp_idle();
 }
 
 /* Kernel message handler, usually sent IMMEDIATE, to shoot down virtual
index 266f80c..d368c05 100644 (file)
@@ -48,8 +48,9 @@ ssize_t core_request(struct proc *p)
         * transition from _M to _S.  Will be issues with handling this async. */
        if (!p->resources[RES_CORES].amt_wanted) {
                assert(p->state == PROC_RUNNING_M); // TODO: (ACR) async core req
-               // save the context, to be restarted in _S mode
+               /* save the context, to be restarted in _S mode */
                p->env_tf = *current_tf;
+               current_tf = 0;                 /* Make sure it isn't used in the future */
                env_push_ancillary_state(p); // TODO: (HSS)
                set_retval(ESUCCESS);
                /* sending death, since it's not our job to save contexts or anything in
@@ -163,6 +164,7 @@ ssize_t core_request(struct proc *p)
                if (need_to_idle) {
                        kref_put(&p->kref);
                        abandon_core();
+                       smp_idle();
                }
        } else { // nothing granted, just return
                spin_unlock(&p->proc_lock);
index e1ab2b1..b86739d 100644 (file)
@@ -43,6 +43,9 @@ void smp_idle(void)
        int8_t state = 0;
        per_cpu_info_t *myinfo = &per_cpu_info[core_id()];
 
+       /* TODO: this is only for a couple commits, to make sure we aren't keeping
+        * this around */
+       assert(!current_tf);
        /* in the future, we may need to proactively leave process context here.
         * for now, it is possible to have a current loaded, even if we are idle
         * (and presumably about to execute a kmsg or fire up a vcore). */