handle TLS mostly in glibc, not parlib
authorAndrew Waterman <waterman@eecs.berkeley.edu>
Tue, 15 May 2012 12:11:24 +0000 (05:11 -0700)
committerAndrew Waterman <waterman@eecs.berkeley.edu>
Tue, 15 May 2012 12:11:24 +0000 (05:11 -0700)
15 files changed:
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/Makefile
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/Versions
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/i386/tls.h
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/init-first.c
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/riscv/tls.h
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/start.c
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/sys/syscall.h
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/sys/vcore-tls.h [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/vcore-tls.c [new file with mode: 0644]
user/parlib/include/glibc-tls.h [deleted file]
user/parlib/include/i686/vcore.h
user/parlib/include/riscv/vcore.h
user/parlib/include/sparc/vcore.h
user/parlib/include/vcore.h
user/parlib/vcore.c

index b78b4f7..abba0b7 100644 (file)
@@ -9,4 +9,4 @@ CPPFLAGS += -D_IO_MTSAFE_IO=1
 ifeq ($(subdir),socket)
 sysdep_routines += sa_len
 endif
-sysdep_headers += sys/syscall.h
+sysdep_headers += sys/syscall.h sys/vcore-tls.h
index e0c44ac..c848333 100644 (file)
@@ -6,5 +6,11 @@ libc {
     __ros_scp_simple_evq;
     __ros_syscall;
     __ros_syscall_errno;
+
+    set_tls_desc;
+    get_tls_desc;
+    allocate_tls;
+    free_tls;
+    reinit_tls;
   }
 }
index 325eaec..724661a 100644 (file)
@@ -430,6 +430,31 @@ union user_desc_init
 #define THREAD_GSCOPE_WAIT() \
   GL(dl_wait_lookup_done) ()
 
+/* Reading from the LDT.  Could also use %gs, but that would require including
+ * half of libc's TLS header.  Sparc will probably ignore the vcoreid, so don't
+ * rely on it too much.  The intent of it is vcoreid is the caller's vcoreid,
+ * and that vcoreid might be in the TLS of the caller (it will be for transition
+ * stacks) and we could avoid a trap on x86 to sys_getvcoreid(). */
+static inline void *__get_tls_desc(uint32_t vcoreid)
+{
+       return (void*)(__procdata.ldt[vcoreid].sd_base_31_24 << 24 |
+                      __procdata.ldt[vcoreid].sd_base_23_16 << 16 |
+                      __procdata.ldt[vcoreid].sd_base_15_0);
+}
+
+/* passing in the vcoreid, since it'll be in TLS of the caller */
+static inline void __set_tls_desc(void *tls_desc, uint32_t vcoreid)
+{
+       /* Keep this technique in sync with sysdeps/ros/i386/tls.h */
+       segdesc_t tmp = SEG(STA_W, (uint32_t)tls_desc, 0xffffffff, 3);
+       __procdata.ldt[vcoreid] = tmp;
+
+       /* GS is still the same (should be!), but it needs to be reloaded to force a
+        * re-read of the LDT. */
+       uint32_t gs = (vcoreid << 3) | 0x07;
+       asm volatile("movl %0,%%gs" : : "r" (gs) : "memory");
+}
+
 static const char* tls_init_tp(void* thrdescr)
 {
   // TCB lives at thrdescr.
@@ -460,18 +485,7 @@ static const char* tls_init_tp(void* thrdescr)
        __ros_syscall(SYS_getpid, 0, 0, 0, 0, 0, 0, NULL);
   }
 
-  // Build the segment
-  segdesc_t tmp = SEG(STA_W, (uint32_t)thrdescr, 0xffffffff, 3);
-
-  // Setup the correct LDT entry for this vcore
-  __procdata.ldt[core_id] = tmp;
-
-  // Create the GS register.
-  uint32_t gs = (core_id << 3) | 0x07;
-
-  // Set the GS register.
-  asm volatile("movl %0,%%gs" : : "r" (gs) : "memory");
-
+  __set_tls_desc(thrdescr, core_id);
   return NULL;
 }
 
index 6d9c5cd..79eda40 100644 (file)
@@ -112,13 +112,15 @@ _init (int argc, char **argv, char **envp)
         break;
     }
   }
-  
+
+  extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign);
   __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN);
 
   __libc_init_secure ();
 
   /* First the initialization which normally would be done by the
      dynamic linker.  */
+  extern void _dl_non_dynamic_init (void) internal_function;
   _dl_non_dynamic_init ();
 #endif
 
index 4544769..322ded9 100644 (file)
@@ -170,6 +170,16 @@ typedef struct rthread {
 #define THREAD_GSCOPE_WAIT() \
   GL(dl_wait_lookup_done) ()
 
+static inline void *__get_tls_desc(uint32_t vcoreid)
+{
+       return READ_THREAD_POINTER() - TLS_TCB_OFFSET;
+}
+
+static inline void __set_tls_desc(void *tls_desc, uint32_t vcoreid)
+{
+       TLS_INIT_TP(tls_desc, 0);
+}
+
 #endif /* __ASSEMBLER__ */
 
 #endif /* tls.h */
index beb02aa..b4a4212 100644 (file)
@@ -5,7 +5,7 @@
 #include <ros/syscall.h>
 #include <ros/procinfo.h>
 #include <unistd.h>
-#include <tls.h>
+#include <vcore-tls.c>
 
 void** __vcore_thread_control_blocks = NULL;
 weak_alias(__vcore_thread_control_blocks,vcore_thread_control_blocks)
index 5f6f75d..d30db33 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _GLIBC_ROS_SYSCALL_H
 #define _GLIBC_ROS_SYSCALL_H
 
+#ifndef __ASSEMBLER__
+
 #include <ros/syscall.h>
 #include <ros/event.h>
 
@@ -47,4 +49,6 @@ void __ros_scp_syscall_blockon(struct syscall *sysc);
 }
 #endif
 
+#endif
+
 #endif /* _GLIBC_ROS_SYSCALL_H */
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/sys/vcore-tls.h b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/sys/vcore-tls.h
new file mode 100644 (file)
index 0000000..0e7502c
--- /dev/null
@@ -0,0 +1,25 @@
+/* Copyright (c) 2012 The Regents of the University of California
+ * Andrew Waterman <waterman@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * glibc syscall functions / tools for working with Akaros */
+
+#ifndef _GLIBC_ROS_VCORE_TLS_H
+#define _GLIBC_ROS_VCORE_TLS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void set_tls_desc(void* addr, int vcoreid);
+void *get_tls_desc(int vcoreid);
+
+void *allocate_tls(void);
+void free_tls(void *tcb);
+void *reinit_tls(void *tcb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GLIBC_ROS_SYSCALL_H */
diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/vcore-tls.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/vcore-tls.c
new file mode 100644 (file)
index 0000000..183fd80
--- /dev/null
@@ -0,0 +1,50 @@
+#include <sys/vcore-tls.h>
+#include <vcore.h>
+#include <ldsodefs.h>
+
+void set_tls_desc(void* addr, int vcoreid)
+{
+       __set_tls_desc(addr, vcoreid);
+       __vcoreid = vcoreid;
+}
+
+void *get_tls_desc(int vcoreid)
+{
+       return __get_tls_desc(vcoreid);
+}
+
+/* Get a TLS, returns 0 on failure.  Vcores have their own TLS, and any thread
+ * created by a user-level scheduler needs to create a TLS as well. */
+void *allocate_tls(void)
+{
+       void *tcb = _dl_allocate_tls(NULL);
+       if (!tcb)
+               return 0;
+#ifdef TLS_TCB_AT_TP
+       /* Make sure the TLS is set up properly - its tcb pointer points to itself.
+        * Keep this in sync with sysdeps/ros/XXX/tls.h.  For whatever reason,
+        * dynamically linked programs do not need this to be redone, but statics
+        * do. */
+       tcbhead_t *head = (tcbhead_t*)tcb;
+       head->tcb = tcb;
+       head->self = tcb;
+#endif
+       return tcb;
+}
+
+/* Free a previously allocated TLS region */
+void free_tls(void *tcb)
+{
+       _dl_deallocate_tls(tcb, TRUE);
+}
+
+/* Reinitialize / reset / refresh a TLS to its initial values.  This doesn't do
+ * it properly yet, it merely frees and re-allocates the TLS, which is why we're
+ * slightly ghetto and return the pointer you should use for the TCB. */
+void *reinit_tls(void *tcb)
+{
+       /* TODO: keep this in sync with the methods used in
+        * allocate_transition_tls() */
+       free_tls(tcb);
+       return allocate_tls();
+}
diff --git a/user/parlib/include/glibc-tls.h b/user/parlib/include/glibc-tls.h
deleted file mode 100644 (file)
index 419a2c7..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This is just a convenient place to drop some structs needed in
- * allocate_tls(), since we need to know where tcb and self are, without
- * cluttering up the main ROS code */
-
-#ifndef _GLIBC_TLS_H
-#define _GLIBC_TLS_H
-
-/* Type for the dtv.  */
-typedef union dtv
-{
-  size_t counter;
-  struct
-  {
-    void *val;
-    bool is_static;
-  } pointer;
-} dtv_t;
-
-
-typedef struct
-{
-  void *tcb;           /* Pointer to the TCB.  Not necessarily the
-                          thread descriptor used by libpthread.  */
-  dtv_t *dtv;
-  void *self;          /* Pointer to the thread descriptor.  */
-  int multiple_threads;
-  uintptr_t sysinfo;
-  uintptr_t stack_guard;
-  uintptr_t pointer_guard;
-  int gscope_flag;
-#ifndef __ASSUME_PRIVATE_FUTEX
-  int private_futex;
-#else
-  int __unused1;
-#endif
-  /* Reservation of some values for the TM ABI.  */
-  void *__private_tm[5];
-} tcbhead_t;
-
-#endif /* _GLIBC_TLS_H */
index b533b66..251d9c3 100644 (file)
@@ -7,8 +7,6 @@
 #include <ros/syscall.h>
 #include <ros/arch/mmu.h>
 
-extern __thread int __vcoreid;
-
 /* Pops an ROS kernel-provided TF, reanabling notifications at the same time.
  * A Userspace scheduler can call this when transitioning off the transition
  * stack.
@@ -208,33 +206,6 @@ init_user_tf(struct user_trapframe *u_tf, uint32_t entry_pt, uint32_t stack_top)
        u_tf->tf_esp = stack_top;
 }
 
-/* Reading from the LDT.  Could also use %gs, but that would require including
- * half of libc's TLS header.  Sparc will probably ignore the vcoreid, so don't
- * rely on it too much.  The intent of it is vcoreid is the caller's vcoreid,
- * and that vcoreid might be in the TLS of the caller (it will be for transition
- * stacks) and we could avoid a trap on x86 to sys_getvcoreid(). */
-static inline void *get_tls_desc(uint32_t vcoreid)
-{
-       return (void*)(__procdata.ldt[vcoreid].sd_base_31_24 << 24 |
-                      __procdata.ldt[vcoreid].sd_base_23_16 << 16 |
-                      __procdata.ldt[vcoreid].sd_base_15_0);
-}
-
-/* passing in the vcoreid, since it'll be in TLS of the caller */
-static inline void set_tls_desc(void *tls_desc, uint32_t vcoreid)
-{
-       /* Keep this technique in sync with sysdeps/ros/i386/tls.h */
-       segdesc_t tmp = SEG(STA_W, (uint32_t)tls_desc, 0xffffffff, 3);
-       __procdata.ldt[vcoreid] = tmp;
-
-       /* GS is still the same (should be!), but it needs to be reloaded to force a
-        * re-read of the LDT. */
-       uint32_t gs = (vcoreid << 3) | 0x07;
-       asm volatile("movl %0,%%gs" : : "r" (gs) : "memory");
-
-       __vcoreid = vcoreid;
-}
-
 // this is how we get our thread id on entry.
 #define __vcore_id_on_entry \
 ({ \
index 4e2d3a2..2f92702 100644 (file)
@@ -7,16 +7,7 @@
 #include <ros/syscall.h>
 #include <ros/procdata.h>
 #include <assert.h>
-
-extern __thread int __vcoreid;
-
-/* Feel free to ignore vcoreid.  It helps x86 to avoid a call to
- * sys_getvcoreid() if we pass it in. */
-static inline void *get_tls_desc(uint32_t vcoreid)
-{
-       register void* tp asm("tp");
-       return tp;
-}
+#include <sys/vcore-tls.h>
 
 #ifdef __riscv64
 # define REG_L "ld"
@@ -26,12 +17,6 @@ static inline void *get_tls_desc(uint32_t vcoreid)
 # define REG_S "sw"
 #endif
 
-static inline void set_tls_desc(void *tls_desc, uint32_t vcoreid)
-{
-       asm volatile ("move tp, %0" : : "r"(tls_desc) : "memory");
-       __vcoreid = vcoreid;
-}
-
 /* Register saves and restores happen in asm. */
 void __pop_ros_tf_regs(struct user_trapframe *tf, struct preempt_data* vcpd,
                     uint32_t vcoreid, void* helper) __attribute__((noreturn));
index 6adb14e..a37a721 100644 (file)
@@ -8,8 +8,6 @@
 #include <ros/procdata.h>
 #include <assert.h>
 
-extern __thread int __vcoreid;
-
 /* Feel free to ignore vcoreid.  It helps x86 to avoid a call to
  * sys_getvcoreid() if we pass it in. */
 static inline void *get_tls_desc(uint32_t vcoreid)
index 62844d1..0bbce22 100644 (file)
@@ -32,11 +32,7 @@ extern "C" {
 extern void vcore_entry();
 /* Declared in glibc's start.c */
 extern __thread bool __vcore_context;
-
-/* Utility Functions */
-void *allocate_tls(void);
-void free_tls(void *tcb);
-void *reinit_tls(void *tcb);
+extern __thread int __vcoreid;
 
 /* Vcore API functions */
 static inline size_t max_vcores(void);
index 418e055..1a4e3cd 100644 (file)
@@ -9,7 +9,6 @@
 #include <stdlib.h>
 #include <sys/mman.h>
 #include <stdio.h>
-#include <glibc-tls.h>
 #include <event.h>
 #include <uthread.h>
 #include <ucq.h>
@@ -22,43 +21,6 @@ atomic_t vc_req_being_handled;
 
 extern void** vcore_thread_control_blocks;
 
-/* Get a TLS, returns 0 on failure.  Vcores have their own TLS, and any thread
- * created by a user-level scheduler needs to create a TLS as well. */
-void *allocate_tls(void)
-{
-       extern void *_dl_allocate_tls(void *mem) internal_function;
-       void *tcb = _dl_allocate_tls(NULL);
-       if (!tcb)
-               return 0;
-       /* Make sure the TLS is set up properly - its tcb pointer points to itself.
-        * Keep this in sync with sysdeps/ros/XXX/tls.h.  For whatever reason,
-        * dynamically linked programs do not need this to be redone, but statics
-        * do. */
-       tcbhead_t *head = (tcbhead_t*)tcb;
-       head->tcb = tcb;
-       head->self = tcb;
-       return tcb;
-}
-
-/* Free a previously allocated TLS region */
-void free_tls(void *tcb)
-{
-       extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb) internal_function;
-       assert(tcb);
-       _dl_deallocate_tls(tcb, TRUE);
-}
-
-/* Reinitialize / reset / refresh a TLS to its initial values.  This doesn't do
- * it properly yet, it merely frees and re-allocates the TLS, which is why we're
- * slightly ghetto and return the pointer you should use for the TCB. */
-void *reinit_tls(void *tcb)
-{
-       /* TODO: keep this in sync with the methods used in
-        * allocate_transition_tls() */
-       free_tls(tcb);
-       return allocate_tls();
-}
-
 /* TODO: probably don't want to dealloc.  Considering caching */
 static void free_transition_tls(int id)
 {