Port-m68k archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

TLS support



Hi all,
attached patch provides the initial version of TLS support for M68K.
It is fully working, but comes with a performance penalty for libpthread
due to the system call to access the thread register. Please test this
carefully. It would be nice to measure the performance impact. If it
isn't too bad, I would prefer to get the patch in now to remove the
second to last architecture depending on stackid on libpthread.

Addressing the thread pointer issue requires more platform knowledge
than I have, so I have to leave that to someone else to finish. There
are two basic approaches for a strictly UP platform like M68K:

(1) Register a global variable with the kernel and write
curlwp->l_private to that location before returning to userland.

Pro: Relative simple modification of the return-from-trap logic.
Con: Has to deal with traps. Requires work for every system call and
context switch.

(2) Provide a global page that is mapped into user processes. Either do
this automatically for all processes on startup and expose the address
via ELF Aux vector or provide a map/unmap interface.

Pro: Fixed memory overhead, only one additional assignment in cpu_switchto.
Con: Requires pmap changes to protect the page.

If the normal userland mapping puts the initial stack at the top of the
address space, it would be an idea to just reduce the user modifable VA
by one page. In that case this is most likely the best option.

Additional work can be put into GCC. The generated code for TLS access
is very suboptimal. E.g. it can calls __m68k_read_tp more than once per
function, instead of caching the results.

Joerg
Index: lib/libc/arch/m68k/Makefile.inc
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/arch/m68k/Makefile.inc,v
retrieving revision 1.13
diff -u -p -r1.13 Makefile.inc
--- lib/libc/arch/m68k/Makefile.inc     9 Feb 2008 02:41:06 -0000       1.13
+++ lib/libc/arch/m68k/Makefile.inc     18 Nov 2011 01:45:52 -0000
@@ -1,6 +1,6 @@
 #      $NetBSD: Makefile.inc,v 1.13 2008/02/09 02:41:06 mrg Exp $
 
-SRCS+= __sigaction14_sigtramp.c __sigtramp2.S __mmap.S
+SRCS+= __sigaction14_sigtramp.c __sigtramp2.S __m68k_read_tp.S __mmap.S
 
 ASM+=  _lwp_getprivate.S mremap.S
 
Index: lib/libc/arch/m68k/gen/Makefile.inc
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/arch/m68k/gen/Makefile.inc,v
retrieving revision 1.30
diff -u -p -r1.30 Makefile.inc
--- lib/libc/arch/m68k/gen/Makefile.inc 6 Dec 2009 07:12:17 -0000       1.30
+++ lib/libc/arch/m68k/gen/Makefile.inc 18 Nov 2011 00:34:06 -0000
@@ -26,6 +26,7 @@ SRCS+=        ashlsi3.S ashrsi3.S \
        negdf2.S negsf2.S
 SRCS+= bswap16.S bswap32.S bswap64.S
 SRCS+= _lwp.c
+CPPFLAGS._lwp.c        += -D_LIBC_SOURCE
 
 # 68000-based machines build with a libgcc that includes
 # much of the (soft)float and integer support that would 
Index: lib/libc/arch/m68k/gen/_lwp.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/arch/m68k/gen/_lwp.c,v
retrieving revision 1.6
diff -u -p -r1.6 _lwp.c
--- lib/libc/arch/m68k/gen/_lwp.c       24 Feb 2011 04:28:42 -0000      1.6
+++ lib/libc/arch/m68k/gen/_lwp.c       18 Nov 2011 02:17:55 -0000
@@ -36,13 +36,14 @@ __RCSID("$NetBSD: _lwp.c,v 1.6 2011/02/2
 
 #include "namespace.h"
 #include <sys/types.h>
+#include <sys/tls.h>
 #include <ucontext.h>
 #include <lwp.h>
 #include <stdlib.h>
 
 void
 _lwp_makecontext(ucontext_t *u, void (*start)(void *),
-    void *arg, void *private, caddr_t stack_base, size_t stack_size)
+    void *arg, void *tcb, caddr_t stack_base, size_t stack_size)
 {
        void **sp;
 
@@ -60,6 +61,7 @@ _lwp_makecontext(ucontext_t *u, void (*s
        *--sp = (void *) _lwp_exit;
 
        u->uc_mcontext.__gregs[_REG_A7] = (int) sp;
-       u->uc_mcontext._mc_tlsbase = (uintptr_t)private;
+       u->uc_mcontext._mc_tlsbase = (uintptr_t)tcb + TLS_TP_OFFSET +
+           sizeof(struct tls_tcb);
        u->uc_flags |= _UC_TLSBASE;
 }
Index: lib/libc/arch/m68k/sys/__m68k_read_tp.S
===================================================================
RCS file: lib/libc/arch/m68k/sys/__m68k_read_tp.S
diff -N lib/libc/arch/m68k/sys/__m68k_read_tp.S
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libc/arch/m68k/sys/__m68k_read_tp.S     18 Nov 2011 02:08:53 -0000
@@ -0,0 +1,7 @@
+#include "SYS.h"
+
+ENTRY(__m68k_read_tp)
+       SYSTRAP(_lwp_getprivate)
+       movl    %d0,%a0
+       rts
+       .size   __m68k_read_tp, .-__m68k_read_tp
Index: libexec/ld.elf_so/arch/m68k/mdreloc.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/libexec/ld.elf_so/arch/m68k/mdreloc.c,v
retrieving revision 1.28
diff -u -p -r1.28 mdreloc.c
--- libexec/ld.elf_so/arch/m68k/mdreloc.c       25 Mar 2011 18:07:05 -0000      
1.28
+++ libexec/ld.elf_so/arch/m68k/mdreloc.c       10 Nov 2011 02:48:06 -0000
@@ -126,6 +126,49 @@ _rtld_relocate_nonplt_objects(Obj_Entry 
                        rdbg(("COPY (avoid in main)"));
                        break;
 
+#ifdef __HAVE_TLS_VARIANT_I
+               case R_TYPE(TLS_DTPMOD32):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       *where = (Elf_Addr)defobj->tlsindex;
+                       rdbg(("DTPMOD32 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(TLS_DTPREL32):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
+                               return -1;
+
+                       *where = (Elf_Addr)(def->st_value + rela->r_addend
+                           - TLS_DTV_OFFSET);
+                       rdbg(("DTPREL32 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+
+               case R_TYPE(TLS_TPREL32):
+                       def = _rtld_find_symdef(symnum, obj, &defobj, false);
+                       if (def == NULL)
+                               return -1;
+
+                       if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
+                               return -1;
+
+                       *where = (Elf_Addr)(def->st_value + rela->r_addend
+                           + defobj->tlsoffset - TLS_TP_OFFSET);
+                       rdbg(("TPREL32 %s in %s --> %p in %s",
+                           obj->strtab + obj->symtab[symnum].st_name,
+                           obj->path, (void *)*where, defobj->path));
+                       break;
+#endif
+
                default:
                        rdbg(("sym = %lu, type = %lu, offset = %p, "
                            "addend = %p, contents = %p, symbol = %s",
Index: sys/arch/m68k/include/mcontext.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/sys/arch/m68k/include/mcontext.h,v
retrieving revision 1.8
diff -u -p -r1.8 mcontext.h
--- sys/arch/m68k/include/mcontext.h    24 Feb 2011 04:28:46 -0000      1.8
+++ sys/arch/m68k/include/mcontext.h    18 Nov 2011 02:18:17 -0000
@@ -109,4 +109,31 @@ typedef struct {
 
 #define        __UCONTEXT_SIZE 1024
 
+#if defined(_LIBC_SOURCE) || defined(_RTLD_SOURCE) || 
defined(__LIBPTHREAD_SOURCE__)
+#define        TLS_TP_OFFSET   0x7000
+#define        TLS_DTV_OFFSET  0x8000
+
+#include <sys/tls.h>
+
+__CTASSERT(TLS_TP_OFFSET + sizeof(struct tls_tcb) < 0x8000);
+__CTASSERT(TLS_TP_OFFSET % sizeof(struct tls_tcb) == 0);
+
+void *_lwp_getprivate(void);
+void _lwp_setprivate(void *);
+
+static __inline struct tls_tcb *
+__lwp_gettcb_fast(void)
+{
+       unsigned int __tcb = (unsigned int)_lwp_getprivate();
+       return (void *)(__tcb - TLS_TP_OFFSET - sizeof(struct tls_tcb));
+}
+
+static inline void
+__lwp_settcb(struct tls_tcb *__tcb)
+{
+       __tcb += TLS_TP_OFFSET / sizeof(*__tcb) + 1;
+       _lwp_setprivate(__tcb);
+}
+#endif
+
 #endif /* !_M68K_MCONTEXT_H_ */
Index: sys/arch/m68k/include/types.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/sys/arch/m68k/include/types.h,v
retrieving revision 1.29
diff -u -p -r1.29 types.h
--- sys/arch/m68k/include/types.h       22 Dec 2010 02:42:28 -0000      1.29
+++ sys/arch/m68k/include/types.h       10 Nov 2011 01:54:12 -0000
@@ -73,6 +73,10 @@ typedef      volatile unsigned char __cpu_sim
 
 #define        __HAVE_SYSCALL_INTERN
 #define        __HAVE_CPU_DATA_FIRST
+#define        __HAVE_COMMON___TLS_GET_ADDR
+#define        __HAVE___LWP_GETTCB_FAST
+#define        __HAVE___LWP_SETTCB
+#define        __HAVE_TLS_VARIANT_I
 
 #if defined(_KERNEL)
 #define        __HAVE_RAS


Home | Main Index | Thread Index | Old Index