Mercurial > hg > CbC > CbC_gcc
annotate gcc/emutls.c @ 58:3aaf117db171
error at dwarf2out.c
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 15 Feb 2010 14:58:24 +0900 |
parents | 58ad6c70ea60 |
children |
rev | line source |
---|---|
0 | 1 /* 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; | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
158 arr = calloc (size + 1, sizeof (void *)); |
0 | 159 if (arr == NULL) |
160 abort (); | |
161 arr->size = size; | |
162 __gthread_setspecific (emutls_key, (void *) arr); | |
163 } | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
164 else if (__builtin_expect (offset > arr->size, 0)) |
0 | 165 { |
166 pointer orig_size = arr->size; | |
167 pointer size = orig_size * 2; | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
168 if (offset > size) |
0 | 169 size = offset + 32; |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
170 arr = realloc (arr, (size + 1) * sizeof (void *)); |
0 | 171 if (arr == NULL) |
172 abort (); | |
173 arr->size = size; | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
174 memset (arr->data + orig_size, 0, |
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 } |