Mercurial > hg > truffle
annotate src/share/vm/runtime/os.cpp @ 1145:e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking.
Reviewed-by: jmasa
author | ysr |
---|---|
date | Wed, 23 Dec 2009 09:23:54 -0800 |
parents | 956304450e80 |
children | 4ce7240d622c |
rev | line source |
---|---|
0 | 1 /* |
579 | 2 * Copyright 1997-2009 Sun Microsystems, Inc. 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 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_os.cpp.incl" | |
27 | |
28 # include <signal.h> | |
29 | |
30 OSThread* os::_starting_thread = NULL; | |
31 address os::_polling_page = NULL; | |
32 volatile int32_t* os::_mem_serialize_page = NULL; | |
33 uintptr_t os::_serialize_page_mask = 0; | |
34 long os::_rand_seed = 1; | |
35 int os::_processor_count = 0; | |
36 size_t os::_page_sizes[os::page_sizes_max]; | |
37 | |
38 #ifndef PRODUCT | |
39 int os::num_mallocs = 0; // # of calls to malloc/realloc | |
40 size_t os::alloc_bytes = 0; // # of bytes allocated | |
41 int os::num_frees = 0; // # of calls to free | |
42 #endif | |
43 | |
44 // Fill in buffer with current local time as an ISO-8601 string. | |
45 // E.g., yyyy-mm-ddThh:mm:ss-zzzz. | |
46 // Returns buffer, or NULL if it failed. | |
47 // This would mostly be a call to | |
48 // strftime(...., "%Y-%m-%d" "T" "%H:%M:%S" "%z", ....) | |
49 // except that on Windows the %z behaves badly, so we do it ourselves. | |
50 // Also, people wanted milliseconds on there, | |
51 // and strftime doesn't do milliseconds. | |
52 char* os::iso8601_time(char* buffer, size_t buffer_length) { | |
53 // Output will be of the form "YYYY-MM-DDThh:mm:ss.mmm+zzzz\0" | |
54 // 1 2 | |
55 // 12345678901234567890123456789 | |
56 static const char* iso8601_format = | |
57 "%04d-%02d-%02dT%02d:%02d:%02d.%03d%c%02d%02d"; | |
58 static const size_t needed_buffer = 29; | |
59 | |
60 // Sanity check the arguments | |
61 if (buffer == NULL) { | |
62 assert(false, "NULL buffer"); | |
63 return NULL; | |
64 } | |
65 if (buffer_length < needed_buffer) { | |
66 assert(false, "buffer_length too small"); | |
67 return NULL; | |
68 } | |
69 // Get the current time | |
61 | 70 jlong milliseconds_since_19700101 = javaTimeMillis(); |
0 | 71 const int milliseconds_per_microsecond = 1000; |
72 const time_t seconds_since_19700101 = | |
73 milliseconds_since_19700101 / milliseconds_per_microsecond; | |
74 const int milliseconds_after_second = | |
75 milliseconds_since_19700101 % milliseconds_per_microsecond; | |
76 // Convert the time value to a tm and timezone variable | |
548
773234c55e8c
6800586: -XX:+PrintGCDateStamps is using mt-unsafe localtime function
ysr
parents:
477
diff
changeset
|
77 struct tm time_struct; |
773234c55e8c
6800586: -XX:+PrintGCDateStamps is using mt-unsafe localtime function
ysr
parents:
477
diff
changeset
|
78 if (localtime_pd(&seconds_since_19700101, &time_struct) == NULL) { |
773234c55e8c
6800586: -XX:+PrintGCDateStamps is using mt-unsafe localtime function
ysr
parents:
477
diff
changeset
|
79 assert(false, "Failed localtime_pd"); |
0 | 80 return NULL; |
81 } | |
82 const time_t zone = timezone; | |
83 | |
84 // If daylight savings time is in effect, | |
85 // we are 1 hour East of our time zone | |
86 const time_t seconds_per_minute = 60; | |
87 const time_t minutes_per_hour = 60; | |
88 const time_t seconds_per_hour = seconds_per_minute * minutes_per_hour; | |
89 time_t UTC_to_local = zone; | |
90 if (time_struct.tm_isdst > 0) { | |
91 UTC_to_local = UTC_to_local - seconds_per_hour; | |
92 } | |
93 // Compute the time zone offset. | |
548
773234c55e8c
6800586: -XX:+PrintGCDateStamps is using mt-unsafe localtime function
ysr
parents:
477
diff
changeset
|
94 // localtime_pd() sets timezone to the difference (in seconds) |
0 | 95 // between UTC and and local time. |
96 // ISO 8601 says we need the difference between local time and UTC, | |
548
773234c55e8c
6800586: -XX:+PrintGCDateStamps is using mt-unsafe localtime function
ysr
parents:
477
diff
changeset
|
97 // we change the sign of the localtime_pd() result. |
0 | 98 const time_t local_to_UTC = -(UTC_to_local); |
99 // Then we have to figure out if if we are ahead (+) or behind (-) UTC. | |
100 char sign_local_to_UTC = '+'; | |
101 time_t abs_local_to_UTC = local_to_UTC; | |
102 if (local_to_UTC < 0) { | |
103 sign_local_to_UTC = '-'; | |
104 abs_local_to_UTC = -(abs_local_to_UTC); | |
105 } | |
106 // Convert time zone offset seconds to hours and minutes. | |
107 const time_t zone_hours = (abs_local_to_UTC / seconds_per_hour); | |
108 const time_t zone_min = | |
109 ((abs_local_to_UTC % seconds_per_hour) / seconds_per_minute); | |
110 | |
111 // Print an ISO 8601 date and time stamp into the buffer | |
112 const int year = 1900 + time_struct.tm_year; | |
113 const int month = 1 + time_struct.tm_mon; | |
114 const int printed = jio_snprintf(buffer, buffer_length, iso8601_format, | |
115 year, | |
116 month, | |
117 time_struct.tm_mday, | |
118 time_struct.tm_hour, | |
119 time_struct.tm_min, | |
120 time_struct.tm_sec, | |
121 milliseconds_after_second, | |
122 sign_local_to_UTC, | |
123 zone_hours, | |
124 zone_min); | |
125 if (printed == 0) { | |
126 assert(false, "Failed jio_printf"); | |
127 return NULL; | |
128 } | |
129 return buffer; | |
130 } | |
131 | |
132 OSReturn os::set_priority(Thread* thread, ThreadPriority p) { | |
133 #ifdef ASSERT | |
134 if (!(!thread->is_Java_thread() || | |
135 Thread::current() == thread || | |
136 Threads_lock->owned_by_self() | |
137 || thread->is_Compiler_thread() | |
138 )) { | |
139 assert(false, "possibility of dangling Thread pointer"); | |
140 } | |
141 #endif | |
142 | |
143 if (p >= MinPriority && p <= MaxPriority) { | |
144 int priority = java_to_os_priority[p]; | |
145 return set_native_priority(thread, priority); | |
146 } else { | |
147 assert(false, "Should not happen"); | |
148 return OS_ERR; | |
149 } | |
150 } | |
151 | |
152 | |
153 OSReturn os::get_priority(const Thread* const thread, ThreadPriority& priority) { | |
154 int p; | |
155 int os_prio; | |
156 OSReturn ret = get_native_priority(thread, &os_prio); | |
157 if (ret != OS_OK) return ret; | |
158 | |
159 for (p = MaxPriority; p > MinPriority && java_to_os_priority[p] > os_prio; p--) ; | |
160 priority = (ThreadPriority)p; | |
161 return OS_OK; | |
162 } | |
163 | |
164 | |
165 // --------------------- sun.misc.Signal (optional) --------------------- | |
166 | |
167 | |
168 // SIGBREAK is sent by the keyboard to query the VM state | |
169 #ifndef SIGBREAK | |
170 #define SIGBREAK SIGQUIT | |
171 #endif | |
172 | |
173 // sigexitnum_pd is a platform-specific special signal used for terminating the Signal thread. | |
174 | |
175 | |
176 static void signal_thread_entry(JavaThread* thread, TRAPS) { | |
177 os::set_priority(thread, NearMaxPriority); | |
178 while (true) { | |
179 int sig; | |
180 { | |
181 // FIXME : Currently we have not decieded what should be the status | |
182 // for this java thread blocked here. Once we decide about | |
183 // that we should fix this. | |
184 sig = os::signal_wait(); | |
185 } | |
186 if (sig == os::sigexitnum_pd()) { | |
187 // Terminate the signal thread | |
188 return; | |
189 } | |
190 | |
191 switch (sig) { | |
192 case SIGBREAK: { | |
193 // Check if the signal is a trigger to start the Attach Listener - in that | |
194 // case don't print stack traces. | |
195 if (!DisableAttachMechanism && AttachListener::is_init_trigger()) { | |
196 continue; | |
197 } | |
198 // Print stack traces | |
199 // Any SIGBREAK operations added here should make sure to flush | |
200 // the output stream (e.g. tty->flush()) after output. See 4803766. | |
201 // Each module also prints an extra carriage return after its output. | |
202 VM_PrintThreads op; | |
203 VMThread::execute(&op); | |
204 VM_PrintJNI jni_op; | |
205 VMThread::execute(&jni_op); | |
206 VM_FindDeadlocks op1(tty); | |
207 VMThread::execute(&op1); | |
208 Universe::print_heap_at_SIGBREAK(); | |
209 if (PrintClassHistogram) { | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
548
diff
changeset
|
210 VM_GC_HeapInspection op1(gclog_or_tty, true /* force full GC before heap inspection */, |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
548
diff
changeset
|
211 true /* need_prologue */); |
0 | 212 VMThread::execute(&op1); |
213 } | |
214 if (JvmtiExport::should_post_data_dump()) { | |
215 JvmtiExport::post_data_dump(); | |
216 } | |
217 break; | |
218 } | |
219 default: { | |
220 // Dispatch the signal to java | |
221 HandleMark hm(THREAD); | |
222 klassOop k = SystemDictionary::resolve_or_null(vmSymbolHandles::sun_misc_Signal(), THREAD); | |
223 KlassHandle klass (THREAD, k); | |
224 if (klass.not_null()) { | |
225 JavaValue result(T_VOID); | |
226 JavaCallArguments args; | |
227 args.push_int(sig); | |
228 JavaCalls::call_static( | |
229 &result, | |
230 klass, | |
231 vmSymbolHandles::dispatch_name(), | |
232 vmSymbolHandles::int_void_signature(), | |
233 &args, | |
234 THREAD | |
235 ); | |
236 } | |
237 if (HAS_PENDING_EXCEPTION) { | |
238 // tty is initialized early so we don't expect it to be null, but | |
239 // if it is we can't risk doing an initialization that might | |
240 // trigger additional out-of-memory conditions | |
241 if (tty != NULL) { | |
242 char klass_name[256]; | |
243 char tmp_sig_name[16]; | |
244 const char* sig_name = "UNKNOWN"; | |
245 instanceKlass::cast(PENDING_EXCEPTION->klass())-> | |
246 name()->as_klass_external_name(klass_name, 256); | |
247 if (os::exception_name(sig, tmp_sig_name, 16) != NULL) | |
248 sig_name = tmp_sig_name; | |
249 warning("Exception %s occurred dispatching signal %s to handler" | |
250 "- the VM may need to be forcibly terminated", | |
251 klass_name, sig_name ); | |
252 } | |
253 CLEAR_PENDING_EXCEPTION; | |
254 } | |
255 } | |
256 } | |
257 } | |
258 } | |
259 | |
260 | |
261 void os::signal_init() { | |
262 if (!ReduceSignalUsage) { | |
263 // Setup JavaThread for processing signals | |
264 EXCEPTION_MARK; | |
265 klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(), true, CHECK); | |
266 instanceKlassHandle klass (THREAD, k); | |
267 instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); | |
268 | |
269 const char thread_name[] = "Signal Dispatcher"; | |
270 Handle string = java_lang_String::create_from_str(thread_name, CHECK); | |
271 | |
272 // Initialize thread_oop to put it into the system threadGroup | |
273 Handle thread_group (THREAD, Universe::system_thread_group()); | |
274 JavaValue result(T_VOID); | |
275 JavaCalls::call_special(&result, thread_oop, | |
276 klass, | |
277 vmSymbolHandles::object_initializer_name(), | |
278 vmSymbolHandles::threadgroup_string_void_signature(), | |
279 thread_group, | |
280 string, | |
281 CHECK); | |
282 | |
283 KlassHandle group(THREAD, SystemDictionary::threadGroup_klass()); | |
284 JavaCalls::call_special(&result, | |
285 thread_group, | |
286 group, | |
287 vmSymbolHandles::add_method_name(), | |
288 vmSymbolHandles::thread_void_signature(), | |
289 thread_oop, // ARG 1 | |
290 CHECK); | |
291 | |
292 os::signal_init_pd(); | |
293 | |
294 { MutexLocker mu(Threads_lock); | |
295 JavaThread* signal_thread = new JavaThread(&signal_thread_entry); | |
296 | |
297 // At this point it may be possible that no osthread was created for the | |
298 // JavaThread due to lack of memory. We would have to throw an exception | |
299 // in that case. However, since this must work and we do not allow | |
300 // exceptions anyway, check and abort if this fails. | |
301 if (signal_thread == NULL || signal_thread->osthread() == NULL) { | |
302 vm_exit_during_initialization("java.lang.OutOfMemoryError", | |
303 "unable to create new native thread"); | |
304 } | |
305 | |
306 java_lang_Thread::set_thread(thread_oop(), signal_thread); | |
307 java_lang_Thread::set_priority(thread_oop(), NearMaxPriority); | |
308 java_lang_Thread::set_daemon(thread_oop()); | |
309 | |
310 signal_thread->set_threadObj(thread_oop()); | |
311 Threads::add(signal_thread); | |
312 Thread::start(signal_thread); | |
313 } | |
314 // Handle ^BREAK | |
315 os::signal(SIGBREAK, os::user_handler()); | |
316 } | |
317 } | |
318 | |
319 | |
320 void os::terminate_signal_thread() { | |
321 if (!ReduceSignalUsage) | |
322 signal_notify(sigexitnum_pd()); | |
323 } | |
324 | |
325 | |
326 // --------------------- loading libraries --------------------- | |
327 | |
328 typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *); | |
329 extern struct JavaVM_ main_vm; | |
330 | |
331 static void* _native_java_library = NULL; | |
332 | |
333 void* os::native_java_library() { | |
334 if (_native_java_library == NULL) { | |
335 char buffer[JVM_MAXPATHLEN]; | |
336 char ebuf[1024]; | |
337 | |
242 | 338 // Try to load verify dll first. In 1.3 java dll depends on it and is not |
339 // always able to find it when the loading executable is outside the JDK. | |
0 | 340 // In order to keep working with 1.2 we ignore any loading errors. |
242 | 341 dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "verify"); |
342 dll_load(buffer, ebuf, sizeof(ebuf)); | |
0 | 343 |
344 // Load java dll | |
242 | 345 dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "java"); |
346 _native_java_library = dll_load(buffer, ebuf, sizeof(ebuf)); | |
0 | 347 if (_native_java_library == NULL) { |
348 vm_exit_during_initialization("Unable to load native library", ebuf); | |
349 } | |
242 | 350 } |
351 static jboolean onLoaded = JNI_FALSE; | |
352 if (onLoaded) { | |
353 // We may have to wait to fire OnLoad until TLS is initialized. | |
354 if (ThreadLocalStorage::is_initialized()) { | |
355 // The JNI_OnLoad handling is normally done by method load in | |
356 // java.lang.ClassLoader$NativeLibrary, but the VM loads the base library | |
357 // explicitly so we have to check for JNI_OnLoad as well | |
358 const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS; | |
359 JNI_OnLoad_t JNI_OnLoad = CAST_TO_FN_PTR( | |
360 JNI_OnLoad_t, dll_lookup(_native_java_library, onLoadSymbols[0])); | |
361 if (JNI_OnLoad != NULL) { | |
362 JavaThread* thread = JavaThread::current(); | |
363 ThreadToNativeFromVM ttn(thread); | |
364 HandleMark hm(thread); | |
365 jint ver = (*JNI_OnLoad)(&main_vm, NULL); | |
366 onLoaded = JNI_TRUE; | |
367 if (!Threads::is_supported_jni_version_including_1_1(ver)) { | |
368 vm_exit_during_initialization("Unsupported JNI version"); | |
369 } | |
0 | 370 } |
371 } | |
372 } | |
373 return _native_java_library; | |
374 } | |
375 | |
376 // --------------------- heap allocation utilities --------------------- | |
377 | |
378 char *os::strdup(const char *str) { | |
379 size_t size = strlen(str); | |
380 char *dup_str = (char *)malloc(size + 1); | |
381 if (dup_str == NULL) return NULL; | |
382 strcpy(dup_str, str); | |
383 return dup_str; | |
384 } | |
385 | |
386 | |
387 | |
388 #ifdef ASSERT | |
389 #define space_before (MallocCushion + sizeof(double)) | |
390 #define space_after MallocCushion | |
391 #define size_addr_from_base(p) (size_t*)(p + space_before - sizeof(size_t)) | |
392 #define size_addr_from_obj(p) ((size_t*)p - 1) | |
393 // MallocCushion: size of extra cushion allocated around objects with +UseMallocOnly | |
394 // NB: cannot be debug variable, because these aren't set from the command line until | |
395 // *after* the first few allocs already happened | |
396 #define MallocCushion 16 | |
397 #else | |
398 #define space_before 0 | |
399 #define space_after 0 | |
400 #define size_addr_from_base(p) should not use w/o ASSERT | |
401 #define size_addr_from_obj(p) should not use w/o ASSERT | |
402 #define MallocCushion 0 | |
403 #endif | |
404 #define paranoid 0 /* only set to 1 if you suspect checking code has bug */ | |
405 | |
406 #ifdef ASSERT | |
407 inline size_t get_size(void* obj) { | |
408 size_t size = *size_addr_from_obj(obj); | |
409 if (size < 0 ) | |
410 fatal2("free: size field of object #%p was overwritten (%lu)", obj, size); | |
411 return size; | |
412 } | |
413 | |
414 u_char* find_cushion_backwards(u_char* start) { | |
415 u_char* p = start; | |
416 while (p[ 0] != badResourceValue || p[-1] != badResourceValue || | |
417 p[-2] != badResourceValue || p[-3] != badResourceValue) p--; | |
418 // ok, we have four consecutive marker bytes; find start | |
419 u_char* q = p - 4; | |
420 while (*q == badResourceValue) q--; | |
421 return q + 1; | |
422 } | |
423 | |
424 u_char* find_cushion_forwards(u_char* start) { | |
425 u_char* p = start; | |
426 while (p[0] != badResourceValue || p[1] != badResourceValue || | |
427 p[2] != badResourceValue || p[3] != badResourceValue) p++; | |
428 // ok, we have four consecutive marker bytes; find end of cushion | |
429 u_char* q = p + 4; | |
430 while (*q == badResourceValue) q++; | |
431 return q - MallocCushion; | |
432 } | |
433 | |
434 void print_neighbor_blocks(void* ptr) { | |
435 // find block allocated before ptr (not entirely crash-proof) | |
436 if (MallocCushion < 4) { | |
437 tty->print_cr("### cannot find previous block (MallocCushion < 4)"); | |
438 return; | |
439 } | |
440 u_char* start_of_this_block = (u_char*)ptr - space_before; | |
441 u_char* end_of_prev_block_data = start_of_this_block - space_after -1; | |
442 // look for cushion in front of prev. block | |
443 u_char* start_of_prev_block = find_cushion_backwards(end_of_prev_block_data); | |
444 ptrdiff_t size = *size_addr_from_base(start_of_prev_block); | |
445 u_char* obj = start_of_prev_block + space_before; | |
446 if (size <= 0 ) { | |
447 // start is bad; mayhave been confused by OS data inbetween objects | |
448 // search one more backwards | |
449 start_of_prev_block = find_cushion_backwards(start_of_prev_block); | |
450 size = *size_addr_from_base(start_of_prev_block); | |
451 obj = start_of_prev_block + space_before; | |
452 } | |
453 | |
454 if (start_of_prev_block + space_before + size + space_after == start_of_this_block) { | |
455 tty->print_cr("### previous object: %p (%ld bytes)", obj, size); | |
456 } else { | |
457 tty->print_cr("### previous object (not sure if correct): %p (%ld bytes)", obj, size); | |
458 } | |
459 | |
460 // now find successor block | |
461 u_char* start_of_next_block = (u_char*)ptr + *size_addr_from_obj(ptr) + space_after; | |
462 start_of_next_block = find_cushion_forwards(start_of_next_block); | |
463 u_char* next_obj = start_of_next_block + space_before; | |
464 ptrdiff_t next_size = *size_addr_from_base(start_of_next_block); | |
465 if (start_of_next_block[0] == badResourceValue && | |
466 start_of_next_block[1] == badResourceValue && | |
467 start_of_next_block[2] == badResourceValue && | |
468 start_of_next_block[3] == badResourceValue) { | |
469 tty->print_cr("### next object: %p (%ld bytes)", next_obj, next_size); | |
470 } else { | |
471 tty->print_cr("### next object (not sure if correct): %p (%ld bytes)", next_obj, next_size); | |
472 } | |
473 } | |
474 | |
475 | |
476 void report_heap_error(void* memblock, void* bad, const char* where) { | |
477 tty->print_cr("## nof_mallocs = %d, nof_frees = %d", os::num_mallocs, os::num_frees); | |
478 tty->print_cr("## memory stomp: byte at %p %s object %p", bad, where, memblock); | |
479 print_neighbor_blocks(memblock); | |
480 fatal("memory stomping error"); | |
481 } | |
482 | |
483 void verify_block(void* memblock) { | |
484 size_t size = get_size(memblock); | |
485 if (MallocCushion) { | |
486 u_char* ptr = (u_char*)memblock - space_before; | |
487 for (int i = 0; i < MallocCushion; i++) { | |
488 if (ptr[i] != badResourceValue) { | |
489 report_heap_error(memblock, ptr+i, "in front of"); | |
490 } | |
491 } | |
492 u_char* end = (u_char*)memblock + size + space_after; | |
493 for (int j = -MallocCushion; j < 0; j++) { | |
494 if (end[j] != badResourceValue) { | |
495 report_heap_error(memblock, end+j, "after"); | |
496 } | |
497 } | |
498 } | |
499 } | |
500 #endif | |
501 | |
502 void* os::malloc(size_t size) { | |
503 NOT_PRODUCT(num_mallocs++); | |
504 NOT_PRODUCT(alloc_bytes += size); | |
505 | |
506 if (size == 0) { | |
507 // return a valid pointer if size is zero | |
508 // if NULL is returned the calling functions assume out of memory. | |
509 size = 1; | |
510 } | |
511 | |
512 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); | |
513 u_char* ptr = (u_char*)::malloc(size + space_before + space_after); | |
514 #ifdef ASSERT | |
515 if (ptr == NULL) return NULL; | |
516 if (MallocCushion) { | |
517 for (u_char* p = ptr; p < ptr + MallocCushion; p++) *p = (u_char)badResourceValue; | |
518 u_char* end = ptr + space_before + size; | |
519 for (u_char* pq = ptr+MallocCushion; pq < end; pq++) *pq = (u_char)uninitBlockPad; | |
520 for (u_char* q = end; q < end + MallocCushion; q++) *q = (u_char)badResourceValue; | |
521 } | |
522 // put size just before data | |
523 *size_addr_from_base(ptr) = size; | |
524 #endif | |
525 u_char* memblock = ptr + space_before; | |
526 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { | |
527 tty->print_cr("os::malloc caught, %lu bytes --> %p", size, memblock); | |
528 breakpoint(); | |
529 } | |
530 debug_only(if (paranoid) verify_block(memblock)); | |
531 if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc %lu bytes --> %p", size, memblock); | |
532 return memblock; | |
533 } | |
534 | |
535 | |
536 void* os::realloc(void *memblock, size_t size) { | |
537 NOT_PRODUCT(num_mallocs++); | |
538 NOT_PRODUCT(alloc_bytes += size); | |
539 #ifndef ASSERT | |
540 return ::realloc(memblock, size); | |
541 #else | |
542 if (memblock == NULL) { | |
543 return os::malloc(size); | |
544 } | |
545 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { | |
546 tty->print_cr("os::realloc caught %p", memblock); | |
547 breakpoint(); | |
548 } | |
549 verify_block(memblock); | |
550 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); | |
551 if (size == 0) return NULL; | |
552 // always move the block | |
553 void* ptr = malloc(size); | |
554 if (PrintMalloc) tty->print_cr("os::remalloc %lu bytes, %p --> %p", size, memblock, ptr); | |
555 // Copy to new memory if malloc didn't fail | |
556 if ( ptr != NULL ) { | |
557 memcpy(ptr, memblock, MIN2(size, get_size(memblock))); | |
558 if (paranoid) verify_block(ptr); | |
559 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { | |
560 tty->print_cr("os::realloc caught, %lu bytes --> %p", size, ptr); | |
561 breakpoint(); | |
562 } | |
563 free(memblock); | |
564 } | |
565 return ptr; | |
566 #endif | |
567 } | |
568 | |
569 | |
570 void os::free(void *memblock) { | |
571 NOT_PRODUCT(num_frees++); | |
572 #ifdef ASSERT | |
573 if (memblock == NULL) return; | |
574 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { | |
575 if (tty != NULL) tty->print_cr("os::free caught %p", memblock); | |
576 breakpoint(); | |
577 } | |
578 verify_block(memblock); | |
579 if (PrintMalloc && tty != NULL) | |
580 // tty->print_cr("os::free %p", memblock); | |
581 fprintf(stderr, "os::free %p\n", memblock); | |
582 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); | |
583 // Added by detlefs. | |
584 if (MallocCushion) { | |
585 u_char* ptr = (u_char*)memblock - space_before; | |
586 for (u_char* p = ptr; p < ptr + MallocCushion; p++) { | |
587 guarantee(*p == badResourceValue, | |
588 "Thing freed should be malloc result."); | |
589 *p = (u_char)freeBlockPad; | |
590 } | |
591 size_t size = get_size(memblock); | |
592 u_char* end = ptr + space_before + size; | |
593 for (u_char* q = end; q < end + MallocCushion; q++) { | |
594 guarantee(*q == badResourceValue, | |
595 "Thing freed should be malloc result."); | |
596 *q = (u_char)freeBlockPad; | |
597 } | |
598 } | |
599 #endif | |
600 ::free((char*)memblock - space_before); | |
601 } | |
602 | |
603 void os::init_random(long initval) { | |
604 _rand_seed = initval; | |
605 } | |
606 | |
607 | |
608 long os::random() { | |
609 /* standard, well-known linear congruential random generator with | |
610 * next_rand = (16807*seed) mod (2**31-1) | |
611 * see | |
612 * (1) "Random Number Generators: Good Ones Are Hard to Find", | |
613 * S.K. Park and K.W. Miller, Communications of the ACM 31:10 (Oct 1988), | |
614 * (2) "Two Fast Implementations of the 'Minimal Standard' Random | |
615 * Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), pp. 87-88. | |
616 */ | |
617 const long a = 16807; | |
618 const unsigned long m = 2147483647; | |
619 const long q = m / a; assert(q == 127773, "weird math"); | |
620 const long r = m % a; assert(r == 2836, "weird math"); | |
621 | |
622 // compute az=2^31p+q | |
623 unsigned long lo = a * (long)(_rand_seed & 0xFFFF); | |
624 unsigned long hi = a * (long)((unsigned long)_rand_seed >> 16); | |
625 lo += (hi & 0x7FFF) << 16; | |
626 | |
627 // if q overflowed, ignore the overflow and increment q | |
628 if (lo > m) { | |
629 lo &= m; | |
630 ++lo; | |
631 } | |
632 lo += hi >> 15; | |
633 | |
634 // if (p+q) overflowed, ignore the overflow and increment (p+q) | |
635 if (lo > m) { | |
636 lo &= m; | |
637 ++lo; | |
638 } | |
639 return (_rand_seed = lo); | |
640 } | |
641 | |
642 // The INITIALIZED state is distinguished from the SUSPENDED state because the | |
643 // conditions in which a thread is first started are different from those in which | |
644 // a suspension is resumed. These differences make it hard for us to apply the | |
645 // tougher checks when starting threads that we want to do when resuming them. | |
646 // However, when start_thread is called as a result of Thread.start, on a Java | |
647 // thread, the operation is synchronized on the Java Thread object. So there | |
648 // cannot be a race to start the thread and hence for the thread to exit while | |
649 // we are working on it. Non-Java threads that start Java threads either have | |
650 // to do so in a context in which races are impossible, or should do appropriate | |
651 // locking. | |
652 | |
653 void os::start_thread(Thread* thread) { | |
654 // guard suspend/resume | |
655 MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag); | |
656 OSThread* osthread = thread->osthread(); | |
657 osthread->set_state(RUNNABLE); | |
658 pd_start_thread(thread); | |
659 } | |
660 | |
661 //--------------------------------------------------------------------------- | |
662 // Helper functions for fatal error handler | |
663 | |
664 void os::print_hex_dump(outputStream* st, address start, address end, int unitsize) { | |
665 assert(unitsize == 1 || unitsize == 2 || unitsize == 4 || unitsize == 8, "just checking"); | |
666 | |
667 int cols = 0; | |
668 int cols_per_line = 0; | |
669 switch (unitsize) { | |
670 case 1: cols_per_line = 16; break; | |
671 case 2: cols_per_line = 8; break; | |
672 case 4: cols_per_line = 4; break; | |
673 case 8: cols_per_line = 2; break; | |
674 default: return; | |
675 } | |
676 | |
677 address p = start; | |
678 st->print(PTR_FORMAT ": ", start); | |
679 while (p < end) { | |
680 switch (unitsize) { | |
681 case 1: st->print("%02x", *(u1*)p); break; | |
682 case 2: st->print("%04x", *(u2*)p); break; | |
683 case 4: st->print("%08x", *(u4*)p); break; | |
684 case 8: st->print("%016" FORMAT64_MODIFIER "x", *(u8*)p); break; | |
685 } | |
686 p += unitsize; | |
687 cols++; | |
688 if (cols >= cols_per_line && p < end) { | |
689 cols = 0; | |
690 st->cr(); | |
691 st->print(PTR_FORMAT ": ", p); | |
692 } else { | |
693 st->print(" "); | |
694 } | |
695 } | |
696 st->cr(); | |
697 } | |
698 | |
699 void os::print_environment_variables(outputStream* st, const char** env_list, | |
700 char* buffer, int len) { | |
701 if (env_list) { | |
702 st->print_cr("Environment Variables:"); | |
703 | |
704 for (int i = 0; env_list[i] != NULL; i++) { | |
705 if (getenv(env_list[i], buffer, len)) { | |
706 st->print(env_list[i]); | |
707 st->print("="); | |
708 st->print_cr(buffer); | |
709 } | |
710 } | |
711 } | |
712 } | |
713 | |
714 void os::print_cpu_info(outputStream* st) { | |
715 // cpu | |
716 st->print("CPU:"); | |
717 st->print("total %d", os::processor_count()); | |
718 // It's not safe to query number of active processors after crash | |
719 // st->print("(active %d)", os::active_processor_count()); | |
720 st->print(" %s", VM_Version::cpu_features()); | |
721 st->cr(); | |
722 } | |
723 | |
724 void os::print_date_and_time(outputStream *st) { | |
725 time_t tloc; | |
726 (void)time(&tloc); | |
727 st->print("time: %s", ctime(&tloc)); // ctime adds newline. | |
728 | |
729 double t = os::elapsedTime(); | |
730 // NOTE: It tends to crash after a SEGV if we want to printf("%f",...) in | |
731 // Linux. Must be a bug in glibc ? Workaround is to round "t" to int | |
732 // before printf. We lost some precision, but who cares? | |
733 st->print_cr("elapsed time: %d seconds", (int)t); | |
734 } | |
735 | |
736 | |
737 // Looks like all platforms except IA64 can use the same function to check | |
738 // if C stack is walkable beyond current frame. The check for fp() is not | |
739 // necessary on Sparc, but it's harmless. | |
740 bool os::is_first_C_frame(frame* fr) { | |
741 #ifdef IA64 | |
742 // In order to walk native frames on Itanium, we need to access the unwind | |
743 // table, which is inside ELF. We don't want to parse ELF after fatal error, | |
744 // so return true for IA64. If we need to support C stack walking on IA64, | |
745 // this function needs to be moved to CPU specific files, as fp() on IA64 | |
746 // is register stack, which grows towards higher memory address. | |
747 return true; | |
748 #endif | |
749 | |
750 // Load up sp, fp, sender sp and sender fp, check for reasonable values. | |
751 // Check usp first, because if that's bad the other accessors may fault | |
752 // on some architectures. Ditto ufp second, etc. | |
753 uintptr_t fp_align_mask = (uintptr_t)(sizeof(address)-1); | |
754 // sp on amd can be 32 bit aligned. | |
755 uintptr_t sp_align_mask = (uintptr_t)(sizeof(int)-1); | |
756 | |
757 uintptr_t usp = (uintptr_t)fr->sp(); | |
758 if ((usp & sp_align_mask) != 0) return true; | |
759 | |
760 uintptr_t ufp = (uintptr_t)fr->fp(); | |
761 if ((ufp & fp_align_mask) != 0) return true; | |
762 | |
763 uintptr_t old_sp = (uintptr_t)fr->sender_sp(); | |
764 if ((old_sp & sp_align_mask) != 0) return true; | |
765 if (old_sp == 0 || old_sp == (uintptr_t)-1) return true; | |
766 | |
767 uintptr_t old_fp = (uintptr_t)fr->link(); | |
768 if ((old_fp & fp_align_mask) != 0) return true; | |
769 if (old_fp == 0 || old_fp == (uintptr_t)-1 || old_fp == ufp) return true; | |
770 | |
771 // stack grows downwards; if old_fp is below current fp or if the stack | |
772 // frame is too large, either the stack is corrupted or fp is not saved | |
773 // on stack (i.e. on x86, ebp may be used as general register). The stack | |
774 // is not walkable beyond current frame. | |
775 if (old_fp < ufp) return true; | |
776 if (old_fp - ufp > 64 * K) return true; | |
777 | |
778 return false; | |
779 } | |
780 | |
781 #ifdef ASSERT | |
782 extern "C" void test_random() { | |
783 const double m = 2147483647; | |
784 double mean = 0.0, variance = 0.0, t; | |
785 long reps = 10000; | |
786 unsigned long seed = 1; | |
787 | |
788 tty->print_cr("seed %ld for %ld repeats...", seed, reps); | |
789 os::init_random(seed); | |
790 long num; | |
791 for (int k = 0; k < reps; k++) { | |
792 num = os::random(); | |
793 double u = (double)num / m; | |
794 assert(u >= 0.0 && u <= 1.0, "bad random number!"); | |
795 | |
796 // calculate mean and variance of the random sequence | |
797 mean += u; | |
798 variance += (u*u); | |
799 } | |
800 mean /= reps; | |
801 variance /= (reps - 1); | |
802 | |
803 assert(num == 1043618065, "bad seed"); | |
804 tty->print_cr("mean of the 1st 10000 numbers: %f", mean); | |
805 tty->print_cr("variance of the 1st 10000 numbers: %f", variance); | |
806 const double eps = 0.0001; | |
807 t = fabsd(mean - 0.5018); | |
808 assert(t < eps, "bad mean"); | |
809 t = (variance - 0.3355) < 0.0 ? -(variance - 0.3355) : variance - 0.3355; | |
810 assert(t < eps, "bad variance"); | |
811 } | |
812 #endif | |
813 | |
814 | |
815 // Set up the boot classpath. | |
816 | |
817 char* os::format_boot_path(const char* format_string, | |
818 const char* home, | |
819 int home_len, | |
820 char fileSep, | |
821 char pathSep) { | |
822 assert((fileSep == '/' && pathSep == ':') || | |
823 (fileSep == '\\' && pathSep == ';'), "unexpected seperator chars"); | |
824 | |
825 // Scan the format string to determine the length of the actual | |
826 // boot classpath, and handle platform dependencies as well. | |
827 int formatted_path_len = 0; | |
828 const char* p; | |
829 for (p = format_string; *p != 0; ++p) { | |
830 if (*p == '%') formatted_path_len += home_len - 1; | |
831 ++formatted_path_len; | |
832 } | |
833 | |
834 char* formatted_path = NEW_C_HEAP_ARRAY(char, formatted_path_len + 1); | |
835 if (formatted_path == NULL) { | |
836 return NULL; | |
837 } | |
838 | |
839 // Create boot classpath from format, substituting separator chars and | |
840 // java home directory. | |
841 char* q = formatted_path; | |
842 for (p = format_string; *p != 0; ++p) { | |
843 switch (*p) { | |
844 case '%': | |
845 strcpy(q, home); | |
846 q += home_len; | |
847 break; | |
848 case '/': | |
849 *q++ = fileSep; | |
850 break; | |
851 case ':': | |
852 *q++ = pathSep; | |
853 break; | |
854 default: | |
855 *q++ = *p; | |
856 } | |
857 } | |
858 *q = '\0'; | |
859 | |
860 assert((q - formatted_path) == formatted_path_len, "formatted_path size botched"); | |
861 return formatted_path; | |
862 } | |
863 | |
864 | |
865 bool os::set_boot_path(char fileSep, char pathSep) { | |
866 const char* home = Arguments::get_java_home(); | |
867 int home_len = (int)strlen(home); | |
868 | |
869 static const char* meta_index_dir_format = "%/lib/"; | |
870 static const char* meta_index_format = "%/lib/meta-index"; | |
871 char* meta_index = format_boot_path(meta_index_format, home, home_len, fileSep, pathSep); | |
872 if (meta_index == NULL) return false; | |
873 char* meta_index_dir = format_boot_path(meta_index_dir_format, home, home_len, fileSep, pathSep); | |
874 if (meta_index_dir == NULL) return false; | |
875 Arguments::set_meta_index_path(meta_index, meta_index_dir); | |
876 | |
877 // Any modification to the JAR-file list, for the boot classpath must be | |
878 // aligned with install/install/make/common/Pack.gmk. Note: boot class | |
879 // path class JARs, are stripped for StackMapTable to reduce download size. | |
880 static const char classpath_format[] = | |
881 "%/lib/resources.jar:" | |
882 "%/lib/rt.jar:" | |
883 "%/lib/sunrsasign.jar:" | |
884 "%/lib/jsse.jar:" | |
885 "%/lib/jce.jar:" | |
886 "%/lib/charsets.jar:" | |
887 "%/classes"; | |
888 char* sysclasspath = format_boot_path(classpath_format, home, home_len, fileSep, pathSep); | |
889 if (sysclasspath == NULL) return false; | |
890 Arguments::set_sysclasspath(sysclasspath); | |
891 | |
892 return true; | |
893 } | |
894 | |
691 | 895 /* |
896 * Splits a path, based on its separator, the number of | |
897 * elements is returned back in n. | |
898 * It is the callers responsibility to: | |
899 * a> check the value of n, and n may be 0. | |
900 * b> ignore any empty path elements | |
901 * c> free up the data. | |
902 */ | |
903 char** os::split_path(const char* path, int* n) { | |
904 *n = 0; | |
905 if (path == NULL || strlen(path) == 0) { | |
906 return NULL; | |
907 } | |
908 const char psepchar = *os::path_separator(); | |
909 char* inpath = (char*)NEW_C_HEAP_ARRAY(char, strlen(path) + 1); | |
910 if (inpath == NULL) { | |
911 return NULL; | |
912 } | |
913 strncpy(inpath, path, strlen(path)); | |
914 int count = 1; | |
915 char* p = strchr(inpath, psepchar); | |
916 // Get a count of elements to allocate memory | |
917 while (p != NULL) { | |
918 count++; | |
919 p++; | |
920 p = strchr(p, psepchar); | |
921 } | |
922 char** opath = (char**) NEW_C_HEAP_ARRAY(char*, count); | |
923 if (opath == NULL) { | |
924 return NULL; | |
925 } | |
926 | |
927 // do the actual splitting | |
928 p = inpath; | |
929 for (int i = 0 ; i < count ; i++) { | |
930 size_t len = strcspn(p, os::path_separator()); | |
931 if (len > JVM_MAXPATHLEN) { | |
932 return NULL; | |
933 } | |
934 // allocate the string and add terminator storage | |
935 char* s = (char*)NEW_C_HEAP_ARRAY(char, len + 1); | |
936 if (s == NULL) { | |
937 return NULL; | |
938 } | |
939 strncpy(s, p, len); | |
940 s[len] = '\0'; | |
941 opath[i] = s; | |
942 p += len + 1; | |
943 } | |
944 FREE_C_HEAP_ARRAY(char, inpath); | |
945 *n = count; | |
946 return opath; | |
947 } | |
948 | |
0 | 949 void os::set_memory_serialize_page(address page) { |
950 int count = log2_intptr(sizeof(class JavaThread)) - log2_intptr(64); | |
951 _mem_serialize_page = (volatile int32_t *)page; | |
952 // We initialize the serialization page shift count here | |
953 // We assume a cache line size of 64 bytes | |
954 assert(SerializePageShiftCount == count, | |
955 "thread size changed, fix SerializePageShiftCount constant"); | |
956 set_serialize_page_mask((uintptr_t)(vm_page_size() - sizeof(int32_t))); | |
957 } | |
958 | |
55
2a8eb116ebbe
6610420: Debug VM crashes during monitor lock rank checking
xlu
parents:
0
diff
changeset
|
959 static volatile intptr_t SerializePageLock = 0; |
2a8eb116ebbe
6610420: Debug VM crashes during monitor lock rank checking
xlu
parents:
0
diff
changeset
|
960 |
0 | 961 // This method is called from signal handler when SIGSEGV occurs while the current |
962 // thread tries to store to the "read-only" memory serialize page during state | |
963 // transition. | |
964 void os::block_on_serialize_page_trap() { | |
965 if (TraceSafepoint) { | |
966 tty->print_cr("Block until the serialize page permission restored"); | |
967 } | |
55
2a8eb116ebbe
6610420: Debug VM crashes during monitor lock rank checking
xlu
parents:
0
diff
changeset
|
968 // When VMThread is holding the SerializePageLock during modifying the |
0 | 969 // access permission of the memory serialize page, the following call |
970 // will block until the permission of that page is restored to rw. | |
971 // Generally, it is unsafe to manipulate locks in signal handlers, but in | |
972 // this case, it's OK as the signal is synchronous and we know precisely when | |
55
2a8eb116ebbe
6610420: Debug VM crashes during monitor lock rank checking
xlu
parents:
0
diff
changeset
|
973 // it can occur. |
2a8eb116ebbe
6610420: Debug VM crashes during monitor lock rank checking
xlu
parents:
0
diff
changeset
|
974 Thread::muxAcquire(&SerializePageLock, "set_memory_serialize_page"); |
2a8eb116ebbe
6610420: Debug VM crashes during monitor lock rank checking
xlu
parents:
0
diff
changeset
|
975 Thread::muxRelease(&SerializePageLock); |
0 | 976 } |
977 | |
978 // Serialize all thread state variables | |
979 void os::serialize_thread_states() { | |
980 // On some platforms such as Solaris & Linux, the time duration of the page | |
981 // permission restoration is observed to be much longer than expected due to | |
982 // scheduler starvation problem etc. To avoid the long synchronization | |
55
2a8eb116ebbe
6610420: Debug VM crashes during monitor lock rank checking
xlu
parents:
0
diff
changeset
|
983 // time and expensive page trap spinning, 'SerializePageLock' is used to block |
2a8eb116ebbe
6610420: Debug VM crashes during monitor lock rank checking
xlu
parents:
0
diff
changeset
|
984 // the mutator thread if such case is encountered. See bug 6546278 for details. |
2a8eb116ebbe
6610420: Debug VM crashes during monitor lock rank checking
xlu
parents:
0
diff
changeset
|
985 Thread::muxAcquire(&SerializePageLock, "serialize_thread_states"); |
237
1fdb98a17101
6716785: implicit null checks not triggering with CompressedOops
coleenp
parents:
196
diff
changeset
|
986 os::protect_memory((char *)os::get_memory_serialize_page(), |
477
24fda36852ce
6727377: VM stack guard pages on Windows should PAGE_READWRITE not PAGE_EXECUTE_READWRITE
coleenp
parents:
242
diff
changeset
|
987 os::vm_page_size(), MEM_PROT_READ); |
24fda36852ce
6727377: VM stack guard pages on Windows should PAGE_READWRITE not PAGE_EXECUTE_READWRITE
coleenp
parents:
242
diff
changeset
|
988 os::protect_memory((char *)os::get_memory_serialize_page(), |
24fda36852ce
6727377: VM stack guard pages on Windows should PAGE_READWRITE not PAGE_EXECUTE_READWRITE
coleenp
parents:
242
diff
changeset
|
989 os::vm_page_size(), MEM_PROT_RW); |
55
2a8eb116ebbe
6610420: Debug VM crashes during monitor lock rank checking
xlu
parents:
0
diff
changeset
|
990 Thread::muxRelease(&SerializePageLock); |
0 | 991 } |
992 | |
993 // Returns true if the current stack pointer is above the stack shadow | |
994 // pages, false otherwise. | |
995 | |
996 bool os::stack_shadow_pages_available(Thread *thread, methodHandle method) { | |
997 assert(StackRedPages > 0 && StackYellowPages > 0,"Sanity check"); | |
998 address sp = current_stack_pointer(); | |
999 // Check if we have StackShadowPages above the yellow zone. This parameter | |
605 | 1000 // is dependent on the depth of the maximum VM call stack possible from |
0 | 1001 // the handler for stack overflow. 'instanceof' in the stack overflow |
1002 // handler or a println uses at least 8k stack of VM and native code | |
1003 // respectively. | |
1004 const int framesize_in_bytes = | |
1005 Interpreter::size_top_interpreter_activation(method()) * wordSize; | |
1006 int reserved_area = ((StackShadowPages + StackRedPages + StackYellowPages) | |
1007 * vm_page_size()) + framesize_in_bytes; | |
1008 // The very lower end of the stack | |
1009 address stack_limit = thread->stack_base() - thread->stack_size(); | |
1010 return (sp > (stack_limit + reserved_area)); | |
1011 } | |
1012 | |
1013 size_t os::page_size_for_region(size_t region_min_size, size_t region_max_size, | |
1014 uint min_pages) | |
1015 { | |
1016 assert(min_pages > 0, "sanity"); | |
1017 if (UseLargePages) { | |
1018 const size_t max_page_size = region_max_size / min_pages; | |
1019 | |
1020 for (unsigned int i = 0; _page_sizes[i] != 0; ++i) { | |
1021 const size_t sz = _page_sizes[i]; | |
1022 const size_t mask = sz - 1; | |
1023 if ((region_min_size & mask) == 0 && (region_max_size & mask) == 0) { | |
1024 // The largest page size with no fragmentation. | |
1025 return sz; | |
1026 } | |
1027 | |
1028 if (sz <= max_page_size) { | |
1029 // The largest page size that satisfies the min_pages requirement. | |
1030 return sz; | |
1031 } | |
1032 } | |
1033 } | |
1034 | |
1035 return vm_page_size(); | |
1036 } | |
1037 | |
1038 #ifndef PRODUCT | |
1039 void os::trace_page_sizes(const char* str, const size_t region_min_size, | |
1040 const size_t region_max_size, const size_t page_size, | |
1041 const char* base, const size_t size) | |
1042 { | |
1043 if (TracePageSizes) { | |
1044 tty->print_cr("%s: min=" SIZE_FORMAT " max=" SIZE_FORMAT | |
1045 " pg_sz=" SIZE_FORMAT " base=" PTR_FORMAT | |
1046 " size=" SIZE_FORMAT, | |
1047 str, region_min_size, region_max_size, | |
1048 page_size, base, size); | |
1049 } | |
1050 } | |
1051 #endif // #ifndef PRODUCT | |
1052 | |
1053 // This is the working definition of a server class machine: | |
1054 // >= 2 physical CPU's and >=2GB of memory, with some fuzz | |
1055 // because the graphics memory (?) sometimes masks physical memory. | |
1056 // If you want to change the definition of a server class machine | |
1057 // on some OS or platform, e.g., >=4GB on Windohs platforms, | |
1058 // then you'll have to parameterize this method based on that state, | |
1059 // as was done for logical processors here, or replicate and | |
1060 // specialize this method for each platform. (Or fix os to have | |
1061 // some inheritance structure and use subclassing. Sigh.) | |
1062 // If you want some platform to always or never behave as a server | |
1063 // class machine, change the setting of AlwaysActAsServerClassMachine | |
1064 // and NeverActAsServerClassMachine in globals*.hpp. | |
1065 bool os::is_server_class_machine() { | |
1066 // First check for the early returns | |
1067 if (NeverActAsServerClassMachine) { | |
1068 return false; | |
1069 } | |
1070 if (AlwaysActAsServerClassMachine) { | |
1071 return true; | |
1072 } | |
1073 // Then actually look at the machine | |
1074 bool result = false; | |
1075 const unsigned int server_processors = 2; | |
1076 const julong server_memory = 2UL * G; | |
1077 // We seem not to get our full complement of memory. | |
1078 // We allow some part (1/8?) of the memory to be "missing", | |
1079 // based on the sizes of DIMMs, and maybe graphics cards. | |
1080 const julong missing_memory = 256UL * M; | |
1081 | |
1082 /* Is this a server class machine? */ | |
1083 if ((os::active_processor_count() >= (int)server_processors) && | |
1084 (os::physical_memory() >= (server_memory - missing_memory))) { | |
1085 const unsigned int logical_processors = | |
1086 VM_Version::logical_processors_per_package(); | |
1087 if (logical_processors > 1) { | |
1088 const unsigned int physical_packages = | |
1089 os::active_processor_count() / logical_processors; | |
1090 if (physical_packages > server_processors) { | |
1091 result = true; | |
1092 } | |
1093 } else { | |
1094 result = true; | |
1095 } | |
1096 } | |
1097 return result; | |
1098 } |