OSDN Git Service

* gcc.target/powerpc/ppc-sdata-1.c: Require nonpic.
[pf3gnuchains/gcc-fork.git] / gcc / emutls.c
index c3374a1..b7ee3bd 100644 (file)
@@ -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 <jakub@redhat.com>.
 
 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
+<http://www.gnu.org/licenses/>.  */
 
 #include "tconfig.h"
 #include "tsystem.h"
@@ -54,6 +49,9 @@ struct __emutls_array
   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;
@@ -144,8 +142,12 @@ __emutls_get_address (struct __emutls_object *obj)
       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);
     }
 
@@ -153,23 +155,23 @@ __emutls_get_address (struct __emutls_object *obj)
   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->size = size;
       __gthread_setspecific (emutls_key, (void *) arr);
     }
-  else if (__builtin_expect (offset >= arr->size, 0))
+  else if (__builtin_expect (offset > arr->size, 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 ();
       arr->size = size;
-      memset (arr->data + orig_size - 1, 0,
+      memset (arr->data + orig_size, 0,
              (size - orig_size) * sizeof (void *));
       __gthread_setspecific (emutls_key, (void *) arr);
     }