get_tlsvar_linaddr() and uthread notes
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 15 May 2015 01:30:53 +0000 (21:30 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 15 May 2015 01:35:44 +0000 (21:35 -0400)
While debugging "Allows pthread_yield() before lib_init()", I noticed
the issues with __vcore_context noted in uthread_manage_thread0().

I made get_tlsvar_linaddr() to debug it.  It's just what we were doing
for get_cur_uth_addr(), but for any TLS variable.

user/parlib/include/uthread.h
user/parlib/include/vcore.h
user/parlib/uthread.c

index 33c2a6b..3e53612 100644 (file)
@@ -92,7 +92,6 @@ void deregister_evq(struct syscall *sysc);
 void highjack_current_uthread(struct uthread *uthread);
 void run_current_uthread(void);
 void run_uthread(struct uthread *uthread);
-static inline struct uthread **get_cur_uth_addr(uint32_t vcoreid);
 
 /* Asking for trouble with this API, when we just want stacktop (or whatever
  * the SP will be). */
@@ -119,15 +118,6 @@ static inline void init_uthread_ctx(struct uthread *uth, void (*entry)(void),
        val;                                                                       \
 })
 
-/* This works so long as we don't dlopen parlib (which we never do) */
-static inline struct uthread **get_cur_uth_addr(uint32_t vcoreid)
-{
-       uintptr_t vc_tls_desc = (uintptr_t)get_vcpd_tls_desc(vcoreid);
-       uintptr_t cur_uth_off = (uintptr_t)&current_uthread -
-                               (uintptr_t)get_tls_desc(vcore_id());
-       return (struct uthread**)(vc_tls_desc + cur_uth_off);
-}
-
 __END_DECLS
 
 #endif /* PARLIB_UTHREAD_H */
index 9c6250f..0ec1750 100644 (file)
@@ -67,6 +67,14 @@ void cpu_relax_vc(uint32_t vcoreid);
 uint32_t get_vcoreid(void);
 bool check_vcoreid(const char *str, uint32_t vcoreid);
 
+/* This works so long as we don't dlopen parlib (which we never do) */
+#define get_tlsvar_linaddr(_vcoreid, _var)                                     \
+({                                                                             \
+       uintptr_t vc_tls_desc = (uintptr_t)get_vcpd_tls_desc(_vcoreid);            \
+       uintptr_t var_off = (uintptr_t)&_var - (uintptr_t)get_tls_desc(vcore_id());\
+       (typeof(_var) *)(vc_tls_desc + var_off);                                   \
+})
+
 /* Static inlines */
 static inline uint32_t max_vcores(void)
 {
index 135e506..a77ae77 100644 (file)
@@ -68,6 +68,13 @@ static void uthread_manage_thread0(struct uthread *uthread)
        if (current_uthread)
                free(current_uthread);
        current_uthread = uthread;
+       /* We could consider setting __vcore_context = TRUE here, since this is
+        * probably the first time we're initializing vcore 0's TLS.  However, when
+        * we actually turn into an MCP, VC 0 will come up and set __vcore_context.
+        * I actually want it cleared until then, so that various asserts will catch
+        * if we call other uthread functions before the 2LS is set up (before we're
+        * an MCP).  For example, if someone calls uthread_yield from thread0 (which
+        * has TLS), we'll panic since VC 0's TLS doesn't know it's a VC yet. */
        end_safe_access_tls_vars();
        set_tls_desc(uthread->tls_desc, 0);
        begin_safe_access_tls_vars();
@@ -364,6 +371,7 @@ void uthread_yield(bool save_state, void (*yield_func)(struct uthread*, void*),
                set_tls_desc(get_vcpd_tls_desc(vcoreid), vcoreid);
                begin_safe_access_tls_vars();
                assert(current_uthread == uthread);
+               /* If this assert fails, see the note in uthread_manage_thread0 */
                assert(in_vcore_context());
                end_safe_access_tls_vars();
        } else {
@@ -955,7 +963,7 @@ static void handle_vc_preempt(struct event_msg *ev_msg, unsigned int ev_type,
        /* At this point, we're clear to try and steal the uthread.  We used to
         * switch to their TLS to steal the uthread, but we can access their
         * current_uthread directly. */
-       rem_cur_uth = get_cur_uth_addr(rem_vcoreid);
+       rem_cur_uth = get_tlsvar_linaddr(rem_vcoreid, current_uthread);
        uthread_to_steal = *rem_cur_uth;
        if (uthread_to_steal) {
                /* Extremely rare: they have a uthread, but it can't migrate.  So we'll