The kernel migrates silly state when becoming _M
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 16 Apr 2010 01:16:03 +0000 (18:16 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:42 +0000 (17:35 -0700)
It will use the preempt slot and fake a notification to get the _M
process to start up at _start on vcore0.

Documentation/processes.txt
kern/arch/i686/process.c
kern/src/resource.c
user/parlib/pthread.c

index 621a22c..cd7baf9 100644 (file)
@@ -171,8 +171,10 @@ user-thread control block, and do whatever is needed to signal vcore0 to run the
 _S context when it starts up.  One way would be to mark vcore0's "active thread"
 variable to point to the _S thread.  When vcore0 starts up at
 _start/vcore_entry() (like all vcores), it will see a thread was running there
-and restart it.  This will need to have some special casing for the FP/silly
-state.
+and restart it.  The kernel will migrate the _S thread's silly state (FP) to the
+new pcore, so that it looks like the process was simply running the _S thread
+and got notified.  Odds are, it will want to just restart that thread, but the
+kernel won't assume that (hence the notification).
 
 In general, all cores (and all subsequently allocated cores) start at the elf
 entry point, with vcoreid in eax or a suitable arch-specific manner.  There is
index 56d5b34..ac798e7 100644 (file)
@@ -45,7 +45,7 @@ void proc_secure_trapframe(struct trapframe *tf)
        tf->tf_fs = 0;
        //tf->tf_gs = whatevs.  ignoring this.
        tf->tf_ss = GD_UD | 3;
-       tf->tf_cs = GD_UT | 3;
+       tf->tf_cs ? GD_UT | 3 : 0; // can be 0 for sysenter TFs.
        tf->tf_eflags |= 0x00000200; // bit 9 is the interrupts-enabled
 }
 
index c11c66e..0002bbf 100644 (file)
@@ -100,8 +100,15 @@ ssize_t core_request(struct proc *p)
                                if ((current != p) || (p->procinfo->vcoremap[0].pcoreid != core_id()))
                                        panic("We don't handle async RUNNING_S core requests yet.");
                                /* save the tf so userspace can restart it.  Like in __notify,
-                                * this assumes a user tf is the same as a kernel tf. */
-                               p->procdata->vcore_preempt_data[0].notif_tf = *current_tf;
+                                * this assumes a user tf is the same as a kernel tf.  We save
+                                * it in the preempt slot so that we can also save the silly
+                                * state. */
+                               struct preempt_data *vcpd = &p->procdata->vcore_preempt_data[0];
+                               vcpd->preempt_tf = *current_tf;
+                               save_fp_state(&vcpd->preempt_anc);
+                               __seq_start_write(&vcpd->preempt_tf_valid);
+                               /* If we remove this, vcore0 will start where the _S left off */
+                               vcpd->notif_pending = TRUE;
                                /* in the async case, we'll need to remotely stop and bundle
                                 * vcore0's TF.  this is already done for the sync case (local
                                 * syscall). */
index e25c4e7..b6940ec 100644 (file)
@@ -6,6 +6,7 @@
 #include <assert.h>
 #include <rstdio.h>
 #include <errno.h>
+#include <parlib.h>
 #include <ros/notification.h>
 #include <arch/atomic.h>
 #include <sys/queue.h>