Fixes TLS for statically linked apps in _M mode
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 15 Sep 2010 02:14:41 +0000 (19:14 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:54 +0000 (17:35 -0700)
kern/src/mm.c
user/include/glibc-tls.h [new file with mode: 0644]
user/parlib/vcore.c

index 3e2f63c..5e66db1 100644 (file)
@@ -557,7 +557,7 @@ int __handle_page_fault(struct proc *p, uintptr_t va, int prot)
        if (!vmr)                                                       /* not mapped at all */
                return -EFAULT;
        if (!(vmr->vm_prot & prot))                     /* wrong prots for this vmr */
-               return -EFAULT;
+               return -EPERM;
        /* find offending PTE (prob don't read this in).  This might alloc an
         * intermediate page table page. */
        pte_t *pte = pgdir_walk(p->env_pgdir, (void*)va, 1);
diff --git a/user/include/glibc-tls.h b/user/include/glibc-tls.h
new file mode 100644 (file)
index 0000000..419a2c7
--- /dev/null
@@ -0,0 +1,40 @@
+/* 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 5ae6882..a8cecdc 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <sys/mman.h>
 #include <rstdio.h>
+#include <glibc-tls.h>
 
 /* starting with 1 since we alloc vcore0's stacks and TLS in vcore_init(). */
 static size_t _max_vcores_ever_wanted = 1;
@@ -28,16 +29,24 @@ static void free_transition_tls(int id)
 
 static int allocate_transition_tls(int id)
 {
-       extern void *_dl_allocate_tls (void *mem) internal_function;
-       // We want to free and then reallocate the tls rather than simply 
-       // reinitializing it because its size may have changed
+       extern void *_dl_allocate_tls(void *mem) internal_function;
+       /* We want to free and then reallocate the tls rather than simply 
+        * reinitializing it because its size may have changed */
        free_transition_tls(id);
 
-       void* tls = _dl_allocate_tls(NULL);
-       if((vcore_thread_control_blocks[id] = tls) == NULL) {
+       void *tcb = _dl_allocate_tls(NULL);
+
+       if ((vcore_thread_control_blocks[id] = tcb) == NULL) {
                errno = ENOMEM;
                return -1;
        }
+       /* 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 0;
 }