X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Femutls.c;h=b7ee3bdfa7cec09b1f43aba5bed1132e71cea4ee;hb=7717ea00902734bd90371e34af23d0b73287f875;hp=f26d21772e3907607352891f604ca8b6fe13dfc7;hpb=2551f8e0be582a9e3fa959425842978d4c6772dc;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/emutls.c b/gcc/emutls.c index f26d21772e3..b7ee3bdfa7c 100644 --- a/gcc/emutls.c +++ b/gcc/emutls.c @@ -1,32 +1,27 @@ /* TLS emulation. - Copyright (C) 2006 Free Software Foundation, Inc. + 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 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. -In addition to the permissions in the GNU General Public License, the -Free Software Foundation gives you unlimited permission to link the -compiled version of this file into combinations with other programs, -and to distribute those combinations without any restriction coming -from the use of this file. (The General Public License restrictions -do apply in other respects; for example, they cover modification of -the file, and distribution when not linked into a combine -executable.) - 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. -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +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" @@ -48,6 +43,15 @@ struct __emutls_object 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; @@ -60,15 +64,16 @@ static pointer emutls_size; static void emutls_destroy (void *ptr) { - void ***arr = (void ***) ptr; - unsigned long int size = (unsigned long int) arr[0]; - ++arr; - while (--size) + struct __emutls_array *arr = ptr; + pointer size = arr->size; + pointer i; + + for (i = 0; i < size; ++i) { - if (*arr) - free ((*arr)[-1]); - ++arr; + if (arr->data[i]) + free (arr->data[i][-1]); } + free (ptr); } @@ -130,48 +135,52 @@ __emutls_get_address (struct __emutls_object *obj) #ifndef __GTHREADS abort (); #else - pointer offset; + pointer offset = obj->loc.offset; - if (__builtin_expect (obj->loc.offset == 0, 0)) + 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 = ++emutls_size; - obj->loc.offset = offset; + offset = obj->loc.offset; + if (offset == 0) + { + offset = ++emutls_size; + obj->loc.offset = offset; + } __gthread_mutex_unlock (&emutls_mutex); } - else - offset = obj->loc.offset; - void **arr = (void **) __gthread_getspecific (emutls_key); + struct __emutls_array *arr = __gthread_getspecific (emutls_key); if (__builtin_expect (arr == NULL, 0)) { pointer size = offset + 32; - arr = calloc (size, sizeof (void *)); + arr = calloc (size + 1, sizeof (void *)); if (arr == NULL) abort (); - arr[0] = (void *) size; + arr->size = size; __gthread_setspecific (emutls_key, (void *) arr); } - else if (__builtin_expect (offset >= (pointer) arr[0], 0)) + else if (__builtin_expect (offset > arr->size, 0)) { - pointer orig_size = (pointer) arr[0]; + pointer orig_size = arr->size; pointer size = orig_size * 2; - if (offset >= size) + if (offset > size) size = offset + 32; - arr = realloc (arr, size * sizeof (void *)); + arr = realloc (arr, (size + 1) * sizeof (void *)); if (arr == NULL) abort (); - memset (arr + orig_size, 0, (size - orig_size) * sizeof (void *)); + arr->size = size; + memset (arr->data + orig_size, 0, + (size - orig_size) * sizeof (void *)); __gthread_setspecific (emutls_key, (void *) arr); } - void *ret = arr[offset]; + void *ret = arr->data[offset - 1]; if (__builtin_expect (ret == NULL, 0)) { ret = emutls_alloc (obj); - arr[offset] = ret; + arr->data[offset - 1] = ret; } return ret; #endif