From 201cdb743879cbffd38c53d8ebf85fa9fff1e0e4 Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Fri, 5 Aug 2011 14:37:48 +0000 Subject: Makefile.in (UNWIND_H): Remove. gcc: * Makefile.in (UNWIND_H): Remove. (LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): Move to ../libgcc/Makefile.in. (LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL): Likewise. (LIBUNWINDDEP): Remove. (libgcc-support): Remove LIB2ADDEH, $(srcdir)/emutls.c dependencies. (libgcc.mvars): Remove LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED, LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL. (stmp-int-hdrs): Remove $(UNWIND_H) dependency. Don't copy $(UNWIND_H). * config.gcc (ia64*-*-linux*): Remove with_system_libunwind handling. * configure.ac (GCC_CHECK_UNWIND_GETIPINFO): Remove. * aclocal.m4: Regenerate. * configure: Regenerate. * emutls.c, unwind-c.c, unwind-compat.c, unwind-compat.h, unwind-dw2-fde-compat.c, unwind-dw2-fde-glibc.c, unwind-dw2-fde.c, unwind-dw2-fde.h, unwind-dw2.c, unwind-dw2.h, unwind-generic.h, unwind-pe.h, unwind-sjlj.c, unwind.inc: Move to ../libgcc. * unwind-dw2-fde-darwin.c: Move to ../libgcc/config. * config/arm/libunwind.S, config/arm/pr-support.c, config/arm/unwind-arm.c, config/arm/unwind-arm.h: Move to ../libgcc/config/arm. * config/arm/t-bpabi (UNWIND_H, LIB2ADDEH): Remove. * config/arm/t-symbian (UNWIND_H, LIB2ADDEH): Remove. * config/frv/t-frv ($(T)frvbegin$(objext)): Use $(srcdir)/../libgcc to refer to unwind-dw2-fde.h. ($(T)frvend$(objext)): Likewise. * config/ia64/t-glibc (LIB2ADDEH): Remove. * config/ia64/t-glibc-libunwind: Move to ../libgcc/config/ia64. * config/ia64/fde-glibc.c, config/ia64/fde-vms.c, config/ia64/unwind-ia64.c, config/ia64/unwind-ia64.h: Move to ../libgcc/config/ia64. * config/ia64/t-hpux (LIB2ADDEH): Remove. * config/ia64/t-ia64 (LIB2ADDEH): Remove. * config/ia64/t-vms (LIB2ADDEH): Remove. * config/ia64/vms.h (UNW_IVMS_MODE, MD_UNW_COMPATIBLE_PERSONALITY_P): Remove. * config/picochip/t-picochip (LIB2ADDEH): Remove. * config/rs6000/aix.h (R_LR, MD_FROB_UPDATE_CONTEXT): Remove. * config/rs6000/t-darwin (LIB2ADDEH): Remove. * config/rs6000/darwin-fallback.c: Move to ../libgcc/config/rs6000. * config/sh/t-sh ($(T)unwind-dw2-Os-4-200.o): Use $(srcdir)/../libgcc to refer to unwinder sources. * config/spu/t-spu-elf (LIB2ADDEH): Remove. * config/t-darwin (LIB2ADDEH): Remove. * config/t-freebsd (LIB2ADDEH): Remove. * config/t-libunwind (LIB2ADDEH, LIB2ADDEHSTATIC): Remove. * config/t-libunwind-elf: Move to ../libgcc/config. * config/t-linux (LIB2ADDEH): Remove. * config/t-sol2 (LIB2ADDEH): Remove. * config/xtensa/t-xtensa (LIB2ADDEH): Remove. * system.h (MD_FROB_UPDATE_CONTEXT): Poison. gcc/po: * EXCLUDES (unwind-c.c, unwind-dw2-fde-darwin.c) (unwind-dw2-fde-glibc.c, unwind-dw2-fde.c, unwind-dw2-fde.h) (unwind-dw2.c, unwind-pe.h, unwind-sjlj.c, unwind.h): Remove. libgcc: * Makefile.in (LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): New variables. (LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL): New variables. (LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): Add $(srcdir)/emutls.c. (install-unwind_h): New target. (all): Depend on it. * config.host (unwind_header): New variable. (*-*-freebsd*): Set tmake_file to t-eh-dw2-dip. (*-*-linux*, frv-*-*linux*, *-*-kfreebsd*-gnu, *-*-knetbsd*-gnu, *-*-gnu*): Likewise, also for *-*-kopensolaris*-gnu. (*-*-solaris2*): Add t-eh-dw2-dip to tmake_file. (arm*-*-linux*): Add arm/t-bpabi for arm*-*-linux-*eabi. Set unwind_header. (arm*-*-uclinux*): Add arm/t-bpabi for arm*-*-uclinux*eabi. Set unwind_header. (arm*-*-eabi*, arm*-*-symbianelf*): Add arm/t-bpabi for arm*-*-eabi*. Add arm/t-symbian to tmake_file for arm*-*-symbianelf*. Set unwind_header. (ia64*-*-elf*): Add ia64/t-eh-ia64 to tmake_file. (ia64*-*-freebsd*): Likewise. (ia64*-*-linux*): Add ia64/t-glibc, ia64/t-eh-ia64, t-libunwind to tmake_file. Add t-libunwind-elf, ia64/t-glibc-libunwind unless $with_system_libunwind. (ia64*-*-hpux*): Set tmake_file. (ia64-hp-*vms*): Add ia64/t-eh-ia64 to tmake_file. (picochip-*-*): Set tmake_file. (rs6000-ibm-aix4.[3456789]*, powerpc-ibm-aix4.[3456789]*): Set md_unwind_header. (rs6000-ibm-aix5.1.*, powerpc-ibm-aix5.1.*): Likewise. (rs6000-ibm-aix[56789].*, powerpc-ibm-aix[56789].*): Likewise. (s390x-ibm-tpf*): Add t-eh-dw2-dip to tmake_file. (xtensa*-*-elf*): Set tmake_file. (xtensa*-*-linux*): Likewise. * configure.ac: Include ../config/unwind_ipinfo.m4. Call GCC_CHECK_UNWIND_GETIPINFO. Link unwind.h to $unwind_header. * configure: Regenerate. * emutls.c, unwind-c.c, unwind-compat.c, unwind-compat.h, unwind-dw2-fde-compat.c, unwind-dw2-fde-dip.c, unwind-dw2-fde.c, unwind-dw2-fde.h, unwind-dw2.c, unwind-dw2.h, unwind-generic.h, unwind-pe.h, unwind-sjlj.c, unwind.inc: New files. * config/unwind-dw2-fde-darwin.c: New file. * config/arm/libunwind.S, config/arm/pr-support.c, config/arm/t-bpabi, config/arm/t-symbian, config/arm/unwind-arm.c, config/arm/unwind-arm.h,: New files. * config/ia64/fde-glibc.c, config/ia64/fde-vms.c, config/ia64/t-eh-ia64, config/ia64/t-glibc, config/ia64/t-glibc-libunwind, config/ia64/t-hpux, config/ia64/t-vms, config/ia64/unwind-ia64.c, config/ia64/unwind-ia64.h: New files. * config/picochip/t-picochip: New file. * config/rs6000/aix-unwind.h, config/rs6000/darwin-fallback.c: New files. * config/rs6000/t-darwin (LIB2ADDEH): Set. * config/s390/t-tpf (LIB2ADDEH): Remove. * config/t-darwin (LIB2ADDEH): Set. * config/t-eh-dw2-dip: New file. * config/t-libunwind, config/t-libunwind-elf: New files. * config/t-sol2 (LIB2ADDEH): Remove. * config/xtensa/t-xtensa: New file. gcc/ada: * gcc-interface/Makefile.in (raise-gcc.o): Search $(srcdir)/../libgcc. libgo: * Makefile.am (AM_CFLAGS): Search $(srcdir)/../libgcc. * Makefile.in: Regenerate. libjava: * configure.ac (GCC_UNWIND_INCLUDE): Rename to LIBGCC_UNWIND_INCLUDE. Point to $(multi_basedir)/./libjava/../libgcc. * configure: Regenerate. * Makefile.am (GCC_UNWIND_INCLUDE): Reflect this. * Makefile.in: Regenerate. libobjc: * Makefile.in (INCLUDES): Search $(srcdir)/$(MULTISRCTOP)../libgcc. libstdc++-v3: * acinclude.m4 (GLIBCXX_EXPORT_INCLUDES): Point TOPLEVEL_INCLUDES to $(toplevel_srcdir)/libgcc. * configure: Regenerate. From-SVN: r177447 --- libgcc/emutls.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 libgcc/emutls.c (limited to 'libgcc/emutls.c') diff --git a/libgcc/emutls.c b/libgcc/emutls.c new file mode 100644 index 0000000..b7ee3bd --- /dev/null +++ b/libgcc/emutls.c @@ -0,0 +1,202 @@ +/* TLS emulation. + Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc. + Contributed by Jakub Jelinek . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "tconfig.h" +#include "tsystem.h" +#include "coretypes.h" +#include "tm.h" +#include "gthr.h" + +typedef unsigned int word __attribute__((mode(word))); +typedef unsigned int pointer __attribute__((mode(pointer))); + +struct __emutls_object +{ + word size; + word align; + union { + pointer offset; + void *ptr; + } loc; + void *templ; +}; + +struct __emutls_array +{ + pointer size; + void **data[]; +}; + +void *__emutls_get_address (struct __emutls_object *); +void __emutls_register_common (struct __emutls_object *, word, word, void *); + +#ifdef __GTHREADS +#ifdef __GTHREAD_MUTEX_INIT +static __gthread_mutex_t emutls_mutex = __GTHREAD_MUTEX_INIT; +#else +static __gthread_mutex_t emutls_mutex; +#endif +static __gthread_key_t emutls_key; +static pointer emutls_size; + +static void +emutls_destroy (void *ptr) +{ + struct __emutls_array *arr = ptr; + pointer size = arr->size; + pointer i; + + for (i = 0; i < size; ++i) + { + if (arr->data[i]) + free (arr->data[i][-1]); + } + + free (ptr); +} + +static void +emutls_init (void) +{ +#ifndef __GTHREAD_MUTEX_INIT + __GTHREAD_MUTEX_INIT_FUNCTION (&emutls_mutex); +#endif + if (__gthread_key_create (&emutls_key, emutls_destroy) != 0) + abort (); +} +#endif + +static void * +emutls_alloc (struct __emutls_object *obj) +{ + void *ptr; + void *ret; + + /* We could use here posix_memalign if available and adjust + emutls_destroy accordingly. */ + if (obj->align <= sizeof (void *)) + { + ptr = malloc (obj->size + sizeof (void *)); + if (ptr == NULL) + abort (); + ((void **) ptr)[0] = ptr; + ret = ptr + sizeof (void *); + } + else + { + ptr = malloc (obj->size + sizeof (void *) + obj->align - 1); + if (ptr == NULL) + abort (); + ret = (void *) (((pointer) (ptr + sizeof (void *) + obj->align - 1)) + & ~(pointer)(obj->align - 1)); + ((void **) ret)[-1] = ptr; + } + + if (obj->templ) + memcpy (ret, obj->templ, obj->size); + else + memset (ret, 0, obj->size); + + return ret; +} + +void * +__emutls_get_address (struct __emutls_object *obj) +{ + if (! __gthread_active_p ()) + { + if (__builtin_expect (obj->loc.ptr == NULL, 0)) + obj->loc.ptr = emutls_alloc (obj); + return obj->loc.ptr; + } + +#ifndef __GTHREADS + abort (); +#else + pointer offset = obj->loc.offset; + + if (__builtin_expect (offset == 0, 0)) + { + static __gthread_once_t once = __GTHREAD_ONCE_INIT; + __gthread_once (&once, emutls_init); + __gthread_mutex_lock (&emutls_mutex); + offset = obj->loc.offset; + if (offset == 0) + { + offset = ++emutls_size; + obj->loc.offset = offset; + } + __gthread_mutex_unlock (&emutls_mutex); + } + + struct __emutls_array *arr = __gthread_getspecific (emutls_key); + if (__builtin_expect (arr == NULL, 0)) + { + pointer size = offset + 32; + arr = calloc (size + 1, sizeof (void *)); + if (arr == NULL) + abort (); + arr->size = size; + __gthread_setspecific (emutls_key, (void *) arr); + } + else if (__builtin_expect (offset > arr->size, 0)) + { + pointer orig_size = arr->size; + pointer size = orig_size * 2; + if (offset > size) + size = offset + 32; + arr = realloc (arr, (size + 1) * sizeof (void *)); + if (arr == NULL) + abort (); + arr->size = size; + memset (arr->data + orig_size, 0, + (size - orig_size) * sizeof (void *)); + __gthread_setspecific (emutls_key, (void *) arr); + } + + void *ret = arr->data[offset - 1]; + if (__builtin_expect (ret == NULL, 0)) + { + ret = emutls_alloc (obj); + arr->data[offset - 1] = ret; + } + return ret; +#endif +} + +void +__emutls_register_common (struct __emutls_object *obj, + word size, word align, void *templ) +{ + if (obj->size < size) + { + obj->size = size; + obj->templ = NULL; + } + if (obj->align < align) + obj->align = align; + if (templ && size == obj->size) + obj->templ = templ; +} -- cgit v1.1