Mercurial > hg > graal-compiler
annotate src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp @ 3320:ca7c15a01229
Merge
author | jmasa |
---|---|
date | Mon, 02 May 2011 07:08:53 -0700 |
parents | f95d63e2154a |
children | f34d701e952e |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "runtime/threadLocalStorage.hpp" | |
27 #include "thread_solaris.inline.hpp" | |
0 | 28 |
29 #ifdef AMD64 | |
30 extern "C" Thread* fs_load(ptrdiff_t tlsOffset); | |
31 extern "C" intptr_t fs_thread(); | |
32 #else | |
33 // From solaris_i486.s | |
34 extern "C" Thread* gs_load(ptrdiff_t tlsOffset); | |
35 extern "C" intptr_t gs_thread(); | |
36 #endif // AMD64 | |
37 | |
38 // tlsMode encoding: | |
39 // | |
40 // pd_tlsAccessUndefined : uninitialized | |
41 // pd_tlsAccessSlow : not available | |
42 // pd_tlsAccessIndirect : | |
43 // old-style indirect access - present in "T1" libthread. | |
44 // use thr_slot_sync_allocate() to attempt to allocate a slot. | |
45 // pd_tlsAccessDirect : | |
46 // new-style direct access - present in late-model "T2" libthread. | |
47 // Allocate the offset (slot) via _thr_slot_offset() or by | |
48 // defining an IE- or LE-mode TLS/TSD slot in the launcher and then passing | |
49 // that offset into libjvm.so. | |
50 // See http://sac.eng/Archives/CaseLog/arc/PSARC/2003/159/. | |
51 // | |
52 // Note that we have a capability gap - some early model T2 forms | |
53 // (e.g., unpatched S9) have neither _thr_slot_sync_allocate() nor | |
54 // _thr_slot_offset(). In that case we revert to the usual | |
55 // thr_getspecific accessor. | |
56 // | |
57 | |
58 static ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_tlsAccessUndefined ; | |
59 static ptrdiff_t tlsOffset = 0 ; | |
60 static thread_key_t tlsKey ; | |
61 | |
62 typedef int (*TSSA_Entry) (ptrdiff_t *, int, int) ; | |
63 typedef ptrdiff_t (*TSO_Entry) (int) ; | |
64 | |
65 ThreadLocalStorage::pd_tlsAccessMode ThreadLocalStorage::pd_getTlsAccessMode () | |
66 { | |
67 guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; | |
68 return tlsMode ; | |
69 } | |
70 | |
71 ptrdiff_t ThreadLocalStorage::pd_getTlsOffset () { | |
72 guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; | |
73 return tlsOffset ; | |
74 } | |
75 | |
76 // TODO: Consider the following improvements: | |
77 // | |
78 // 1. Convert from thr_*specific* to pthread_*specific*. | |
79 // The pthread_ forms are slightly faster. Also, the | |
80 // pthread_ forms have a pthread_key_delete() API which | |
81 // would aid in clean JVM shutdown and the eventual goal | |
82 // of permitting a JVM to reinstantiate itself withing a process. | |
83 // | |
84 // 2. See ThreadLocalStorage::init(). We end up allocating | |
85 // two TLS keys during VM startup. That's benign, but we could collapse | |
86 // down to one key without too much trouble. | |
87 // | |
88 // 3. MacroAssembler::get_thread() currently emits calls to thr_getspecific(). | |
89 // Modify get_thread() to call Thread::current() instead. | |
90 // | |
91 // 4. Thread::current() currently uses a cache keyed by %gs:[0]. | |
92 // (The JVM has PSARC permission to use %g7/%gs:[0] | |
93 // as an opaque temporally unique thread identifier). | |
94 // For C++ access to a thread's reflexive "self" pointer we | |
95 // should consider using one of the following: | |
96 // a. a radix tree keyed by %esp - as in EVM. | |
97 // This requires two loads (the 2nd dependent on the 1st), but | |
98 // is easily inlined and doesn't require a "miss" slow path. | |
99 // b. a fast TLS/TSD slot allocated by _thr_slot_offset | |
100 // or _thr_slot_sync_allocate. | |
101 // | |
102 // 5. 'generate_code_for_get_thread' is a misnomer. | |
103 // We should change it to something more general like | |
104 // pd_ThreadSelf_Init(), for instance. | |
105 // | |
106 | |
107 static void AllocateTLSOffset () | |
108 { | |
109 int rslt ; | |
110 TSSA_Entry tssa ; | |
111 TSO_Entry tso ; | |
112 ptrdiff_t off ; | |
113 | |
114 guarantee (tlsMode == ThreadLocalStorage::pd_tlsAccessUndefined, "tlsMode not set") ; | |
115 tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; | |
116 tlsOffset = 0 ; | |
117 #ifndef AMD64 | |
118 | |
119 tssa = (TSSA_Entry) dlsym (RTLD_DEFAULT, "thr_slot_sync_allocate") ; | |
120 if (tssa != NULL) { | |
121 off = -1 ; | |
122 rslt = (*tssa)(&off, NULL, NULL) ; // (off,dtor,darg) | |
123 if (off != -1) { | |
124 tlsOffset = off ; | |
125 tlsMode = ThreadLocalStorage::pd_tlsAccessIndirect ; | |
126 return ; | |
127 } | |
128 } | |
129 | |
130 rslt = thr_keycreate (&tlsKey, NULL) ; | |
131 if (rslt != 0) { | |
132 tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; // revert to slow mode | |
133 return ; | |
134 } | |
135 | |
136 tso = (TSO_Entry) dlsym (RTLD_DEFAULT, "_thr_slot_offset") ; | |
137 if (tso != NULL) { | |
138 off = (*tso)(tlsKey) ; | |
139 if (off >= 0) { | |
140 tlsOffset = off ; | |
141 tlsMode = ThreadLocalStorage::pd_tlsAccessDirect ; | |
142 return ; | |
143 } | |
144 } | |
145 | |
146 // Failure: Too bad ... we've allocated a TLS slot we don't need and there's | |
147 // no provision in the ABI for returning the slot. | |
148 // | |
149 // If we didn't find a slot then then: | |
150 // 1. We might be on liblwp. | |
151 // 2. We might be on T2 libthread, but all "fast" slots are already | |
152 // consumed | |
153 // 3. We might be on T1, and all TSD (thr_slot_sync_allocate) slots are | |
154 // consumed. | |
155 // 4. We might be on T2 libthread, but it's be re-architected | |
156 // so that fast slots are no longer g7-relative. | |
157 // | |
158 | |
159 tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; | |
160 return ; | |
161 #endif // AMD64 | |
162 } | |
163 | |
164 void ThreadLocalStorage::generate_code_for_get_thread() { | |
165 AllocateTLSOffset() ; | |
166 } | |
167 | |
168 void ThreadLocalStorage::set_thread_in_slot(Thread *thread) { | |
169 guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; | |
170 if (tlsMode == pd_tlsAccessIndirect) { | |
171 #ifdef AMD64 | |
172 intptr_t tbase = fs_thread(); | |
173 #else | |
174 intptr_t tbase = gs_thread(); | |
175 #endif // AMD64 | |
176 *((Thread**) (tbase + tlsOffset)) = thread ; | |
177 } else | |
178 if (tlsMode == pd_tlsAccessDirect) { | |
179 thr_setspecific (tlsKey, (void *) thread) ; | |
180 // set with thr_setspecific and then readback with gs_load to validate. | |
181 #ifdef AMD64 | |
182 guarantee (thread == fs_load(tlsOffset), "tls readback failure") ; | |
183 #else | |
184 guarantee (thread == gs_load(tlsOffset), "tls readback failure") ; | |
185 #endif // AMD64 | |
186 } | |
187 } | |
188 | |
189 | |
190 extern "C" Thread* get_thread() { | |
191 return ThreadLocalStorage::thread(); | |
192 } |