Helpers to determine vcoreid (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 27 Sep 2012 00:14:28 +0000 (17:14 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 27 Sep 2012 00:30:24 +0000 (17:30 -0700)
Some helpers, useful in debugging and low-level (glibc) code.

It's actually not possible (currently) for a syscall to know what
vcore submitted the syscall, due to concurrent preemptions.  But given a
pcoreid, you can tell what vcore is running.  We might fix
sys_getvcoreid in the future.  Regardless, the pcoreid version is worth
checking out.

Reinstall your kernel headers.

kern/include/ros/procinfo.h
user/parlib/include/vcore.h
user/parlib/vcore.c

index 10fdf2a..36a380c 100644 (file)
@@ -97,6 +97,38 @@ procinfo_pack_args(procinfo_t* p, char* const* argv, char* const* envp)
 // this is how user programs access the procinfo page
 #ifndef ROS_KERNEL
 # define __procinfo (*(procinfo_t*)UINFO)
-#endif
+
+#include <ros/common.h>
+#include <ros/atomic.h>
+#include <ros/syscall.h>
+
+/* Figure out what your vcoreid is from your pcoreid and procinfo.  Only low
+ * level or debugging code should call this. */
+static inline uint32_t __get_vcoreid_from_procinfo(void)
+{
+       /* The assumption is that any IPIs/KMSGs would knock userspace into the
+        * kernel before it could read the closing of the seqctr.  Put another way,
+        * there is a 'memory barrier' between the IPI write and the seqctr write.
+        * I think this is true. */
+       uint32_t kpcoreid, kvcoreid;
+       seq_ctr_t old_seq;
+       do {
+               cmb();
+               old_seq = __procinfo.coremap_seqctr;
+               kpcoreid = __ros_syscall(SYS_getpcoreid, 0, 0, 0, 0, 0, 0, NULL);
+               if (!__procinfo.pcoremap[kpcoreid].valid)
+                       continue;
+               kvcoreid = __procinfo.pcoremap[kpcoreid].vcoreid;
+       } while (seqctr_retry(old_seq, __procinfo.coremap_seqctr));
+       return kvcoreid;
+}
+
+static inline uint32_t __get_vcoreid(void)
+{
+       /* since sys_getvcoreid could lie (and might never change) */
+       return __get_vcoreid_from_procinfo();
+}
+
+#endif /* ifndef ROS_KERNEL */
 
 #endif // !ROS_PROCDATA_H
index df7c021..467d8b9 100644 (file)
@@ -59,6 +59,8 @@ void disable_notifs(uint32_t vcoreid);
 void vcore_idle(void);
 void ensure_vcore_runs(uint32_t vcoreid);
 void cpu_relax_vc(uint32_t vcoreid);
+uint32_t get_vcoreid(void);
+bool check_vcoreid(const char *str, uint32_t vcoreid);
 
 /* Static inlines */
 static inline size_t max_vcores(void)
index 1a4e3cd..8c34c2c 100644 (file)
@@ -417,3 +417,30 @@ void cpu_relax_vc(uint32_t vcoreid)
        }
        cpu_relax();
 }
+
+/* Check with the kernel to determine what vcore we are.  Normally, you should
+ * never call this, since your vcoreid is stored in your TLS.  Also, if you call
+ * it from a uthread, you could get migrated, so you should drop into some form
+ * of vcore context (DONT_MIGRATE on) */
+uint32_t get_vcoreid(void)
+{
+       if (!in_vcore_context()) {
+               assert(current_uthread);
+               assert(current_uthread->flags & UTHREAD_DONT_MIGRATE);
+       }
+       return __get_vcoreid();
+}
+
+/* Debugging helper.  Pass in the string you want printed if your vcoreid is
+ * wrong, and pass in what vcoreid you think you are.  Don't call from uthread
+ * context unless migrations are disabled.  Will print some stuff and return
+ * FALSE if you were wrong. */
+bool check_vcoreid(const char *str, uint32_t vcoreid)
+{
+       uint32_t kvcoreid = get_vcoreid();
+       if (vcoreid != kvcoreid) {
+               ros_debug("%s: VC %d thought it was VC %d\n", str, kvcoreid, vcoreid);
+               return FALSE;
+       }
+       return TRUE;
+}