2 Copyright (C) 2006 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>.
5 This file is part of GCC.
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 2, or (at your option) any later
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
21 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
22 WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 You should have received a copy of the GNU General Public License
27 along with GCC; see the file COPYING. If not, write to the Free
28 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
33 #include "coretypes.h"
37 typedef unsigned int word
__attribute__((mode(word
)));
38 typedef unsigned int pointer
__attribute__((mode(pointer
)));
40 struct __emutls_object
58 #ifdef __GTHREAD_MUTEX_INIT
59 static __gthread_mutex_t emutls_mutex
= __GTHREAD_MUTEX_INIT
;
61 static __gthread_mutex_t emutls_mutex
;
63 static __gthread_key_t emutls_key
;
64 static pointer emutls_size
;
67 emutls_destroy (void *ptr
)
69 struct __emutls_array
*arr
= ptr
;
70 pointer size
= arr
->size
;
73 for (i
= 0; i
< size
; ++i
)
76 free (arr
->data
[i
][-1]);
85 #ifndef __GTHREAD_MUTEX_INIT
86 __GTHREAD_MUTEX_INIT_FUNCTION (&emutls_mutex
);
88 if (__gthread_key_create (&emutls_key
, emutls_destroy
) != 0)
94 emutls_alloc (struct __emutls_object
*obj
)
99 /* We could use here posix_memalign if available and adjust
100 emutls_destroy accordingly. */
101 if (obj
->align
<= sizeof (void *))
103 ptr
= malloc (obj
->size
+ sizeof (void *));
106 ((void **) ptr
)[0] = ptr
;
107 ret
= ptr
+ sizeof (void *);
111 ptr
= malloc (obj
->size
+ sizeof (void *) + obj
->align
- 1);
114 ret
= (void *) (((pointer
) (ptr
+ sizeof (void *) + obj
->align
- 1))
115 & ~(pointer
)(obj
->align
- 1));
116 ((void **) ret
)[-1] = ptr
;
120 memcpy (ret
, obj
->templ
, obj
->size
);
122 memset (ret
, 0, obj
->size
);
128 __emutls_get_address (struct __emutls_object
*obj
)
130 if (! __gthread_active_p ())
132 if (__builtin_expect (obj
->loc
.ptr
== NULL
, 0))
133 obj
->loc
.ptr
= emutls_alloc (obj
);
140 pointer offset
= obj
->loc
.offset
;
142 if (__builtin_expect (offset
== 0, 0))
144 static __gthread_once_t once
= __GTHREAD_ONCE_INIT
;
145 __gthread_once (&once
, emutls_init
);
146 __gthread_mutex_lock (&emutls_mutex
);
147 offset
= ++emutls_size
;
148 obj
->loc
.offset
= offset
;
149 __gthread_mutex_unlock (&emutls_mutex
);
152 struct __emutls_array
*arr
= __gthread_getspecific (emutls_key
);
153 if (__builtin_expect (arr
== NULL
, 0))
155 pointer size
= offset
+ 32;
156 arr
= calloc (size
, sizeof (void *));
160 __gthread_setspecific (emutls_key
, (void *) arr
);
162 else if (__builtin_expect (offset
>= arr
->size
, 0))
164 pointer orig_size
= arr
->size
;
165 pointer size
= orig_size
* 2;
168 arr
= realloc (arr
, size
* sizeof (void *));
172 memset (arr
->data
+ orig_size
- 1, 0,
173 (size
- orig_size
) * sizeof (void *));
174 __gthread_setspecific (emutls_key
, (void *) arr
);
177 void *ret
= arr
->data
[offset
- 1];
178 if (__builtin_expect (ret
== NULL
, 0))
180 ret
= emutls_alloc (obj
);
181 arr
->data
[offset
- 1] = ret
;
188 __emutls_register_common (struct __emutls_object
*obj
,
189 word size
, word align
, void *templ
)
191 if (obj
->size
< size
)
196 if (obj
->align
< align
)
198 if (templ
&& size
== obj
->size
)