OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [emutls.c] - Blame information for rev 280

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 280 jeremybenn
/* TLS emulation.
2
   Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc.
3
   Contributed by Jakub Jelinek <jakub@redhat.com>.
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 3, or (at your option) any later
10
version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
for more details.
16
 
17
Under Section 7 of GPL version 3, you are granted additional
18
permissions described in the GCC Runtime Library Exception, version
19
3.1, as published by the Free Software Foundation.
20
 
21
You should have received a copy of the GNU General Public License and
22
a copy of the GCC Runtime Library Exception along with this program;
23
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24
<http://www.gnu.org/licenses/>.  */
25
 
26
#include "tconfig.h"
27
#include "tsystem.h"
28
#include "coretypes.h"
29
#include "tm.h"
30
#include "gthr.h"
31
 
32
typedef unsigned int word __attribute__((mode(word)));
33
typedef unsigned int pointer __attribute__((mode(pointer)));
34
 
35
struct __emutls_object
36
{
37
  word size;
38
  word align;
39
  union {
40
    pointer offset;
41
    void *ptr;
42
  } loc;
43
  void *templ;
44
};
45
 
46
struct __emutls_array
47
{
48
  pointer size;
49
  void **data[];
50
};
51
 
52
void *__emutls_get_address (struct __emutls_object *);
53
void __emutls_register_common (struct __emutls_object *, word, word, void *);
54
 
55
#ifdef __GTHREADS
56
#ifdef __GTHREAD_MUTEX_INIT
57
static __gthread_mutex_t emutls_mutex = __GTHREAD_MUTEX_INIT;
58
#else
59
static __gthread_mutex_t emutls_mutex;
60
#endif
61
static __gthread_key_t emutls_key;
62
static pointer emutls_size;
63
 
64
static void
65
emutls_destroy (void *ptr)
66
{
67
  struct __emutls_array *arr = ptr;
68
  pointer size = arr->size;
69
  pointer i;
70
 
71
  for (i = 0; i < size; ++i)
72
    {
73
      if (arr->data[i])
74
        free (arr->data[i][-1]);
75
    }
76
 
77
  free (ptr);
78
}
79
 
80
static void
81
emutls_init (void)
82
{
83
#ifndef __GTHREAD_MUTEX_INIT
84
  __GTHREAD_MUTEX_INIT_FUNCTION (&emutls_mutex);
85
#endif
86
  if (__gthread_key_create (&emutls_key, emutls_destroy) != 0)
87
    abort ();
88
}
89
#endif
90
 
91
static void *
92
emutls_alloc (struct __emutls_object *obj)
93
{
94
  void *ptr;
95
  void *ret;
96
 
97
  /* We could use here posix_memalign if available and adjust
98
     emutls_destroy accordingly.  */
99
  if (obj->align <= sizeof (void *))
100
    {
101
      ptr = malloc (obj->size + sizeof (void *));
102
      if (ptr == NULL)
103
        abort ();
104
      ((void **) ptr)[0] = ptr;
105
      ret = ptr + sizeof (void *);
106
    }
107
  else
108
    {
109
      ptr = malloc (obj->size + sizeof (void *) + obj->align - 1);
110
      if (ptr == NULL)
111
        abort ();
112
      ret = (void *) (((pointer) (ptr + sizeof (void *) + obj->align - 1))
113
                      & ~(pointer)(obj->align - 1));
114
      ((void **) ret)[-1] = ptr;
115
    }
116
 
117
  if (obj->templ)
118
    memcpy (ret, obj->templ, obj->size);
119
  else
120
    memset (ret, 0, obj->size);
121
 
122
  return ret;
123
}
124
 
125
void *
126
__emutls_get_address (struct __emutls_object *obj)
127
{
128
  if (! __gthread_active_p ())
129
    {
130
      if (__builtin_expect (obj->loc.ptr == NULL, 0))
131
        obj->loc.ptr = emutls_alloc (obj);
132
      return obj->loc.ptr;
133
    }
134
 
135
#ifndef __GTHREADS
136
  abort ();
137
#else
138
  pointer offset = obj->loc.offset;
139
 
140
  if (__builtin_expect (offset == 0, 0))
141
    {
142
      static __gthread_once_t once = __GTHREAD_ONCE_INIT;
143
      __gthread_once (&once, emutls_init);
144
      __gthread_mutex_lock (&emutls_mutex);
145
      offset = obj->loc.offset;
146
      if (offset == 0)
147
        {
148
          offset = ++emutls_size;
149
          obj->loc.offset = offset;
150
        }
151
      __gthread_mutex_unlock (&emutls_mutex);
152
    }
153
 
154
  struct __emutls_array *arr = __gthread_getspecific (emutls_key);
155
  if (__builtin_expect (arr == NULL, 0))
156
    {
157
      pointer size = offset + 32;
158
      arr = calloc (size + 1, sizeof (void *));
159
      if (arr == NULL)
160
        abort ();
161
      arr->size = size;
162
      __gthread_setspecific (emutls_key, (void *) arr);
163
    }
164
  else if (__builtin_expect (offset > arr->size, 0))
165
    {
166
      pointer orig_size = arr->size;
167
      pointer size = orig_size * 2;
168
      if (offset > size)
169
        size = offset + 32;
170
      arr = realloc (arr, (size + 1) * sizeof (void *));
171
      if (arr == NULL)
172
        abort ();
173
      arr->size = size;
174
      memset (arr->data + orig_size, 0,
175
              (size - orig_size) * sizeof (void *));
176
      __gthread_setspecific (emutls_key, (void *) arr);
177
    }
178
 
179
  void *ret = arr->data[offset - 1];
180
  if (__builtin_expect (ret == NULL, 0))
181
    {
182
      ret = emutls_alloc (obj);
183
      arr->data[offset - 1] = ret;
184
    }
185
  return ret;
186
#endif
187
}
188
 
189
void
190
__emutls_register_common (struct __emutls_object *obj,
191
                          word size, word align, void *templ)
192
{
193
  if (obj->size < size)
194
    {
195
      obj->size = size;
196
      obj->templ = NULL;
197
    }
198
  if (obj->align < align)
199
    obj->align = align;
200
  if (templ && size == obj->size)
201
    obj->templ = templ;
202
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.