Mercurial > hg > truffle
annotate src/os/linux/vm/os_linux.hpp @ 4582:b24386206122
Made all vm builds go into subdirectories, even product builds to simplify building the various types of VMs (server, client and graal).
Made HotSpot build jobs use the number of CPUs on the host machine.
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 13 Feb 2012 23:13:37 +0100 |
parents | 7c2653aefc46 |
children | 7432b9db36ff |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 1999, 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:
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; | |
73 | |
74 static julong available_memory(); | |
75 static julong physical_memory() { return _physical_memory; } | |
76 static void initialize_system_info(); | |
77 | |
199
f139919897d2
6681796: hotspot build failure on gcc 4.2.x (ubuntu 8.04) w/ openjdk 6
xlu
parents:
141
diff
changeset
|
78 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
|
79 static void set_libpthread_version(const char *s) { _libpthread_version = s; } |
0 | 80 |
81 static bool supports_variable_stack_size(); | |
82 | |
83 static void set_is_NPTL() { _is_NPTL = true; } | |
84 static void set_is_LinuxThreads() { _is_NPTL = false; } | |
85 static void set_is_floating_stack() { _is_floating_stack = true; } | |
86 | |
141 | 87 static void rebuild_cpu_to_node_map(); |
88 static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; } | |
3286
139667d9836a
7034464: Support transparent large pages on Linux
iveresov
parents:
1972
diff
changeset
|
89 |
139667d9836a
7034464: Support transparent large pages on Linux
iveresov
parents:
1972
diff
changeset
|
90 static bool hugetlbfs_sanity_check(bool warn, size_t page_size); |
139667d9836a
7034464: Support transparent large pages on Linux
iveresov
parents:
1972
diff
changeset
|
91 |
0 | 92 public: |
93 static void init_thread_fpu_state(); | |
94 static int get_fpu_control_word(); | |
95 static void set_fpu_control_word(int fpu_control); | |
96 static pthread_t main_thread(void) { return _main_thread; } | |
97 // returns kernel thread id (similar to LWP id on Solaris), which can be | |
98 // used to access /proc | |
99 static pid_t gettid(); | |
100 static void set_createThread_lock(Mutex* lk) { _createThread_lock = lk; } | |
101 static Mutex* createThread_lock(void) { return _createThread_lock; } | |
102 static void hotspot_sigmask(Thread* thread); | |
103 | |
104 static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; } | |
105 static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; } | |
106 static bool is_initial_thread(void); | |
107 | |
108 static int page_size(void) { return _page_size; } | |
109 static void set_page_size(int val) { _page_size = val; } | |
110 | |
111 static address ucontext_get_pc(ucontext_t* uc); | |
112 static intptr_t* ucontext_get_sp(ucontext_t* uc); | |
113 static intptr_t* ucontext_get_fp(ucontext_t* uc); | |
114 | |
115 // For Analyzer Forte AsyncGetCallTrace profiling support: | |
116 // | |
117 // This interface should be declared in os_linux_i486.hpp, but | |
118 // that file provides extensions to the os class and not the | |
119 // Linux class. | |
120 static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc, | |
121 intptr_t** ret_sp, intptr_t** ret_fp); | |
122 | |
123 // This boolean allows users to forward their own non-matching signals | |
124 // to JVM_handle_linux_signal, harmlessly. | |
125 static bool signal_handlers_are_installed; | |
126 | |
127 static int get_our_sigflags(int); | |
128 static void set_our_sigflags(int, int); | |
129 static void signal_sets_init(); | |
130 static void install_signal_handlers(); | |
131 static void set_signal_handler(int, bool); | |
132 static bool is_sig_ignored(int sig); | |
133 | |
134 static sigset_t* unblocked_signals(); | |
135 static sigset_t* vm_signals(); | |
136 static sigset_t* allowdebug_blocked_signals(); | |
137 | |
138 // For signal-chaining | |
139 static struct sigaction *get_chained_signal_action(int sig); | |
140 static bool chained_handler(int sig, siginfo_t* siginfo, void* context); | |
141 | |
142 // 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
|
143 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
|
144 static const char *libpthread_version() { return _libpthread_version; } |
0 | 145 |
146 // NPTL or LinuxThreads? | |
147 static bool is_LinuxThreads() { return !_is_NPTL; } | |
148 static bool is_NPTL() { return _is_NPTL; } | |
149 | |
150 // NPTL is always floating stack. LinuxThreads could be using floating | |
151 // stack or fixed stack. | |
152 static bool is_floating_stack() { return _is_floating_stack; } | |
153 | |
154 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
|
155 static bool libnuma_init(); |
763
cf71f149d7ae
6840196: NUMA allocator: crash in fastdebug during startup on Linux
iveresov
parents:
462
diff
changeset
|
156 static void* libnuma_dlsym(void* handle, const char* name); |
0 | 157 // Minimum stack size a thread can be created with (allowing |
158 // the VM to completely create the thread and enter user code) | |
159 static size_t min_stack_allowed; | |
160 | |
161 // Return default stack size or guard size for the specified thread type | |
162 static size_t default_stack_size(os::ThreadType thr_type); | |
163 static size_t default_guard_size(os::ThreadType thr_type); | |
164 | |
165 static void capture_initial_stack(size_t max_size); | |
166 | |
167 // Stack overflow handling | |
168 static bool manually_expand_stack(JavaThread * t, address addr); | |
169 static int max_register_window_saves_before_flushing(); | |
170 | |
171 // Real-time clock functions | |
172 static void clock_init(void); | |
173 | |
174 // fast POSIX clocks support | |
175 static void fast_thread_clock_init(void); | |
176 | |
177 static bool supports_monotonic_clock() { | |
178 return _clock_gettime != NULL; | |
179 } | |
180 | |
181 static int clock_gettime(clockid_t clock_id, struct timespec *tp) { | |
182 return _clock_gettime ? _clock_gettime(clock_id, tp) : -1; | |
183 } | |
184 | |
185 static int pthread_getcpuclockid(pthread_t tid, clockid_t *clock_id) { | |
186 return _pthread_getcpuclockid ? _pthread_getcpuclockid(tid, clock_id) : -1; | |
187 } | |
188 | |
189 static bool supports_fast_thread_cpu_time() { | |
190 return _supports_fast_thread_cpu_time; | |
191 } | |
192 | |
193 static jlong fast_thread_cpu_time(clockid_t clockid); | |
194 | |
195 // Stack repair handling | |
196 | |
197 // none present | |
198 | |
199 // LinuxThreads work-around for 6292965 | |
200 static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime); | |
201 | |
202 | |
203 // Linux suspend/resume support - this helper is a shadow of its former | |
204 // self now that low-level suspension is barely used, and old workarounds | |
205 // for LinuxThreads are no longer needed. | |
206 class SuspendResume { | |
207 private: | |
208 volatile int _suspend_action; | |
209 // values for suspend_action: | |
210 #define SR_NONE (0x00) | |
211 #define SR_SUSPEND (0x01) // suspend request | |
212 #define SR_CONTINUE (0x02) // resume request | |
213 | |
214 volatile jint _state; | |
215 // values for _state: + SR_NONE | |
216 #define SR_SUSPENDED (0x20) | |
217 public: | |
218 SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; } | |
219 | |
220 int suspend_action() const { return _suspend_action; } | |
221 void set_suspend_action(int x) { _suspend_action = x; } | |
222 | |
223 // atomic updates for _state | |
224 void set_suspended() { | |
225 jint temp, temp2; | |
226 do { | |
227 temp = _state; | |
228 temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp); | |
229 } while (temp2 != temp); | |
230 } | |
231 void clear_suspended() { | |
232 jint temp, temp2; | |
233 do { | |
234 temp = _state; | |
235 temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp); | |
236 } while (temp2 != temp); | |
237 } | |
238 bool is_suspended() { return _state & SR_SUSPENDED; } | |
239 | |
240 #undef SR_SUSPENDED | |
241 }; | |
141 | 242 |
243 private: | |
244 typedef int (*sched_getcpu_func_t)(void); | |
245 typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen); | |
246 typedef int (*numa_max_node_func_t)(void); | |
247 typedef int (*numa_available_func_t)(void); | |
248 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
|
249 typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask); |
141 | 250 |
251 static sched_getcpu_func_t _sched_getcpu; | |
252 static numa_node_to_cpus_func_t _numa_node_to_cpus; | |
253 static numa_max_node_func_t _numa_max_node; | |
254 static numa_available_func_t _numa_available; | |
255 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
|
256 static numa_interleave_memory_func_t _numa_interleave_memory; |
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
257 static unsigned long* _numa_all_nodes; |
141 | 258 |
259 static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; } | |
260 static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; } | |
261 static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; } | |
262 static void set_numa_available(numa_available_func_t func) { _numa_available = func; } | |
263 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
|
264 static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; } |
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
265 static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; } |
3826 | 266 static int sched_getcpu_syscall(void); |
141 | 267 public: |
268 static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; } | |
269 static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) { | |
270 return _numa_node_to_cpus != NULL ? _numa_node_to_cpus(node, buffer, bufferlen) : -1; | |
271 } | |
272 static int numa_max_node() { return _numa_max_node != NULL ? _numa_max_node() : -1; } | |
273 static int numa_available() { return _numa_available != NULL ? _numa_available() : -1; } | |
274 static int numa_tonode_memory(void *start, size_t size, int node) { | |
275 return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1; | |
276 } | |
462
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
277 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
|
278 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
|
279 _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
|
280 } |
85f1b9537f70
6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents:
235
diff
changeset
|
281 } |
141 | 282 static int get_node_by_cpu(int cpu_id); |
0 | 283 }; |
284 | |
285 | |
286 class PlatformEvent : public CHeapObj { | |
287 private: | |
288 double CachePad [4] ; // increase odds that _mutex is sole occupant of cache line | |
289 volatile int _Event ; | |
290 volatile int _nParked ; | |
291 pthread_mutex_t _mutex [1] ; | |
292 pthread_cond_t _cond [1] ; | |
293 double PostPad [2] ; | |
294 Thread * _Assoc ; | |
295 | |
296 public: // TODO-FIXME: make dtor private | |
297 ~PlatformEvent() { guarantee (0, "invariant") ; } | |
298 | |
299 public: | |
300 PlatformEvent() { | |
301 int status; | |
302 status = pthread_cond_init (_cond, NULL); | |
303 assert_status(status == 0, status, "cond_init"); | |
304 status = pthread_mutex_init (_mutex, NULL); | |
305 assert_status(status == 0, status, "mutex_init"); | |
306 _Event = 0 ; | |
307 _nParked = 0 ; | |
308 _Assoc = NULL ; | |
309 } | |
310 | |
311 // Use caution with reset() and fired() -- they may require MEMBARs | |
312 void reset() { _Event = 0 ; } | |
313 int fired() { return _Event; } | |
314 void park () ; | |
315 void unpark () ; | |
316 int TryPark () ; | |
317 int park (jlong millis) ; | |
318 void SetAssociation (Thread * a) { _Assoc = a ; } | |
319 } ; | |
320 | |
321 class PlatformParker : public CHeapObj { | |
322 protected: | |
323 pthread_mutex_t _mutex [1] ; | |
324 pthread_cond_t _cond [1] ; | |
325 | |
326 public: // TODO-FIXME: make dtor private | |
327 ~PlatformParker() { guarantee (0, "invariant") ; } | |
328 | |
329 public: | |
330 PlatformParker() { | |
331 int status; | |
332 status = pthread_cond_init (_cond, NULL); | |
333 assert_status(status == 0, status, "cond_init"); | |
334 status = pthread_mutex_init (_mutex, NULL); | |
335 assert_status(status == 0, status, "mutex_init"); | |
336 } | |
337 } ; | |
1972 | 338 |
339 #endif // OS_LINUX_VM_OS_LINUX_HPP |