Helpers to determine vcoreid (XCC)
[akaros.git] / user / parlib / include / vcore.h
index 0bbce22..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)
@@ -151,93 +153,110 @@ static inline bool __preempt_is_pending(uint32_t vcoreid)
 #include <features.h>
 #if __GNUC_PREREQ(4,4)
 
-#define begin_safe_access_tls_vars()                                    \
-  void __attribute__((noinline, optimize("O0")))                        \
-  safe_access_tls_var_internal() {                                      \
-    asm("");                                                            \
+/* These macro acrobatics trick the compiler into not caching the (linear)
+ * address of TLS variables across loads/stores of the TLS descriptor, in lieu
+ * of a "TLS cmb()". */
+#define begin_safe_access_tls_vars()                                           \
+       void __attribute__((noinline, optimize("O0")))                             \
+       safe_access_tls_var_internal() {                                           \
+               asm("");                                                               \
 
-#define end_safe_access_tls_vars()                                      \
-  } safe_access_tls_var_internal();                                     \
+#define end_safe_access_tls_vars()                                             \
+       } safe_access_tls_var_internal();                                          \
 
 #else
 
-#define begin_safe_access_tls_vars()                                                   \
-  printf("ERROR: For PIC you must be using gcc 4.4 or above for tls support!\n");      \
-  printf("ERROR: As a quick fix, try recompiling your application with -static...\n"); \
-  exit(2);
+#define begin_safe_access_tls_vars()                                           \
+       printf("ERROR: For PIC use gcc 4.4 or above for tls support!\n");          \
+       printf("ERROR: As a quick fix, recompile your app with -static...\n");     \
+       exit(2);
 
-#define end_safe_access_tls_vars()                                         \
-  printf("Will never be called because we abort above!");                  \
-  exit(2);
+#define end_safe_access_tls_vars()                                             \
+       printf("Will never be called because we abort above!");                    \
+       exit(2);
 
 #endif //__GNUC_PREREQ
 #endif // __PIC__
 
-#define begin_access_tls_vars(tls_desc)                               \
-{                                                                     \
-       uthread_t *caller;                                            \
-        int invcore = in_vcore_context();                             \
-        if(!invcore) {                                                \
-          caller = current_uthread;                                   \
-         assert(caller);                                             \
-         caller->flags |= UTHREAD_DONT_MIGRATE;                      \
-        }                                                             \
-                                                                      \
-       cmb();                                                        \
-       int vcoreid = vcore_id();                                     \
-        void *temp_tls_desc = get_tls_desc(vcoreid);                  \
-                                                                      \
-        if(!invcore)                                                  \
-         disable_notifs(vcoreid);                                    \
-                                                                      \
-        set_tls_desc(tls_desc, vcoreid);                              \
-        begin_safe_access_tls_vars();
-
-#define end_access_tls_vars()                                         \
-        end_safe_access_tls_vars();                                   \
-        set_tls_desc(temp_tls_desc, vcoreid);                         \
-                                                                      \
-        if(!invcore) {                                                \
-         caller->flags &= ~UTHREAD_DONT_MIGRATE;                     \
-          cmb();                                                      \
-         if(in_multi_mode())                                         \
-            enable_notifs(vcoreid);                                   \
-        }                                                             \
-       cmb();                                                        \
+/* Switches into the TLS 'tls_desc'.  Capable of being called from either
+ * uthread or vcore context.  Pairs with end_access_tls_vars(). */
+#define begin_access_tls_vars(tls_desc)                                        \
+{                                                                              \
+       struct uthread *caller;                                                    \
+       uint32_t vcoreid;                                                          \
+       void *temp_tls_desc;                                                       \
+       bool invcore = in_vcore_context();                                         \
+       if (!invcore) {                                                            \
+               caller = current_uthread;                                              \
+               /* If you have no current_uthread, you might be called too early in the
+                * process's lifetime.  Make sure something like uthread_slim_init() has
+                * been run. */                                                        \
+               assert(caller);                                                        \
+               /* We need to disable notifs here (in addition to not migrating), since
+                * we could get interrupted when we're in the other TLS, and when the
+                * vcore restarts us, it will put us in our old TLS, not the one we were
+                * in when we were interrupted.  We need to not migrate, since once we
+                * know the vcoreid, we depend on being on the same vcore throughout.*/\
+               caller->flags |= UTHREAD_DONT_MIGRATE;                                 \
+               /* Not concerned about cross-core memory ordering, so no CPU mbs needed.
+                * The cmb is to prevent the compiler from issuing the vcore read before
+                * the DONT_MIGRATE write. */                                          \
+               cmb();                                                                 \
+               vcoreid = vcore_id();                                                  \
+               disable_notifs(vcoreid);                                               \
+       } else { /* vcore context */                                               \
+               vcoreid = vcore_id();                                                  \
+       }                                                                          \
+       temp_tls_desc = get_tls_desc(vcoreid);                                     \
+       set_tls_desc(tls_desc, vcoreid);                                           \
+       begin_safe_access_tls_vars();
+
+#define end_access_tls_vars()                                                  \
+       end_safe_access_tls_vars();                                                \
+       set_tls_desc(temp_tls_desc, vcoreid);                                      \
+       if (!invcore) {                                                            \
+               /* Note we reenable migration before enabling notifs, which is reverse
+                * from how we disabled notifs.  We must enabling migration before
+                * enabling notifs.  See 6c7fb12 and 5e4825eb4 for details. */         \
+               caller->flags &= ~UTHREAD_DONT_MIGRATE;                                \
+               cmb();  /* turn off DONT_MIGRATE before enabling notifs */             \
+               if (in_multi_mode())                                                   \
+                       enable_notifs(vcoreid);                                            \
+       }                                                                          \
 }
 
-#define safe_set_tls_var(name, val)                                   \
-({                                                                    \
-        begin_safe_access_tls_vars();                                 \
-        name = val;                                                   \
-        end_safe_access_tls_vars();                                   \
+#define safe_set_tls_var(name, val)                                            \
+({                                                                             \
+       begin_safe_access_tls_vars();                                              \
+       name = val;                                                                \
+       end_safe_access_tls_vars();                                                \
 })
 
-#define safe_get_tls_var(name)                                        \
-({                                                                    \
-        typeof(name) __val;                                           \
-        begin_safe_access_tls_vars();                                 \
-        __val = name;                                                 \
-        end_safe_access_tls_vars();                                   \
-        __val;                                                        \
+#define safe_get_tls_var(name)                                                 \
+({                                                                             \
+       typeof(name) __val;                                                        \
+       begin_safe_access_tls_vars();                                              \
+       __val = name;                                                              \
+       end_safe_access_tls_vars();                                                \
+       __val;                                                                     \
 })
 
-#define vcore_set_tls_var(name, val)                                     \
-{                                                                        \
-      extern void** vcore_thread_control_blocks;                         \
-      typeof(val) __val = val;                                           \
-      begin_access_tls_vars(vcore_thread_control_blocks[vcoreid]);       \
-      name = __val;                                                      \
-      end_access_tls_vars();                                             \
-}
+#define vcore_set_tls_var(name, val)                                           \
+({                                                                             \
+       extern void** vcore_thread_control_blocks;                                 \
+       typeof(val) __val = val;                                                   \
+       begin_access_tls_vars(vcore_thread_control_blocks[vcoreid]);               \
+       name = __val;                                                              \
+       end_access_tls_vars();                                                     \
+})
 
-#define vcore_get_tls_var(name)                                 \
-({                                                              \
-      typeof(name) val;                                         \
-      begin_access_tls_vars(vcore_tls_descs[vcoreid]);          \
-      val = name;                                               \
-      end_access_tls_vars();                                    \
-      val;                                                      \
+#define vcore_get_tls_var(name)                                                \
+({                                                                             \
+       typeof(name) val;                                                          \
+       begin_access_tls_vars(vcore_tls_descs[vcoreid]);                           \
+       val = name;                                                                \
+       end_access_tls_vars();                                                     \
+       val;                                                                       \
 })
 
 #ifdef __cplusplus