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
52 #ifdef __GTHREAD_MUTEX_INIT
53 static __gthread_mutex_t emutls_mutex
= __GTHREAD_MUTEX_INIT
;
55 static __gthread_mutex_t emutls_mutex
;
57 static __gthread_key_t emutls_key
;
58 static pointer emutls_size
;
61 emutls_destroy (void *ptr
)
63 void ***arr
= (void ***) ptr
;
64 unsigned long int size
= (unsigned long int) arr
[0];
78 #ifndef __GTHREAD_MUTEX_INIT
79 __GTHREAD_MUTEX_INIT_FUNCTION (&emutls_mutex
);
81 if (__gthread_key_create (&emutls_key
, emutls_destroy
) != 0)
87 emutls_alloc (struct __emutls_object
*obj
)
92 /* We could use here posix_memalign if available and adjust
93 emutls_destroy accordingly. */
94 if (obj
->align
<= sizeof (void *))
96 ptr
= malloc (obj
->size
+ sizeof (void *));
99 ((void **) ptr
)[0] = ptr
;
100 ret
= ptr
+ sizeof (void *);
104 ptr
= malloc (obj
->size
+ sizeof (void *) + obj
->align
- 1);
107 ret
= (void *) (((pointer
) (ptr
+ sizeof (void *) + obj
->align
- 1))
108 & ~(pointer
)(obj
->align
- 1));
109 ((void **) ret
)[-1] = ptr
;
113 memcpy (ret
, obj
->templ
, obj
->size
);
115 memset (ret
, 0, obj
->size
);
121 __emutls_get_address (struct __emutls_object
*obj
)
123 if (! __gthread_active_p ())
125 if (__builtin_expect (obj
->loc
.ptr
== NULL
, 0))
126 obj
->loc
.ptr
= emutls_alloc (obj
);
135 if (__builtin_expect (obj
->loc
.offset
== 0, 0))
137 static __gthread_once_t once
= __GTHREAD_ONCE_INIT
;
138 __gthread_once (&once
, emutls_init
);
139 __gthread_mutex_lock (&emutls_mutex
);
140 offset
= ++emutls_size
;
141 obj
->loc
.offset
= offset
;
142 __gthread_mutex_unlock (&emutls_mutex
);
145 offset
= obj
->loc
.offset
;
147 void **arr
= (void **) __gthread_getspecific (emutls_key
);
148 if (__builtin_expect (arr
== NULL
, 0))
150 pointer size
= offset
+ 32;
151 arr
= calloc (size
, sizeof (void *));
154 arr
[0] = (void *) size
;
155 __gthread_setspecific (emutls_key
, (void *) arr
);
157 else if (__builtin_expect (offset
>= (pointer
) arr
[0], 0))
159 pointer orig_size
= (pointer
) arr
[0];
160 pointer size
= orig_size
* 2;
163 arr
= realloc (arr
, size
* sizeof (void *));
166 memset (arr
+ orig_size
, 0, (size
- orig_size
) * sizeof (void *));
167 __gthread_setspecific (emutls_key
, (void *) arr
);
170 void *ret
= arr
[offset
];
171 if (__builtin_expect (ret
== NULL
, 0))
173 ret
= emutls_alloc (obj
);
181 __emutls_register_common (struct __emutls_object
*obj
,
182 word size
, word align
, void *templ
)
184 if (obj
->size
< size
)
189 if (obj
->align
< align
)
191 if (templ
&& size
== obj
->size
)