Mercurial > hg > graal-compiler
annotate src/os/linux/vm/os_linux.hpp @ 12176:88c255656030
8016155: SIGBUS when running Kitchensink with ParallelScavenge and ParallelOld
Summary: When using NUMA and large pages we need to ease the requirement on which node the memory should be allocated on. To avoid the SIGBUS we now use the memory policy MPOL_PREFERRED, which prefers a certain node, instead of MPOL_BIND, which requires a certain node.
Reviewed-by: jmasa, pliden
Contributed-by: stefan.johansson@oracle.com
author | mgerdin |
---|---|
date | Thu, 22 Aug 2013 10:50:41 +0200 |
parents | a837fa3d3f86 |
children | 0d59407e7e09 |
rev | line source |
---|---|
0 | 1 /* |
8675
63e54c37ac64
8008959: Fix non-PCH build on Linux, Windows and MacOS X
simonis
parents:
6630
diff
changeset
|
2 * Copyright (c) 1999, 2013, 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:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
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:
844
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef OS_LINUX_VM_OS_LINUX_HPP |
26 #define OS_LINUX_VM_OS_LINUX_HPP | |
27 | |
0 | 28 // Linux_OS defines the interface to Linux operating systems |
29 | |
30 /* pthread_getattr_np comes with LinuxThreads-0.9-7 on RedHat 7.1 */ | |
31 typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *); | |
32 | |
33 class Linux { | |
34 friend class os; | |
35 | |
36 // For signal-chaining | |
37 #define MAXSIGNUM 32 | |
38 static struct sigaction sigact[MAXSIGNUM]; // saved preinstalled sigactions | |
39 static unsigned int sigs; // mask of signals that have | |
40 // preinstalled signal handlers | |
41 static bool libjsig_is_loaded; // libjsig that interposes sigaction(), | |
42 // __sigaction(), signal() is loaded | |
43 static struct sigaction *(*get_signal_action)(int); | |
44 static struct sigaction *get_preinstalled_handler(int); | |
45 static void save_preinstalled_handler(int, struct sigaction&); | |
46 | |
47 static void check_signal_handler(int sig); | |
48 | |
49 // For signal flags diagnostics | |
50 static int sigflags[MAXSIGNUM]; | |
51 | |
52 static int (*_clock_gettime)(clockid_t, struct timespec *); | |
53 static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *); | |
54 | |
55 static address _initial_thread_stack_bottom; | |
56 static uintptr_t _initial_thread_stack_size; | |
57 | |
199
f139919897d2
6681796: hotspot build failure on gcc 4.2.x (ubuntu 8.04) w/ openjdk 6
xlu
parents:
141
diff
changeset
|
58 static const char *_glibc_version; |
f139919897d2
6681796: hotspot build failure on gcc 4.2.x (ubuntu 8.04) w/ openjdk 6
xlu
parents:
141
diff
changeset
|
59 static const char *_libpthread_version; |
0 | 60 |
61 static bool _is_floating_stack; | |
62 static bool _is_NPTL; | |
63 static bool _supports_fast_thread_cpu_time; | |
64 | |
141 | 65 static GrowableArray<int>* _cpu_to_node; |
66 | |
0 | 67 protected: |
68 | |
69 static julong _physical_memory; | |
70 static pthread_t _main_thread; | |
71 static Mutex* _createThread_lock; | |
72 static int _page_size; | |
10164
b4081e9714ec
8013398: Adjust number of stack guard pages on systems with large memory page size
vladidan
parents:
8812
diff
changeset
|
73 static const int _vm_default_page_size; |
0 | 74 |
75 static julong available_memory(); | |
76 static julong physical_memory() { return _physical_memory; } | |
77 static void initialize_system_info(); | |
78 | |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
79 static int commit_memory_impl(char* addr, size_t bytes, bool exec); |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
80 static int commit_memory_impl(char* addr, size_t bytes, |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
81 size_t alignment_hint, bool exec); |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
82 |
199
f139919897d2
6681796: hotspot build failure on gcc 4.2.x (ubuntu 8.04) w/ openjdk 6
xlu
parents:
141
diff
changeset
|
83 static void set_glibc_version(const char *s) { _glibc_version = s; } |
f139919897d2
6681796: hotspot build failure on gcc 4.2.x (ubuntu 8.04) w/ openjdk 6
xlu
parents:
141
diff
changeset
|
84 static void set_libpthread_version(const char *s) { _libpthread_version = s; } |
0 | 85 |
86 static bool supports_variable_stack_size(); | |
87 | |
88 static void set_is_NPTL() { _is_NPTL = true; } | |
89 static void set_is_LinuxThreads() { _is_NPTL = false; } | |
90 static void set_is_floating_stack() { _is_floating_stack = true; } | |
91 | |
141 | 92 static void rebuild_cpu_to_node_map(); |
93 static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; } | |
3286
139667d9836a
7034464: Support transparent large pages on Linux
iveresov
parents:
1972
diff
changeset
|
94 |
139667d9836a
7034464: Support transparent large pages on Linux
iveresov
parents:
1972
diff
changeset
|
95 static bool hugetlbfs_sanity_check(bool warn, size_t page_size); |
139667d9836a
7034464: Support transparent large pages on Linux
iveresov
parents:
1972
diff
changeset
|
96 |
6080
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
3826
diff
changeset
|
97 static void print_full_memory_info(outputStream* st); |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
3826
diff
changeset
|
98 static void print_distro_info(outputStream* st); |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
3826
diff
changeset
|
99 static void print_libversion_info(outputStream* st); |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
3826
diff
changeset
|
100 |
0 | 101 public: |
8710
9058789475af
7107135: Stack guard pages are no more protected after loading a shared library with executable stack
iklam
parents:
8675
diff
changeset
|
102 static bool _stack_is_executable; |
8812
14509df4cd63
8010389: After fix for 7107135 a failed dlopen() call results in a VM crash
iklam
parents:
8710
diff
changeset
|
103 static void *dlopen_helper(const char *name, char *ebuf, int ebuflen); |
14509df4cd63
8010389: After fix for 7107135 a failed dlopen() call results in a VM crash
iklam
parents:
8710
diff
changeset
|
104 static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen); |
8710
9058789475af
7107135: Stack guard pages are no more protected after loading a shared library with executable stack
iklam
parents:
8675
diff
changeset
|
105 |
0 | 106 static void init_thread_fpu_state(); |
107 static int get_fpu_control_word(); | |
108 static void set_fpu_control_word(int fpu_control); | |
109 static pthread_t main_thread(void) { return _main_thread; } | |
110 // returns kernel thread id (similar to LWP id on Solaris), which can be | |
111 // used to access /proc | |
112 static pid_t gettid(); | |
113 static void set_createThread_lock(Mutex* lk) { _createThread_lock = lk; } | |
114 static Mutex* createThread_lock(void) { return _createThread_lock; } | |
115 static void hotspot_sigmask(Thread* thread); | |
116 | |
117 static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; } | |
118 static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; } | |
119 static bool is_initial_thread(void); | |
120 | |
121 static int page_size(void) { return _page_size; } | |
122 static void set_page_size(int val) { _page_size = val; } | |
123 | |
10164
b4081e9714ec
8013398: Adjust number of stack guard pages on systems with large memory page size
vladidan
parents:
8812
diff
changeset
|
124 static int vm_default_page_size(void) { return _vm_default_page_size; } |
b4081e9714ec
8013398: Adjust number of stack guard pages on systems with large memory page size
vladidan
parents:
8812
diff
changeset
|
125 |
0 | 126 static address ucontext_get_pc(ucontext_t* uc); |
127 static intptr_t* ucontext_get_sp(ucontext_t* uc); | |
128 static intptr_t* ucontext_get_fp(ucontext_t* uc); | |
129 | |
130 // For Analyzer Forte AsyncGetCallTrace profiling support: | |
131 // | |
132 // This interface should be declared in os_linux_i486.hpp, but | |
133 // that file provides extensions to the os class and not the | |
134 // Linux class. | |
135 static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc, | |
136 intptr_t** ret_sp, intptr_t** ret_fp); | |
137 | |
138 // This boolean allows users to forward their own non-matching signals | |
139 // to JVM_handle_linux_signal, harmlessly. | |
140 static bool signal_handlers_are_installed; | |
141 | |
142 static int get_our_sigflags(int); | |
143 static void set_our_sigflags(int, int); | |
144 static void signal_sets_init(); | |
145 static void install_signal_handlers(); | |
146 static void set_signal_handler(int, bool); | |
147 static bool is_sig_ignored(int sig); | |
148 | |
149 static sigset_t* unblocked_signals(); | |
150 static sigset_t* vm_signals(); | |
151 static sigset_t* allowdebug_blocked_signals(); | |
152 | |
153 // For signal-chaining | |
154 static struct sigaction *get_chained_signal_action(int sig); | |
155 static bool chained_handler(int sig, siginfo_t* siginfo, void* context); | |
156 | |
157 // GNU libc and libpthread version strings | |
199
f139919897d2
6681796: hotspot build failure on gcc 4.2.x (ubuntu 8.04) w/ openjdk 6
xlu
parents:
141
diff
changeset
|
158 static const char *glibc_version() { return _glibc_version; } |
f139919897d2
6681796: hotspot build failure on gcc 4.2.x (ubuntu 8.04) w/ openjdk 6
xlu
parents:
141
diff
changeset
|
159 static const char *libpthread_version() { return _libpthread_version; } |
0 | 160 |
161 // NPTL or LinuxThreads? | |
162 static bool is_LinuxThreads() { return !_is_NPTL; } | |
163 static bool is_NPTL() { return _is_NPTL; } | |
164 | |
165 // NPTL is always floating stack. LinuxThreads could be using floating | |
166 // stack or fixed stack. | |
167 static bool is_floating_stack() { return _is_floating_stack; } | |
168 | |
169 static void libpthread_init(); | |
462
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
170 static bool libnuma_init(); |
763
cf71f149d7ae
6840196: NUMA allocator: crash in fastdebug during startup on Linux
iveresov
parents:
462
diff
changeset
|
171 static void* libnuma_dlsym(void* handle, const char* name); |
0 | 172 // Minimum stack size a thread can be created with (allowing |
173 // the VM to completely create the thread and enter user code) | |
174 static size_t min_stack_allowed; | |
175 | |
176 // Return default stack size or guard size for the specified thread type | |
177 static size_t default_stack_size(os::ThreadType thr_type); | |
178 static size_t default_guard_size(os::ThreadType thr_type); | |
179 | |
180 static void capture_initial_stack(size_t max_size); | |
181 | |
182 // Stack overflow handling | |
183 static bool manually_expand_stack(JavaThread * t, address addr); | |
184 static int max_register_window_saves_before_flushing(); | |
185 | |
186 // Real-time clock functions | |
187 static void clock_init(void); | |
188 | |
189 // fast POSIX clocks support | |
190 static void fast_thread_clock_init(void); | |
191 | |
6630
fa9253dcd4df
7194409: os::javaTimeNanos() shows hot on CPU_CLK_UNHALTED profiles
johnc
parents:
6197
diff
changeset
|
192 static inline bool supports_monotonic_clock() { |
0 | 193 return _clock_gettime != NULL; |
194 } | |
195 | |
196 static int clock_gettime(clockid_t clock_id, struct timespec *tp) { | |
197 return _clock_gettime ? _clock_gettime(clock_id, tp) : -1; | |
198 } | |
199 | |
200 static int pthread_getcpuclockid(pthread_t tid, clockid_t *clock_id) { | |
201 return _pthread_getcpuclockid ? _pthread_getcpuclockid(tid, clock_id) : -1; | |
202 } | |
203 | |
204 static bool supports_fast_thread_cpu_time() { | |
205 return _supports_fast_thread_cpu_time; | |
206 } | |
207 | |
208 static jlong fast_thread_cpu_time(clockid_t clockid); | |
209 | |
210 // Stack repair handling | |
211 | |
212 // none present | |
213 | |
214 // LinuxThreads work-around for 6292965 | |
215 static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime); | |
216 | |
141 | 217 private: |
218 typedef int (*sched_getcpu_func_t)(void); | |
219 typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen); | |
220 typedef int (*numa_max_node_func_t)(void); | |
221 typedef int (*numa_available_func_t)(void); | |
222 typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node); | |
462
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
223 typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask); |
12176
88c255656030
8016155: SIGBUS when running Kitchensink with ParallelScavenge and ParallelOld
mgerdin
parents:
10969
diff
changeset
|
224 typedef void (*numa_set_bind_policy_func_t)(int policy); |
141 | 225 |
226 static sched_getcpu_func_t _sched_getcpu; | |
227 static numa_node_to_cpus_func_t _numa_node_to_cpus; | |
228 static numa_max_node_func_t _numa_max_node; | |
229 static numa_available_func_t _numa_available; | |
230 static numa_tonode_memory_func_t _numa_tonode_memory; | |
462
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
231 static numa_interleave_memory_func_t _numa_interleave_memory; |
12176
88c255656030
8016155: SIGBUS when running Kitchensink with ParallelScavenge and ParallelOld
mgerdin
parents:
10969
diff
changeset
|
232 static numa_set_bind_policy_func_t _numa_set_bind_policy; |
462
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
233 static unsigned long* _numa_all_nodes; |
141 | 234 |
235 static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; } | |
236 static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; } | |
237 static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; } | |
238 static void set_numa_available(numa_available_func_t func) { _numa_available = func; } | |
239 static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; } | |
462
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
240 static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; } |
12176
88c255656030
8016155: SIGBUS when running Kitchensink with ParallelScavenge and ParallelOld
mgerdin
parents:
10969
diff
changeset
|
241 static void set_numa_set_bind_policy(numa_set_bind_policy_func_t func) { _numa_set_bind_policy = func; } |
462
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
242 static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; } |
3826 | 243 static int sched_getcpu_syscall(void); |
141 | 244 public: |
245 static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; } | |
246 static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) { | |
247 return _numa_node_to_cpus != NULL ? _numa_node_to_cpus(node, buffer, bufferlen) : -1; | |
248 } | |
249 static int numa_max_node() { return _numa_max_node != NULL ? _numa_max_node() : -1; } | |
250 static int numa_available() { return _numa_available != NULL ? _numa_available() : -1; } | |
251 static int numa_tonode_memory(void *start, size_t size, int node) { | |
252 return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1; | |
253 } | |
462
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
254 static void numa_interleave_memory(void *start, size_t size) { |
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
255 if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) { |
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
256 _numa_interleave_memory(start, size, _numa_all_nodes); |
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
257 } |
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
258 } |
12176
88c255656030
8016155: SIGBUS when running Kitchensink with ParallelScavenge and ParallelOld
mgerdin
parents:
10969
diff
changeset
|
259 static void numa_set_bind_policy(int policy) { |
88c255656030
8016155: SIGBUS when running Kitchensink with ParallelScavenge and ParallelOld
mgerdin
parents:
10969
diff
changeset
|
260 if (_numa_set_bind_policy != NULL) { |
88c255656030
8016155: SIGBUS when running Kitchensink with ParallelScavenge and ParallelOld
mgerdin
parents:
10969
diff
changeset
|
261 _numa_set_bind_policy(policy); |
88c255656030
8016155: SIGBUS when running Kitchensink with ParallelScavenge and ParallelOld
mgerdin
parents:
10969
diff
changeset
|
262 } |
88c255656030
8016155: SIGBUS when running Kitchensink with ParallelScavenge and ParallelOld
mgerdin
parents:
10969
diff
changeset
|
263 } |
141 | 264 static int get_node_by_cpu(int cpu_id); |
0 | 265 }; |
266 | |
267 | |
6197 | 268 class PlatformEvent : public CHeapObj<mtInternal> { |
0 | 269 private: |
270 double CachePad [4] ; // increase odds that _mutex is sole occupant of cache line | |
271 volatile int _Event ; | |
272 volatile int _nParked ; | |
273 pthread_mutex_t _mutex [1] ; | |
274 pthread_cond_t _cond [1] ; | |
275 double PostPad [2] ; | |
276 Thread * _Assoc ; | |
277 | |
278 public: // TODO-FIXME: make dtor private | |
279 ~PlatformEvent() { guarantee (0, "invariant") ; } | |
280 | |
281 public: | |
282 PlatformEvent() { | |
283 int status; | |
284 status = pthread_cond_init (_cond, NULL); | |
285 assert_status(status == 0, status, "cond_init"); | |
286 status = pthread_mutex_init (_mutex, NULL); | |
287 assert_status(status == 0, status, "mutex_init"); | |
288 _Event = 0 ; | |
289 _nParked = 0 ; | |
290 _Assoc = NULL ; | |
291 } | |
292 | |
293 // Use caution with reset() and fired() -- they may require MEMBARs | |
294 void reset() { _Event = 0 ; } | |
295 int fired() { return _Event; } | |
296 void park () ; | |
297 void unpark () ; | |
298 int TryPark () ; | |
299 int park (jlong millis) ; | |
300 void SetAssociation (Thread * a) { _Assoc = a ; } | |
301 } ; | |
302 | |
6197 | 303 class PlatformParker : public CHeapObj<mtInternal> { |
0 | 304 protected: |
305 pthread_mutex_t _mutex [1] ; | |
306 pthread_cond_t _cond [1] ; | |
307 | |
308 public: // TODO-FIXME: make dtor private | |
309 ~PlatformParker() { guarantee (0, "invariant") ; } | |
310 | |
311 public: | |
312 PlatformParker() { | |
313 int status; | |
314 status = pthread_cond_init (_cond, NULL); | |
315 assert_status(status == 0, status, "cond_init"); | |
316 status = pthread_mutex_init (_mutex, NULL); | |
317 assert_status(status == 0, status, "mutex_init"); | |
318 } | |
10405 | 319 }; |
1972 | 320 |
321 #endif // OS_LINUX_VM_OS_LINUX_HPP |