annotate src/hotspot/os/aix/os_aix.cpp @ 50768:1a4101ebec92

8202014: Possible to receive signal before signal semaphore created Summary: initialize jdk.internal.misc.Signal in os_init2 and rename initialization functions. Reviewed-by: dholmes, stuefe
author coleenp
date Fri, 18 May 2018 15:56:42 -0400
parents 9806f23d5e5e
children 83aec1d357d4
rev   line source
simonis@22831 1 /*
coleenp@48955 2 * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
clanger@49206 3 * Copyright (c) 2012, 2018 SAP SE. All rights reserved.
simonis@22831 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
simonis@22831 5 *
simonis@22831 6 * This code is free software; you can redistribute it and/or modify it
simonis@22831 7 * under the terms of the GNU General Public License version 2 only, as
simonis@22831 8 * published by the Free Software Foundation.
simonis@22831 9 *
simonis@22831 10 * This code is distributed in the hope that it will be useful, but WITHOUT
simonis@22831 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
simonis@22831 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
simonis@22831 13 * version 2 for more details (a copy is included in the LICENSE file that
simonis@22831 14 * accompanied this code).
simonis@22831 15 *
simonis@22831 16 * You should have received a copy of the GNU General Public License version
simonis@22831 17 * 2 along with this work; if not, write to the Free Software Foundation,
simonis@22831 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
simonis@22831 19 *
simonis@22831 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
simonis@22831 21 * or visit www.oracle.com if you need additional information or have any
simonis@22831 22 * questions.
simonis@22831 23 *
simonis@22831 24 */
simonis@22831 25
simonis@22831 26 // According to the AIX OS doc #pragma alloca must be used
simonis@22831 27 // with C++ compiler before referencing the function alloca()
simonis@22831 28 #pragma alloca
simonis@22831 29
simonis@22831 30 // no precompiled headers
coleenp@47946 31 #include "jvm.h"
simonis@22831 32 #include "classfile/classLoader.hpp"
simonis@22831 33 #include "classfile/systemDictionary.hpp"
simonis@22831 34 #include "classfile/vmSymbols.hpp"
simonis@22831 35 #include "code/icBuffer.hpp"
simonis@22831 36 #include "code/vtableStubs.hpp"
simonis@22831 37 #include "compiler/compileBroker.hpp"
simonis@22831 38 #include "interpreter/interpreter.hpp"
stuefe@36355 39 #include "logging/log.hpp"
stuefe@34647 40 #include "libo4.hpp"
simonis@22831 41 #include "libperfstat_aix.hpp"
mdoerr@35063 42 #include "libodm_aix.hpp"
simonis@22831 43 #include "loadlib_aix.hpp"
simonis@22831 44 #include "memory/allocation.inline.hpp"
simonis@22831 45 #include "memory/filemap.hpp"
stuefe@33743 46 #include "misc_aix.hpp"
simonis@22831 47 #include "oops/oop.inline.hpp"
goetz@25468 48 #include "os_aix.inline.hpp"
simonis@22831 49 #include "os_share_aix.hpp"
simonis@22831 50 #include "porting_aix.hpp"
simonis@22831 51 #include "prims/jniFastGetField.hpp"
simonis@22831 52 #include "prims/jvm_misc.hpp"
simonis@22831 53 #include "runtime/arguments.hpp"
dholmes@40655 54 #include "runtime/atomic.hpp"
simonis@22831 55 #include "runtime/extendedPC.hpp"
simonis@22831 56 #include "runtime/globals.hpp"
coleenp@49914 57 #include "runtime/interfaceSupport.inline.hpp"
simonis@22831 58 #include "runtime/java.hpp"
simonis@22831 59 #include "runtime/javaCalls.hpp"
simonis@22831 60 #include "runtime/mutexLocker.hpp"
simonis@22831 61 #include "runtime/objectMonitor.hpp"
goetz@24351 62 #include "runtime/orderAccess.inline.hpp"
zgu@25949 63 #include "runtime/os.hpp"
simonis@22831 64 #include "runtime/osThread.hpp"
simonis@22831 65 #include "runtime/perfMemory.hpp"
simonis@22831 66 #include "runtime/sharedRuntime.hpp"
simonis@22831 67 #include "runtime/statSampler.hpp"
simonis@22831 68 #include "runtime/stubRoutines.hpp"
goetz@23522 69 #include "runtime/thread.inline.hpp"
simonis@22831 70 #include "runtime/threadCritical.hpp"
simonis@22831 71 #include "runtime/timer.hpp"
goetz@25715 72 #include "runtime/vm_version.hpp"
simonis@22831 73 #include "services/attachListener.hpp"
simonis@22831 74 #include "services/runtimeService.hpp"
stefank@46625 75 #include "utilities/align.hpp"
simonis@22831 76 #include "utilities/decoder.hpp"
simonis@22831 77 #include "utilities/defaultStream.hpp"
simonis@22831 78 #include "utilities/events.hpp"
simonis@22831 79 #include "utilities/growableArray.hpp"
simonis@22831 80 #include "utilities/vmError.hpp"
simonis@22831 81
simonis@22831 82 // put OS-includes here (sorted alphabetically)
simonis@22831 83 #include <errno.h>
simonis@22831 84 #include <fcntl.h>
simonis@22831 85 #include <inttypes.h>
simonis@22831 86 #include <poll.h>
simonis@22831 87 #include <procinfo.h>
simonis@22831 88 #include <pthread.h>
simonis@22831 89 #include <pwd.h>
simonis@22831 90 #include <semaphore.h>
simonis@22831 91 #include <signal.h>
simonis@22831 92 #include <stdint.h>
simonis@22831 93 #include <stdio.h>
simonis@22831 94 #include <string.h>
simonis@22831 95 #include <unistd.h>
simonis@22831 96 #include <sys/ioctl.h>
simonis@22831 97 #include <sys/ipc.h>
simonis@22831 98 #include <sys/mman.h>
simonis@22831 99 #include <sys/resource.h>
simonis@22831 100 #include <sys/select.h>
simonis@22831 101 #include <sys/shm.h>
simonis@22831 102 #include <sys/socket.h>
simonis@22831 103 #include <sys/stat.h>
simonis@22831 104 #include <sys/sysinfo.h>
simonis@22831 105 #include <sys/systemcfg.h>
simonis@22831 106 #include <sys/time.h>
simonis@22831 107 #include <sys/times.h>
simonis@22831 108 #include <sys/types.h>
simonis@22831 109 #include <sys/utsname.h>
simonis@22831 110 #include <sys/vminfo.h>
simonis@22831 111 #include <sys/wait.h>
simonis@22831 112
stuefe@34647 113 // Missing prototypes for various system APIs.
stuefe@34647 114 extern "C"
stuefe@34647 115 int mread_real_time(timebasestruct_t *t, size_t size_of_timebasestruct_t);
stuefe@34647 116
simonis@22831 117 #if !defined(_AIXVERSION_610)
stuefe@34647 118 extern "C" int getthrds64(pid_t, struct thrdentry64*, int, tid64_t*, int);
stuefe@34647 119 extern "C" int getprocs64(procentry64*, int, fdsinfo*, int, pid_t*, int);
clanger@49206 120 extern "C" int getargs(procsinfo*, int, char*, int);
simonis@22831 121 #endif
simonis@22831 122
simonis@22831 123 #define MAX_PATH (2 * K)
simonis@22831 124
simonis@22831 125 // for timer info max values which include all bits
simonis@22831 126 #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
simonis@22831 127 // for multipage initialization error analysis (in 'g_multipage_error')
simonis@22831 128 #define ERROR_MP_OS_TOO_OLD 100
simonis@22831 129 #define ERROR_MP_EXTSHM_ACTIVE 101
simonis@22831 130 #define ERROR_MP_VMGETINFO_FAILED 102
simonis@22831 131 #define ERROR_MP_VMGETINFO_CLAIMS_NO_SUPPORT_FOR_64K 103
simonis@22831 132
clanger@49206 133 // excerpts from systemcfg.h that might be missing on older os levels
clanger@49206 134 #ifndef PV_5_Compat
clanger@49206 135 #define PV_5_Compat 0x0F8000 /* Power PC 5 */
clanger@49206 136 #endif
clanger@49206 137 #ifndef PV_6
clanger@49206 138 #define PV_6 0x100000 /* Power PC 6 */
clanger@49206 139 #endif
clanger@49206 140 #ifndef PV_6_1
clanger@49206 141 #define PV_6_1 0x100001 /* Power PC 6 DD1.x */
clanger@49206 142 #endif
clanger@49206 143 #ifndef PV_6_Compat
clanger@49206 144 #define PV_6_Compat 0x108000 /* Power PC 6 */
clanger@49206 145 #endif
clanger@49206 146 #ifndef PV_7
clanger@49206 147 #define PV_7 0x200000 /* Power PC 7 */
clanger@49206 148 #endif
clanger@49206 149 #ifndef PV_7_Compat
clanger@49206 150 #define PV_7_Compat 0x208000 /* Power PC 7 */
clanger@49206 151 #endif
clanger@49206 152 #ifndef PV_8
clanger@49206 153 #define PV_8 0x300000 /* Power PC 8 */
clanger@49206 154 #endif
clanger@49206 155 #ifndef PV_8_Compat
clanger@49206 156 #define PV_8_Compat 0x308000 /* Power PC 8 */
clanger@49206 157 #endif
clanger@49206 158
stuefe@34647 159 static address resolve_function_descriptor_to_code_pointer(address p);
simonis@22831 160
stuefe@34647 161 static void vmembk_print_on(outputStream* os);
stuefe@34647 162
simonis@22831 163 ////////////////////////////////////////////////////////////////////////////////
simonis@22831 164 // global variables (for a description see os_aix.hpp)
simonis@22831 165
simonis@22831 166 julong os::Aix::_physical_memory = 0;
stuefe@34647 167
simonis@22831 168 pthread_t os::Aix::_main_thread = ((pthread_t)0);
simonis@22831 169 int os::Aix::_page_size = -1;
stuefe@34647 170
stuefe@34647 171 // -1 = uninitialized, 0 if AIX, 1 if OS/400 pase
simonis@22831 172 int os::Aix::_on_pase = -1;
stuefe@34647 173
mdoerr@35063 174 // 0 = uninitialized, otherwise 32 bit number:
mdoerr@35063 175 // 0xVVRRTTSS
mdoerr@35063 176 // VV - major version
mdoerr@35063 177 // RR - minor version
mdoerr@35063 178 // TT - tech level, if known, 0 otherwise
mdoerr@35063 179 // SS - service pack, if known, 0 otherwise
mdoerr@35063 180 uint32_t os::Aix::_os_version = 0;
stuefe@34647 181
stuefe@34647 182 // -1 = uninitialized, 0 - no, 1 - yes
simonis@22831 183 int os::Aix::_xpg_sus_mode = -1;
stuefe@34647 184
stuefe@34647 185 // -1 = uninitialized, 0 - no, 1 - yes
simonis@22831 186 int os::Aix::_extshm = -1;
simonis@22831 187
simonis@22831 188 ////////////////////////////////////////////////////////////////////////////////
simonis@22831 189 // local variables
simonis@22831 190
clanger@49260 191 static volatile jlong max_real_time = 0;
simonis@22831 192 static jlong initial_time_count = 0;
simonis@22831 193 static int clock_tics_per_sec = 100;
simonis@22831 194 static sigset_t check_signal_done; // For diagnostics to print a message once (see run_periodic_checks)
simonis@22831 195 static bool check_signals = true;
simonis@22831 196 static int SR_signum = SIGUSR2; // Signal used to suspend/resume a thread (must be > SIGSEGV, see 4355769)
simonis@22831 197 static sigset_t SR_sigset;
simonis@22831 198
stuefe@34647 199 // Process break recorded at startup.
stuefe@34647 200 static address g_brk_at_startup = NULL;
stuefe@34647 201
goetz@30198 202 // This describes the state of multipage support of the underlying
goetz@30198 203 // OS. Note that this is of no interest to the outsize world and
goetz@30198 204 // therefore should not be defined in AIX class.
goetz@30198 205 //
goetz@30198 206 // AIX supports four different page sizes - 4K, 64K, 16MB, 16GB. The
goetz@30198 207 // latter two (16M "large" resp. 16G "huge" pages) require special
goetz@30198 208 // setup and are normally not available.
goetz@30198 209 //
goetz@30198 210 // AIX supports multiple page sizes per process, for:
goetz@30198 211 // - Stack (of the primordial thread, so not relevant for us)
goetz@30198 212 // - Data - data, bss, heap, for us also pthread stacks
goetz@30198 213 // - Text - text code
goetz@30198 214 // - shared memory
goetz@30198 215 //
goetz@30198 216 // Default page sizes can be set via linker options (-bdatapsize, -bstacksize, ...)
goetz@30198 217 // and via environment variable LDR_CNTRL (DATAPSIZE, STACKPSIZE, ...).
goetz@30198 218 //
goetz@30198 219 // For shared memory, page size can be set dynamically via
goetz@30198 220 // shmctl(). Different shared memory regions can have different page
goetz@30198 221 // sizes.
goetz@30198 222 //
goetz@30198 223 // More information can be found at AIBM info center:
goetz@30198 224 // http://publib.boulder.ibm.com/infocenter/aix/v6r1/index.jsp?topic=/com.ibm.aix.prftungd/doc/prftungd/multiple_page_size_app_support.htm
goetz@30198 225 //
goetz@30198 226 static struct {
goetz@30198 227 size_t pagesize; // sysconf _SC_PAGESIZE (4K)
goetz@30198 228 size_t datapsize; // default data page size (LDR_CNTRL DATAPSIZE)
goetz@30198 229 size_t shmpsize; // default shared memory page size (LDR_CNTRL SHMPSIZE)
goetz@30198 230 size_t pthr_stack_pagesize; // stack page size of pthread threads
goetz@30198 231 size_t textpsize; // default text page size (LDR_CNTRL STACKPSIZE)
goetz@30198 232 bool can_use_64K_pages; // True if we can alloc 64K pages dynamically with Sys V shm.
goetz@30198 233 bool can_use_16M_pages; // True if we can alloc 16M pages dynamically with Sys V shm.
goetz@30198 234 int error; // Error describing if something went wrong at multipage init.
goetz@30198 235 } g_multipage_support = {
goetz@30198 236 (size_t) -1,
goetz@30198 237 (size_t) -1,
goetz@30198 238 (size_t) -1,
goetz@30198 239 (size_t) -1,
goetz@30198 240 (size_t) -1,
goetz@30198 241 false, false,
goetz@30198 242 0
goetz@30198 243 };
goetz@30198 244
goetz@30198 245 // We must not accidentally allocate memory close to the BRK - even if
goetz@30198 246 // that would work - because then we prevent the BRK segment from
goetz@30198 247 // growing which may result in a malloc OOM even though there is
goetz@30198 248 // enough memory. The problem only arises if we shmat() or mmap() at
goetz@30198 249 // a specific wish address, e.g. to place the heap in a
goetz@30198 250 // compressed-oops-friendly way.
goetz@30198 251 static bool is_close_to_brk(address a) {
stuefe@34647 252 assert0(g_brk_at_startup != NULL);
stuefe@34647 253 if (a >= g_brk_at_startup &&
stuefe@34647 254 a < (g_brk_at_startup + MaxExpectedDataSegmentSize)) {
goetz@30198 255 return true;
goetz@30198 256 }
goetz@30198 257 return false;
goetz@30198 258 }
goetz@30198 259
simonis@22831 260 julong os::available_memory() {
simonis@22831 261 return Aix::available_memory();
simonis@22831 262 }
simonis@22831 263
simonis@22831 264 julong os::Aix::available_memory() {
stuefe@34647 265 // Avoid expensive API call here, as returned value will always be null.
stuefe@34647 266 if (os::Aix::on_pase()) {
stuefe@34647 267 return 0x0LL;
stuefe@34647 268 }
simonis@22837 269 os::Aix::meminfo_t mi;
simonis@22837 270 if (os::Aix::get_meminfo(&mi)) {
simonis@22837 271 return mi.real_free;
simonis@22837 272 } else {
stuefe@34647 273 return ULONG_MAX;
simonis@22837 274 }
simonis@22831 275 }
simonis@22831 276
simonis@22831 277 julong os::physical_memory() {
simonis@22831 278 return Aix::physical_memory();
simonis@22831 279 }
simonis@22831 280
simonis@22831 281 // Return true if user is running as root.
simonis@22831 282
simonis@22831 283 bool os::have_special_privileges() {
simonis@22831 284 static bool init = false;
simonis@22831 285 static bool privileges = false;
simonis@22831 286 if (!init) {
simonis@22831 287 privileges = (getuid() != geteuid()) || (getgid() != getegid());
simonis@22831 288 init = true;
simonis@22831 289 }
simonis@22831 290 return privileges;
simonis@22831 291 }
simonis@22831 292
simonis@22831 293 // Helper function, emulates disclaim64 using multiple 32bit disclaims
simonis@22831 294 // because we cannot use disclaim64() on AS/400 and old AIX releases.
simonis@22831 295 static bool my_disclaim64(char* addr, size_t size) {
simonis@22831 296
simonis@22831 297 if (size == 0) {
simonis@22831 298 return true;
simonis@22831 299 }
simonis@22831 300
simonis@22831 301 // Maximum size 32bit disclaim() accepts. (Theoretically 4GB, but I just do not trust that.)
goetz@30198 302 const unsigned int maxDisclaimSize = 0x40000000;
simonis@22831 303
simonis@22831 304 const unsigned int numFullDisclaimsNeeded = (size / maxDisclaimSize);
simonis@22831 305 const unsigned int lastDisclaimSize = (size % maxDisclaimSize);
simonis@22831 306
simonis@22831 307 char* p = addr;
simonis@22831 308
simonis@22831 309 for (int i = 0; i < numFullDisclaimsNeeded; i ++) {
simonis@22831 310 if (::disclaim(p, maxDisclaimSize, DISCLAIM_ZEROMEM) != 0) {
stuefe@34647 311 trcVerbose("Cannot disclaim %p - %p (errno %d)\n", p, p + maxDisclaimSize, errno);
simonis@22831 312 return false;
simonis@22831 313 }
simonis@22831 314 p += maxDisclaimSize;
simonis@22831 315 }
simonis@22831 316
simonis@22831 317 if (lastDisclaimSize > 0) {
simonis@22831 318 if (::disclaim(p, lastDisclaimSize, DISCLAIM_ZEROMEM) != 0) {
stuefe@34647 319 trcVerbose("Cannot disclaim %p - %p (errno %d)\n", p, p + lastDisclaimSize, errno);
simonis@22831 320 return false;
simonis@22831 321 }
simonis@22831 322 }
simonis@22831 323
simonis@22831 324 return true;
simonis@22831 325 }
simonis@22831 326
simonis@22831 327 // Cpu architecture string
simonis@22831 328 #if defined(PPC32)
simonis@22831 329 static char cpu_arch[] = "ppc";
simonis@22831 330 #elif defined(PPC64)
simonis@22831 331 static char cpu_arch[] = "ppc64";
simonis@22831 332 #else
simonis@22831 333 #error Add appropriate cpu_arch setting
simonis@22831 334 #endif
simonis@22831 335
stuefe@34647 336 // Wrap the function "vmgetinfo" which is not available on older OS releases.
stuefe@34647 337 static int checked_vmgetinfo(void *out, int command, int arg) {
mdoerr@35063 338 if (os::Aix::on_pase() && os::Aix::os_version_short() < 0x0601) {
stuefe@34647 339 guarantee(false, "cannot call vmgetinfo on AS/400 older than V6R1");
stuefe@34647 340 }
stuefe@34647 341 return ::vmgetinfo(out, command, arg);
stuefe@34647 342 }
simonis@22831 343
simonis@22831 344 // Given an address, returns the size of the page backing that address.
simonis@22831 345 size_t os::Aix::query_pagesize(void* addr) {
simonis@22831 346
mdoerr@35063 347 if (os::Aix::on_pase() && os::Aix::os_version_short() < 0x0601) {
stuefe@34647 348 // AS/400 older than V6R1: no vmgetinfo here, default to 4K
simonis@42061 349 return 4*K;
stuefe@34647 350 }
stuefe@34647 351
simonis@22831 352 vm_page_info pi;
simonis@22831 353 pi.addr = (uint64_t)addr;
stuefe@34647 354 if (checked_vmgetinfo(&pi, VM_PAGE_INFO, sizeof(pi)) == 0) {
simonis@22831 355 return pi.pagesize;
simonis@22831 356 } else {
simonis@22831 357 assert(false, "vmgetinfo failed to retrieve page size");
simonis@42061 358 return 4*K;
simonis@22831 359 }
simonis@22831 360 }
simonis@22831 361
simonis@22831 362 void os::Aix::initialize_system_info() {
simonis@22831 363
goetz@28187 364 // Get the number of online(logical) cpus instead of configured.
simonis@22831 365 os::_processor_count = sysconf(_SC_NPROCESSORS_ONLN);
simonis@22831 366 assert(_processor_count > 0, "_processor_count must be > 0");
simonis@22831 367
goetz@28187 368 // Retrieve total physical storage.
simonis@22831 369 os::Aix::meminfo_t mi;
simonis@22831 370 if (!os::Aix::get_meminfo(&mi)) {
simonis@22831 371 assert(false, "os::Aix::get_meminfo failed.");
simonis@22831 372 }
simonis@22831 373 _physical_memory = (julong) mi.real_total;
simonis@22831 374 }
simonis@22831 375
simonis@22831 376 // Helper function for tracing page sizes.
simonis@22831 377 static const char* describe_pagesize(size_t pagesize) {
simonis@22831 378 switch (pagesize) {
simonis@42061 379 case 4*K : return "4K";
simonis@42061 380 case 64*K: return "64K";
simonis@42061 381 case 16*M: return "16M";
simonis@42061 382 case 16*G: return "16G";
simonis@22831 383 default:
simonis@22831 384 assert(false, "surprise");
simonis@22831 385 return "??";
simonis@22831 386 }
simonis@22831 387 }
simonis@22831 388
goetz@30198 389 // Probe OS for multipage support.
goetz@30198 390 // Will fill the global g_multipage_support structure.
simonis@22831 391 // Must be called before calling os::large_page_init().
goetz@30198 392 static void query_multipage_support() {
goetz@30198 393
goetz@30198 394 guarantee(g_multipage_support.pagesize == -1,
simonis@22831 395 "do not call twice");
simonis@22831 396
goetz@30198 397 g_multipage_support.pagesize = ::sysconf(_SC_PAGESIZE);
simonis@22831 398
simonis@22831 399 // This really would surprise me.
simonis@42061 400 assert(g_multipage_support.pagesize == 4*K, "surprise!");
simonis@22831 401
goetz@23522 402 // Query default data page size (default page size for C-Heap, pthread stacks and .bss).
goetz@30198 403 // Default data page size is defined either by linker options (-bdatapsize)
simonis@22831 404 // or by environment variable LDR_CNTRL (suboption DATAPSIZE). If none is given,
simonis@22831 405 // default should be 4K.
simonis@22831 406 {
simonis@42061 407 void* p = ::malloc(16*M);
goetz@30198 408 g_multipage_support.datapsize = os::Aix::query_pagesize(p);
goetz@30198 409 ::free(p);
goetz@30198 410 }
goetz@30198 411
goetz@30198 412 // Query default shm page size (LDR_CNTRL SHMPSIZE).
stuefe@34647 413 // Note that this is pure curiosity. We do not rely on default page size but set
stuefe@34647 414 // our own page size after allocated.
simonis@22831 415 {
simonis@22831 416 const int shmid = ::shmget(IPC_PRIVATE, 1, IPC_CREAT | S_IRUSR | S_IWUSR);
simonis@22831 417 guarantee(shmid != -1, "shmget failed");
simonis@22831 418 void* p = ::shmat(shmid, NULL, 0);
simonis@22831 419 ::shmctl(shmid, IPC_RMID, NULL);
simonis@22831 420 guarantee(p != (void*) -1, "shmat failed");
goetz@30198 421 g_multipage_support.shmpsize = os::Aix::query_pagesize(p);
simonis@22831 422 ::shmdt(p);
simonis@22831 423 }
simonis@22831 424
goetz@30198 425 // Before querying the stack page size, make sure we are not running as primordial
simonis@22831 426 // thread (because primordial thread's stack may have different page size than
simonis@22831 427 // pthread thread stacks). Running a VM on the primordial thread won't work for a
goetz@30198 428 // number of reasons so we may just as well guarantee it here.
dholmes@48202 429 guarantee0(!os::is_primordial_thread());
goetz@30198 430
stuefe@34647 431 // Query pthread stack page size. Should be the same as data page size because
stuefe@34647 432 // pthread stacks are allocated from C-Heap.
simonis@22831 433 {
simonis@22831 434 int dummy = 0;
goetz@30198 435 g_multipage_support.pthr_stack_pagesize = os::Aix::query_pagesize(&dummy);
goetz@30198 436 }
goetz@30198 437
goetz@30198 438 // Query default text page size (LDR_CNTRL TEXTPSIZE).
goetz@30198 439 {
goetz@30198 440 address any_function =
stuefe@34647 441 resolve_function_descriptor_to_code_pointer((address)describe_pagesize);
goetz@30198 442 g_multipage_support.textpsize = os::Aix::query_pagesize(any_function);
goetz@30198 443 }
goetz@30198 444
goetz@30198 445 // Now probe for support of 64K pages and 16M pages.
goetz@30198 446
goetz@30198 447 // Before OS/400 V6R1, there is no support for pages other than 4K.
goetz@30198 448 if (os::Aix::on_pase_V5R4_or_older()) {
stuefe@34647 449 trcVerbose("OS/400 < V6R1 - no large page support.");
stuefe@34647 450 g_multipage_support.error = ERROR_MP_OS_TOO_OLD;
simonis@22831 451 goto query_multipage_support_end;
simonis@22831 452 }
simonis@22831 453
goetz@30198 454 // Now check which page sizes the OS claims it supports, and of those, which actually can be used.
simonis@22831 455 {
simonis@22831 456 const int MAX_PAGE_SIZES = 4;
simonis@22831 457 psize_t sizes[MAX_PAGE_SIZES];
stuefe@34647 458 const int num_psizes = checked_vmgetinfo(sizes, VMINFO_GETPSIZES, MAX_PAGE_SIZES);
simonis@22831 459 if (num_psizes == -1) {
stuefe@34647 460 trcVerbose("vmgetinfo(VMINFO_GETPSIZES) failed (errno: %d)", errno);
stuefe@34647 461 trcVerbose("disabling multipage support.");
goetz@30198 462 g_multipage_support.error = ERROR_MP_VMGETINFO_FAILED;
simonis@22831 463 goto query_multipage_support_end;
simonis@22831 464 }
simonis@22831 465 guarantee(num_psizes > 0, "vmgetinfo(.., VMINFO_GETPSIZES, ...) failed.");
simonis@22831 466 assert(num_psizes <= MAX_PAGE_SIZES, "Surprise! more than 4 page sizes?");
goetz@30198 467 trcVerbose("vmgetinfo(.., VMINFO_GETPSIZES, ...) returns %d supported page sizes: ", num_psizes);
goetz@30198 468 for (int i = 0; i < num_psizes; i ++) {
goetz@30198 469 trcVerbose(" %s ", describe_pagesize(sizes[i]));
goetz@30198 470 }
goetz@30198 471
goetz@30198 472 // Can we use 64K, 16M pages?
goetz@30198 473 for (int i = 0; i < num_psizes; i ++) {
goetz@30198 474 const size_t pagesize = sizes[i];
simonis@42061 475 if (pagesize != 64*K && pagesize != 16*M) {
goetz@30198 476 continue;
simonis@22831 477 }
goetz@30198 478 bool can_use = false;
goetz@30198 479 trcVerbose("Probing support for %s pages...", describe_pagesize(pagesize));
goetz@30198 480 const int shmid = ::shmget(IPC_PRIVATE, pagesize,
goetz@30198 481 IPC_CREAT | S_IRUSR | S_IWUSR);
goetz@30198 482 guarantee0(shmid != -1); // Should always work.
goetz@30198 483 // Try to set pagesize.
goetz@30198 484 struct shmid_ds shm_buf = { 0 };
goetz@30198 485 shm_buf.shm_pagesize = pagesize;
goetz@30198 486 if (::shmctl(shmid, SHM_PAGESIZE, &shm_buf) != 0) {
goetz@30198 487 const int en = errno;
goetz@30198 488 ::shmctl(shmid, IPC_RMID, NULL); // As early as possible!
stuefe@34647 489 trcVerbose("shmctl(SHM_PAGESIZE) failed with errno=%n",
stuefe@34647 490 errno);
goetz@30198 491 } else {
goetz@30198 492 // Attach and double check pageisze.
goetz@30198 493 void* p = ::shmat(shmid, NULL, 0);
goetz@30198 494 ::shmctl(shmid, IPC_RMID, NULL); // As early as possible!
goetz@30198 495 guarantee0(p != (void*) -1); // Should always work.
goetz@30198 496 const size_t real_pagesize = os::Aix::query_pagesize(p);
goetz@30198 497 if (real_pagesize != pagesize) {
goetz@30198 498 trcVerbose("real page size (0x%llX) differs.", real_pagesize);
goetz@30198 499 } else {
goetz@30198 500 can_use = true;
goetz@30198 501 }
goetz@30198 502 ::shmdt(p);
goetz@30198 503 }
goetz@30198 504 trcVerbose("Can use: %s", (can_use ? "yes" : "no"));
simonis@42061 505 if (pagesize == 64*K) {
goetz@30198 506 g_multipage_support.can_use_64K_pages = can_use;
simonis@42061 507 } else if (pagesize == 16*M) {
goetz@30198 508 g_multipage_support.can_use_16M_pages = can_use;
simonis@22831 509 }
simonis@22831 510 }
simonis@22831 511
simonis@22831 512 } // end: check which pages can be used for shared memory
simonis@22831 513
simonis@22831 514 query_multipage_support_end:
simonis@22831 515
stuefe@34647 516 trcVerbose("base page size (sysconf _SC_PAGESIZE): %s",
goetz@30198 517 describe_pagesize(g_multipage_support.pagesize));
stuefe@34647 518 trcVerbose("Data page size (C-Heap, bss, etc): %s",
goetz@30198 519 describe_pagesize(g_multipage_support.datapsize));
stuefe@34647 520 trcVerbose("Text page size: %s",
goetz@30198 521 describe_pagesize(g_multipage_support.textpsize));
stuefe@34647 522 trcVerbose("Thread stack page size (pthread): %s",
goetz@30198 523 describe_pagesize(g_multipage_support.pthr_stack_pagesize));
stuefe@34647 524 trcVerbose("Default shared memory page size: %s",
goetz@30198 525 describe_pagesize(g_multipage_support.shmpsize));
stuefe@34647 526 trcVerbose("Can use 64K pages dynamically with shared meory: %s",
goetz@30198 527 (g_multipage_support.can_use_64K_pages ? "yes" :"no"));
stuefe@34647 528 trcVerbose("Can use 16M pages dynamically with shared memory: %s",
goetz@30198 529 (g_multipage_support.can_use_16M_pages ? "yes" :"no"));
stuefe@34647 530 trcVerbose("Multipage error details: %d",
goetz@30198 531 g_multipage_support.error);
goetz@30198 532
goetz@30198 533 // sanity checks
simonis@42061 534 assert0(g_multipage_support.pagesize == 4*K);
simonis@42061 535 assert0(g_multipage_support.datapsize == 4*K || g_multipage_support.datapsize == 64*K);
simonis@42061 536 assert0(g_multipage_support.textpsize == 4*K || g_multipage_support.textpsize == 64*K);
goetz@30198 537 assert0(g_multipage_support.pthr_stack_pagesize == g_multipage_support.datapsize);
simonis@42061 538 assert0(g_multipage_support.shmpsize == 4*K || g_multipage_support.shmpsize == 64*K);
simonis@22831 539
stuefe@34647 540 }
simonis@22831 541
simonis@22831 542 void os::init_system_properties_values() {
goetz@23522 543
stuefe@34647 544 #define DEFAULT_LIBPATH "/lib:/usr/lib"
simonis@22831 545 #define EXTENSIONS_DIR "/lib/ext"
simonis@22831 546
goetz@23522 547 // Buffer that fits several sprintfs.
goetz@23522 548 // Note that the space for the trailing null is provided
goetz@23522 549 // by the nulls included by the sizeof operator.
goetz@23522 550 const size_t bufsize =
chegar@27562 551 MAX2((size_t)MAXPATHLEN, // For dll_dir & friends.
chegar@27562 552 (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR)); // extensions dir
goetz@23522 553 char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
goetz@23522 554
simonis@22831 555 // sysclasspath, java_home, dll_dir
goetz@23522 556 {
goetz@23522 557 char *pslash;
goetz@23522 558 os::jvm_path(buf, bufsize);
goetz@23522 559
goetz@23522 560 // Found the full path to libjvm.so.
goetz@23522 561 // Now cut the path to <java_home>/jre if we can.
stuefe@34647 562 pslash = strrchr(buf, '/');
stuefe@34647 563 if (pslash != NULL) {
stuefe@34647 564 *pslash = '\0'; // Get rid of /libjvm.so.
stuefe@34647 565 }
simonis@22831 566 pslash = strrchr(buf, '/');
simonis@22831 567 if (pslash != NULL) {
goetz@23522 568 *pslash = '\0'; // Get rid of /{client|server|hotspot}.
goetz@23522 569 }
goetz@23522 570 Arguments::set_dll_dir(buf);
goetz@23522 571
goetz@23522 572 if (pslash != NULL) {
simonis@22831 573 pslash = strrchr(buf, '/');
simonis@22831 574 if (pslash != NULL) {
erikj@42633 575 *pslash = '\0'; // Get rid of /lib.
simonis@22831 576 }
simonis@22831 577 }
goetz@23522 578 Arguments::set_java_home(buf);
goetz@23522 579 set_boot_path('/', ':');
goetz@23522 580 }
goetz@23522 581
goetz@23522 582 // Where to look for native libraries.
goetz@23522 583
goetz@23522 584 // On Aix we get the user setting of LIBPATH.
simonis@22831 585 // Eventually, all the library path setting will be done here.
goetz@23522 586 // Get the user setting of LIBPATH.
goetz@23522 587 const char *v = ::getenv("LIBPATH");
goetz@23522 588 const char *v_colon = ":";
goetz@23522 589 if (v == NULL) { v = ""; v_colon = ""; }
goetz@23522 590
goetz@23522 591 // Concatenate user and invariant part of ld_library_path.
goetz@23522 592 // That's +1 for the colon and +1 for the trailing '\0'.
goetz@23522 593 char *ld_library_path = (char *)NEW_C_HEAP_ARRAY(char, strlen(v) + 1 + sizeof(DEFAULT_LIBPATH) + 1, mtInternal);
goetz@23522 594 sprintf(ld_library_path, "%s%s" DEFAULT_LIBPATH, v, v_colon);
simonis@22831 595 Arguments::set_library_path(ld_library_path);
coleenp@27880 596 FREE_C_HEAP_ARRAY(char, ld_library_path);
goetz@23522 597
goetz@23522 598 // Extensions directories.
goetz@23522 599 sprintf(buf, "%s" EXTENSIONS_DIR, Arguments::get_java_home());
goetz@23522 600 Arguments::set_ext_dirs(buf);
simonis@22831 601
coleenp@27880 602 FREE_C_HEAP_ARRAY(char, buf);
goetz@23522 603
simonis@22831 604 #undef DEFAULT_LIBPATH
simonis@22831 605 #undef EXTENSIONS_DIR
simonis@22831 606 }
simonis@22831 607
simonis@22831 608 ////////////////////////////////////////////////////////////////////////////////
simonis@22831 609 // breakpoint support
simonis@22831 610
simonis@22831 611 void os::breakpoint() {
simonis@22831 612 BREAKPOINT;
simonis@22831 613 }
simonis@22831 614
simonis@22831 615 extern "C" void breakpoint() {
simonis@22831 616 // use debugger to set breakpoint here
simonis@22831 617 }
simonis@22831 618
simonis@22831 619 ////////////////////////////////////////////////////////////////////////////////
simonis@22831 620 // signal support
simonis@22831 621
simonis@22831 622 debug_only(static bool signal_sets_initialized = false);
dholmes@46507 623 static sigset_t unblocked_sigs, vm_sigs;
simonis@22831 624
simonis@22831 625 void os::Aix::signal_sets_init() {
simonis@22831 626 // Should also have an assertion stating we are still single-threaded.
simonis@22831 627 assert(!signal_sets_initialized, "Already initialized");
simonis@22831 628 // Fill in signals that are necessarily unblocked for all threads in
simonis@22831 629 // the VM. Currently, we unblock the following signals:
simonis@22831 630 // SHUTDOWN{1,2,3}_SIGNAL: for shutdown hooks support (unless over-ridden
simonis@22831 631 // by -Xrs (=ReduceSignalUsage));
simonis@22831 632 // BREAK_SIGNAL which is unblocked only by the VM thread and blocked by all
simonis@22831 633 // other threads. The "ReduceSignalUsage" boolean tells us not to alter
simonis@22831 634 // the dispositions or masks wrt these signals.
simonis@22831 635 // Programs embedding the VM that want to use the above signals for their
simonis@22831 636 // own purposes must, at this time, use the "-Xrs" option to prevent
simonis@22831 637 // interference with shutdown hooks and BREAK_SIGNAL thread dumping.
simonis@22831 638 // (See bug 4345157, and other related bugs).
simonis@22831 639 // In reality, though, unblocking these signals is really a nop, since
simonis@22831 640 // these signals are not blocked by default.
simonis@22831 641 sigemptyset(&unblocked_sigs);
simonis@22831 642 sigaddset(&unblocked_sigs, SIGILL);
simonis@22831 643 sigaddset(&unblocked_sigs, SIGSEGV);
simonis@22831 644 sigaddset(&unblocked_sigs, SIGBUS);
simonis@22831 645 sigaddset(&unblocked_sigs, SIGFPE);
simonis@22831 646 sigaddset(&unblocked_sigs, SIGTRAP);
simonis@22831 647 sigaddset(&unblocked_sigs, SR_signum);
simonis@22831 648
simonis@22831 649 if (!ReduceSignalUsage) {
coleenp@50761 650 if (!os::Posix::is_sig_ignored(SHUTDOWN1_SIGNAL)) {
simonis@22831 651 sigaddset(&unblocked_sigs, SHUTDOWN1_SIGNAL);
simonis@22831 652 }
coleenp@50761 653 if (!os::Posix::is_sig_ignored(SHUTDOWN2_SIGNAL)) {
simonis@22831 654 sigaddset(&unblocked_sigs, SHUTDOWN2_SIGNAL);
simonis@22831 655 }
coleenp@50761 656 if (!os::Posix::is_sig_ignored(SHUTDOWN3_SIGNAL)) {
simonis@22831 657 sigaddset(&unblocked_sigs, SHUTDOWN3_SIGNAL);
simonis@22831 658 }
simonis@22831 659 }
simonis@22831 660 // Fill in signals that are blocked by all but the VM thread.
simonis@22831 661 sigemptyset(&vm_sigs);
simonis@22831 662 if (!ReduceSignalUsage)
simonis@22831 663 sigaddset(&vm_sigs, BREAK_SIGNAL);
simonis@22831 664 debug_only(signal_sets_initialized = true);
simonis@22831 665 }
simonis@22831 666
simonis@22831 667 // These are signals that are unblocked while a thread is running Java.
simonis@22831 668 // (For some reason, they get blocked by default.)
simonis@22831 669 sigset_t* os::Aix::unblocked_signals() {
simonis@22831 670 assert(signal_sets_initialized, "Not initialized");
simonis@22831 671 return &unblocked_sigs;
simonis@22831 672 }
simonis@22831 673
simonis@22831 674 // These are the signals that are blocked while a (non-VM) thread is
simonis@22831 675 // running Java. Only the VM thread handles these signals.
simonis@22831 676 sigset_t* os::Aix::vm_signals() {
simonis@22831 677 assert(signal_sets_initialized, "Not initialized");
simonis@22831 678 return &vm_sigs;
simonis@22831 679 }
simonis@22831 680
simonis@22831 681 void os::Aix::hotspot_sigmask(Thread* thread) {
simonis@22831 682
simonis@22831 683 //Save caller's signal mask before setting VM signal mask
simonis@22831 684 sigset_t caller_sigmask;
simonis@22831 685 pthread_sigmask(SIG_BLOCK, NULL, &caller_sigmask);
simonis@22831 686
simonis@22831 687 OSThread* osthread = thread->osthread();
simonis@22831 688 osthread->set_caller_sigmask(caller_sigmask);
simonis@22831 689
simonis@22831 690 pthread_sigmask(SIG_UNBLOCK, os::Aix::unblocked_signals(), NULL);
simonis@22831 691
simonis@22831 692 if (!ReduceSignalUsage) {
simonis@22831 693 if (thread->is_VM_thread()) {
simonis@22831 694 // Only the VM thread handles BREAK_SIGNAL ...
simonis@22831 695 pthread_sigmask(SIG_UNBLOCK, vm_signals(), NULL);
simonis@22831 696 } else {
simonis@22831 697 // ... all other threads block BREAK_SIGNAL
simonis@22831 698 pthread_sigmask(SIG_BLOCK, vm_signals(), NULL);
simonis@22831 699 }
simonis@22831 700 }
simonis@22831 701 }
simonis@22831 702
simonis@22831 703 // retrieve memory information.
simonis@22831 704 // Returns false if something went wrong;
simonis@22831 705 // content of pmi undefined in this case.
simonis@22831 706 bool os::Aix::get_meminfo(meminfo_t* pmi) {
simonis@22831 707
simonis@22831 708 assert(pmi, "get_meminfo: invalid parameter");
simonis@22831 709
simonis@22831 710 memset(pmi, 0, sizeof(meminfo_t));
simonis@22831 711
simonis@22831 712 if (os::Aix::on_pase()) {
stuefe@34647 713 // On PASE, use the libo4 porting library.
stuefe@34647 714
stuefe@34647 715 unsigned long long virt_total = 0;
stuefe@34647 716 unsigned long long real_total = 0;
stuefe@34647 717 unsigned long long real_free = 0;
stuefe@34647 718 unsigned long long pgsp_total = 0;
stuefe@34647 719 unsigned long long pgsp_free = 0;
stuefe@34647 720 if (libo4::get_memory_info(&virt_total, &real_total, &real_free, &pgsp_total, &pgsp_free)) {
stuefe@34647 721 pmi->virt_total = virt_total;
stuefe@34647 722 pmi->real_total = real_total;
stuefe@34647 723 pmi->real_free = real_free;
stuefe@34647 724 pmi->pgsp_total = pgsp_total;
stuefe@34647 725 pmi->pgsp_free = pgsp_free;
stuefe@34647 726 return true;
stuefe@34647 727 }
simonis@22831 728 return false;
simonis@22831 729
simonis@22831 730 } else {
simonis@22831 731
simonis@22831 732 // On AIX, I use the (dynamically loaded) perfstat library to retrieve memory statistics
simonis@22831 733 // See:
simonis@22831 734 // http://publib.boulder.ibm.com/infocenter/systems/index.jsp
simonis@22831 735 // ?topic=/com.ibm.aix.basetechref/doc/basetrf1/perfstat_memtot.htm
simonis@22831 736 // http://publib.boulder.ibm.com/infocenter/systems/index.jsp
simonis@22831 737 // ?topic=/com.ibm.aix.files/doc/aixfiles/libperfstat.h.htm
simonis@22831 738
simonis@22831 739 perfstat_memory_total_t psmt;
simonis@22831 740 memset (&psmt, '\0', sizeof(psmt));
simonis@22831 741 const int rc = libperfstat::perfstat_memory_total(NULL, &psmt, sizeof(psmt), 1);
simonis@22831 742 if (rc == -1) {
stuefe@34647 743 trcVerbose("perfstat_memory_total() failed (errno=%d)", errno);
simonis@22831 744 assert(0, "perfstat_memory_total() failed");
simonis@22831 745 return false;
simonis@22831 746 }
simonis@22831 747
simonis@22831 748 assert(rc == 1, "perfstat_memory_total() - weird return code");
simonis@22831 749
simonis@22831 750 // excerpt from
simonis@22831 751 // http://publib.boulder.ibm.com/infocenter/systems/index.jsp
simonis@22831 752 // ?topic=/com.ibm.aix.files/doc/aixfiles/libperfstat.h.htm
simonis@22831 753 // The fields of perfstat_memory_total_t:
simonis@22831 754 // u_longlong_t virt_total Total virtual memory (in 4 KB pages).
simonis@22831 755 // u_longlong_t real_total Total real memory (in 4 KB pages).
simonis@22831 756 // u_longlong_t real_free Free real memory (in 4 KB pages).
simonis@22831 757 // u_longlong_t pgsp_total Total paging space (in 4 KB pages).
simonis@22831 758 // u_longlong_t pgsp_free Free paging space (in 4 KB pages).
simonis@22831 759
simonis@22831 760 pmi->virt_total = psmt.virt_total * 4096;
simonis@22831 761 pmi->real_total = psmt.real_total * 4096;
simonis@22831 762 pmi->real_free = psmt.real_free * 4096;
simonis@22831 763 pmi->pgsp_total = psmt.pgsp_total * 4096;
simonis@22831 764 pmi->pgsp_free = psmt.pgsp_free * 4096;
simonis@22831 765
simonis@22831 766 return true;
simonis@22831 767
simonis@22831 768 }
simonis@22831 769 } // end os::Aix::get_meminfo
simonis@22831 770
simonis@22831 771 //////////////////////////////////////////////////////////////////////////////
simonis@22831 772 // create new thread
simonis@22831 773
simonis@22831 774 // Thread start routine for all newly created threads
dholmes@38290 775 static void *thread_native_entry(Thread *thread) {
simonis@22831 776
simonis@22831 777 // find out my own stack dimensions
simonis@22831 778 {
simonis@22831 779 // actually, this should do exactly the same as thread->record_stack_base_and_size...
stuefe@46576 780 thread->set_stack_base(os::current_stack_base());
stuefe@46576 781 thread->set_stack_size(os::current_stack_size());
simonis@22831 782 }
simonis@22831 783
stuefe@34647 784 const pthread_t pthread_id = ::pthread_self();
stuefe@34647 785 const tid_t kernel_thread_id = ::thread_self();
stuefe@34647 786
stuefe@47681 787 LogTarget(Info, os, thread) lt;
stuefe@47681 788 if (lt.is_enabled()) {
stuefe@47681 789 address low_address = thread->stack_end();
stuefe@47681 790 address high_address = thread->stack_base();
stuefe@47681 791 lt.print("Thread is alive (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT
stuefe@47681 792 ", stack [" PTR_FORMAT " - " PTR_FORMAT " (" SIZE_FORMAT "k using %uk pages)).",
stuefe@47681 793 os::current_thread_id(), (uintx) kernel_thread_id, low_address, high_address,
stuefe@47681 794 (high_address - low_address) / K, os::Aix::query_pagesize(low_address) / K);
stuefe@47681 795 }
stuefe@34647 796
stuefe@34647 797 // Normally, pthread stacks on AIX live in the data segment (are allocated with malloc()
stuefe@34647 798 // by the pthread library). In rare cases, this may not be the case, e.g. when third-party
stuefe@34647 799 // tools hook pthread_create(). In this case, we may run into problems establishing
stuefe@34647 800 // guard pages on those stacks, because the stacks may reside in memory which is not
stuefe@34647 801 // protectable (shmated).
stuefe@34647 802 if (thread->stack_base() > ::sbrk(0)) {
stuefe@36379 803 log_warning(os, thread)("Thread stack not in data segment.");
stuefe@34647 804 }
stuefe@34647 805
simonis@22831 806 // Try to randomize the cache line index of hot stack frames.
simonis@22831 807 // This helps when threads of the same stack traces evict each other's
simonis@22831 808 // cache lines. The threads can be either from the same JVM instance, or
simonis@22831 809 // from different JVM instances. The benefit is especially true for
simonis@22831 810 // processors with hyperthreading technology.
simonis@22831 811
simonis@22831 812 static int counter = 0;
simonis@22831 813 int pid = os::current_process_id();
simonis@22831 814 alloca(((pid ^ counter++) & 7) * 128);
simonis@22831 815
dholmes@34633 816 thread->initialize_thread_current();
simonis@22831 817
simonis@22831 818 OSThread* osthread = thread->osthread();
simonis@22831 819
stuefe@34647 820 // Thread_id is pthread id.
stuefe@34647 821 osthread->set_thread_id(pthread_id);
stuefe@34647 822
stuefe@34647 823 // .. but keep kernel thread id too for diagnostics
stuefe@34647 824 osthread->set_kernel_thread_id(kernel_thread_id);
stuefe@34647 825
stuefe@34647 826 // Initialize signal mask for this thread.
simonis@22831 827 os::Aix::hotspot_sigmask(thread);
simonis@22831 828
stuefe@34647 829 // Initialize floating point control register.
simonis@22831 830 os::Aix::init_thread_fpu_state();
simonis@22831 831
simonis@22831 832 assert(osthread->get_state() == RUNNABLE, "invalid os thread state");
simonis@22831 833
stuefe@34647 834 // Call one more level start routine.
simonis@22831 835 thread->run();
simonis@22831 836
stuefe@36379 837 log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").",
stuefe@36379 838 os::current_thread_id(), (uintx) kernel_thread_id);
stuefe@34647 839
dholmes@38290 840 // If a thread has not deleted itself ("delete this") as part of its
dholmes@38290 841 // termination sequence, we have to ensure thread-local-storage is
dholmes@38290 842 // cleared before we actually terminate. No threads should ever be
dholmes@38290 843 // deleted asynchronously with respect to their termination.
dholmes@38290 844 if (Thread::current_or_null_safe() != NULL) {
dholmes@38290 845 assert(Thread::current_or_null_safe() == thread, "current thread is wrong");
dholmes@38290 846 thread->clear_thread_current();
dholmes@38290 847 }
dholmes@38290 848
simonis@22831 849 return 0;
simonis@22831 850 }
simonis@22831 851
rdurbin@41070 852 bool os::create_thread(Thread* thread, ThreadType thr_type,
rdurbin@41070 853 size_t req_stack_size) {
simonis@22831 854
simonis@22831 855 assert(thread->osthread() == NULL, "caller responsible");
simonis@22831 856
goetz@42905 857 // Allocate the OSThread object.
simonis@22831 858 OSThread* osthread = new OSThread(NULL, NULL);
simonis@22831 859 if (osthread == NULL) {
simonis@22831 860 return false;
simonis@22831 861 }
simonis@22831 862
goetz@42905 863 // Set the correct thread state.
simonis@22831 864 osthread->set_thread_type(thr_type);
simonis@22831 865
simonis@22831 866 // Initial state is ALLOCATED but not INITIALIZED
simonis@22831 867 osthread->set_state(ALLOCATED);
simonis@22831 868
simonis@22831 869 thread->set_osthread(osthread);
simonis@22831 870
goetz@42905 871 // Init thread attributes.
simonis@22831 872 pthread_attr_t attr;
simonis@22831 873 pthread_attr_init(&attr);
simonis@22831 874 guarantee(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0, "???");
simonis@22831 875
simonis@22831 876 // Make sure we run in 1:1 kernel-user-thread mode.
simonis@22831 877 if (os::Aix::on_aix()) {
simonis@22831 878 guarantee(pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) == 0, "???");
simonis@22831 879 guarantee(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0, "???");
goetz@42905 880 }
simonis@22831 881
simonis@22831 882 // Start in suspended state, and in os::thread_start, wake the thread up.
simonis@22831 883 guarantee(pthread_attr_setsuspendstate_np(&attr, PTHREAD_CREATE_SUSPENDED_NP) == 0, "???");
simonis@22831 884
goetz@42905 885 // Calculate stack size if it's not specified by caller.
rdurbin@41070 886 size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);
goetz@46823 887
stuefe@47681 888 // JDK-8187028: It was observed that on some configurations (4K backed thread stacks)
stuefe@47681 889 // the real thread stack size may be smaller than the requested stack size, by as much as 64K.
stuefe@47681 890 // This very much looks like a pthread lib error. As a workaround, increase the stack size
stuefe@47681 891 // by 64K for small thread stacks (arbitrarily choosen to be < 4MB)
stuefe@47681 892 if (stack_size < 4096 * K) {
stuefe@47681 893 stack_size += 64 * K;
stuefe@47681 894 }
stuefe@47681 895
goetz@46823 896 // On Aix, pthread_attr_setstacksize fails with huge values and leaves the
goetz@46823 897 // thread size in attr unchanged. If this is the minimal stack size as set
goetz@46823 898 // by pthread_attr_init this leads to crashes after thread creation. E.g. the
goetz@46823 899 // guard pages might not fit on the tiny stack created.
goetz@46823 900 int ret = pthread_attr_setstacksize(&attr, stack_size);
goetz@46823 901 if (ret != 0) {
goetz@46823 902 log_warning(os, thread)("The thread stack size specified is invalid: " SIZE_FORMAT "k",
goetz@46823 903 stack_size / K);
goetz@46823 904 }
simonis@22831 905
stuefe@47800 906 // Save some cycles and a page by disabling OS guard pages where we have our own
stuefe@47800 907 // VM guard pages (in java threads). For other threads, keep system default guard
stuefe@47800 908 // pages in place.
stuefe@47800 909 if (thr_type == java_thread || thr_type == compiler_thread) {
stuefe@47800 910 ret = pthread_attr_setguardsize(&attr, 0);
stuefe@47800 911 }
goetz@46823 912
goetz@46823 913 pthread_t tid = 0;
stuefe@36355 914 if (ret == 0) {
goetz@46823 915 ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
goetz@46823 916 }
goetz@46823 917
goetz@46823 918 if (ret == 0) {
goetz@46823 919 char buf[64];
stuefe@36355 920 log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ",
stuefe@36355 921 (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
stuefe@36355 922 } else {
goetz@46823 923 char buf[64];
stuefe@37113 924 log_warning(os, thread)("Failed to start thread - pthread_create failed (%d=%s) for attributes: %s.",
stuefe@37113 925 ret, os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
stuefe@36355 926 }
stuefe@36355 927
simonis@22831 928 pthread_attr_destroy(&attr);
simonis@22831 929
stuefe@36355 930 if (ret != 0) {
goetz@42905 931 // Need to clean up stuff we've allocated so far.
simonis@22831 932 thread->set_osthread(NULL);
simonis@22831 933 delete osthread;
simonis@22831 934 return false;
simonis@22831 935 }
simonis@22831 936
stuefe@34647 937 // OSThread::thread_id is the pthread id.
stuefe@34647 938 osthread->set_thread_id(tid);
simonis@22831 939
simonis@22831 940 return true;
simonis@22831 941 }
simonis@22831 942
simonis@22831 943 /////////////////////////////////////////////////////////////////////////////
simonis@22831 944 // attach existing thread
simonis@22831 945
simonis@22831 946 // bootstrap the main thread
simonis@22831 947 bool os::create_main_thread(JavaThread* thread) {
simonis@22831 948 assert(os::Aix::_main_thread == pthread_self(), "should be called inside main thread");
simonis@22831 949 return create_attached_thread(thread);
simonis@22831 950 }
simonis@22831 951
simonis@22831 952 bool os::create_attached_thread(JavaThread* thread) {
simonis@22831 953 #ifdef ASSERT
simonis@22831 954 thread->verify_not_published();
simonis@22831 955 #endif
simonis@22831 956
simonis@22831 957 // Allocate the OSThread object
simonis@22831 958 OSThread* osthread = new OSThread(NULL, NULL);
simonis@22831 959
simonis@22831 960 if (osthread == NULL) {
simonis@22831 961 return false;
simonis@22831 962 }
simonis@22831 963
stuefe@34647 964 const pthread_t pthread_id = ::pthread_self();
stuefe@34647 965 const tid_t kernel_thread_id = ::thread_self();
stuefe@34647 966
stuefe@34647 967 // OSThread::thread_id is the pthread id.
stuefe@34647 968 osthread->set_thread_id(pthread_id);
stuefe@34647 969
stuefe@34647 970 // .. but keep kernel thread id too for diagnostics
stuefe@34647 971 osthread->set_kernel_thread_id(kernel_thread_id);
simonis@22831 972
simonis@22831 973 // initialize floating point control register
simonis@22831 974 os::Aix::init_thread_fpu_state();
simonis@22831 975
simonis@22831 976 // Initial thread state is RUNNABLE
simonis@22831 977 osthread->set_state(RUNNABLE);
simonis@22831 978
simonis@22831 979 thread->set_osthread(osthread);
simonis@22831 980
simonis@22831 981 if (UseNUMA) {
simonis@22831 982 int lgrp_id = os::numa_get_group_id();
simonis@22831 983 if (lgrp_id != -1) {
simonis@22831 984 thread->set_lgrp_id(lgrp_id);
simonis@22831 985 }
simonis@22831 986 }
simonis@22831 987
simonis@22831 988 // initialize signal mask for this thread
simonis@22831 989 // and save the caller's signal mask
simonis@22831 990 os::Aix::hotspot_sigmask(thread);
simonis@22831 991
stuefe@36379 992 log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").",
stuefe@36379 993 os::current_thread_id(), (uintx) kernel_thread_id);
stuefe@36355 994
simonis@22831 995 return true;
simonis@22831 996 }
simonis@22831 997
simonis@22831 998 void os::pd_start_thread(Thread* thread) {
simonis@22831 999 int status = pthread_continue_np(thread->osthread()->pthread_id());
simonis@22831 1000 assert(status == 0, "thr_continue failed");
simonis@22831 1001 }
simonis@22831 1002
simonis@22831 1003 // Free OS resources related to the OSThread
simonis@22831 1004 void os::free_thread(OSThread* osthread) {
simonis@22831 1005 assert(osthread != NULL, "osthread not set");
simonis@22831 1006
dholmes@38290 1007 // We are told to free resources of the argument thread,
dholmes@38290 1008 // but we can only really operate on the current thread.
dholmes@38290 1009 assert(Thread::current()->osthread() == osthread,
dholmes@38290 1010 "os::free_thread but not current thread");
dholmes@38290 1011
dholmes@38290 1012 // Restore caller's signal mask
dholmes@38290 1013 sigset_t sigmask = osthread->caller_sigmask();
dholmes@38290 1014 pthread_sigmask(SIG_SETMASK, &sigmask, NULL);
simonis@22831 1015
simonis@22831 1016 delete osthread;
simonis@22831 1017 }
simonis@22831 1018
simonis@22831 1019 ////////////////////////////////////////////////////////////////////////////////
simonis@22831 1020 // time support
simonis@22831 1021
simonis@22831 1022 // Time since start-up in seconds to a fine granularity.
simonis@22831 1023 // Used by VMSelfDestructTimer and the MemProfiler.
simonis@22831 1024 double os::elapsedTime() {
simonis@22831 1025 return (double)(os::elapsed_counter()) * 0.000001;
simonis@22831 1026 }
simonis@22831 1027
simonis@22831 1028 jlong os::elapsed_counter() {
simonis@22831 1029 timeval time;
simonis@22831 1030 int status = gettimeofday(&time, NULL);
simonis@22831 1031 return jlong(time.tv_sec) * 1000 * 1000 + jlong(time.tv_usec) - initial_time_count;
simonis@22831 1032 }
simonis@22831 1033
simonis@22831 1034 jlong os::elapsed_frequency() {
simonis@22831 1035 return (1000 * 1000);
simonis@22831 1036 }
simonis@22831 1037
simonis@27668 1038 bool os::supports_vtime() { return true; }
simonis@22831 1039 bool os::enable_vtime() { return false; }
simonis@22831 1040 bool os::vtime_enabled() { return false; }
simonis@27668 1041
simonis@22831 1042 double os::elapsedVTime() {
simonis@27668 1043 struct rusage usage;
simonis@27668 1044 int retval = getrusage(RUSAGE_THREAD, &usage);
simonis@27668 1045 if (retval == 0) {
simonis@27668 1046 return usage.ru_utime.tv_sec + usage.ru_stime.tv_sec + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec) / (1000.0 * 1000);
simonis@27668 1047 } else {
simonis@27668 1048 // better than nothing, but not much
simonis@27668 1049 return elapsedTime();
simonis@27668 1050 }
simonis@22831 1051 }
simonis@22831 1052
simonis@22831 1053 jlong os::javaTimeMillis() {
simonis@22831 1054 timeval time;
simonis@22831 1055 int status = gettimeofday(&time, NULL);
simonis@22831 1056 assert(status != -1, "aix error at gettimeofday()");
simonis@22831 1057 return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
simonis@22831 1058 }
simonis@22831 1059
dfuchs@28737 1060 void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
dfuchs@28737 1061 timeval time;
dfuchs@28737 1062 int status = gettimeofday(&time, NULL);
dfuchs@28737 1063 assert(status != -1, "aix error at gettimeofday()");
dfuchs@28737 1064 seconds = jlong(time.tv_sec);
dfuchs@28737 1065 nanos = jlong(time.tv_usec) * 1000;
dfuchs@28737 1066 }
dfuchs@28737 1067
clanger@49260 1068 // We use mread_real_time here.
clanger@49260 1069 // On AIX: If the CPU has a time register, the result will be RTC_POWER and
clanger@49260 1070 // it has to be converted to real time. AIX documentations suggests to do
clanger@49260 1071 // this unconditionally, so we do it.
clanger@49260 1072 //
clanger@49260 1073 // See: https://www.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.basetrf2/read_real_time.htm
clanger@49260 1074 //
clanger@49260 1075 // On PASE: mread_real_time will always return RTC_POWER_PC data, so no
clanger@49260 1076 // conversion is necessary. However, mread_real_time will not return
clanger@49260 1077 // monotonic results but merely matches read_real_time. So we need a tweak
clanger@49260 1078 // to ensure monotonic results.
clanger@49260 1079 //
clanger@49260 1080 // For PASE no public documentation exists, just word by IBM
simonis@22831 1081 jlong os::javaTimeNanos() {
clanger@49260 1082 timebasestruct_t time;
clanger@49260 1083 int rc = mread_real_time(&time, TIMEBASE_SZ);
simonis@22831 1084 if (os::Aix::on_pase()) {
clanger@49260 1085 assert(rc == RTC_POWER, "expected time format RTC_POWER from mread_real_time in PASE");
clanger@49260 1086 jlong now = jlong(time.tb_high) * NANOSECS_PER_SEC + jlong(time.tb_low);
clanger@49260 1087 jlong prev = max_real_time;
clanger@49260 1088 if (now <= prev) {
clanger@49260 1089 return prev; // same or retrograde time;
clanger@49260 1090 }
clanger@49260 1091 jlong obsv = Atomic::cmpxchg(now, &max_real_time, prev);
clanger@49260 1092 assert(obsv >= prev, "invariant"); // Monotonicity
clanger@49260 1093 // If the CAS succeeded then we're done and return "now".
clanger@49260 1094 // If the CAS failed and the observed value "obsv" is >= now then
clanger@49260 1095 // we should return "obsv". If the CAS failed and now > obsv > prv then
clanger@49260 1096 // some other thread raced this thread and installed a new value, in which case
clanger@49260 1097 // we could either (a) retry the entire operation, (b) retry trying to install now
clanger@49260 1098 // or (c) just return obsv. We use (c). No loop is required although in some cases
clanger@49260 1099 // we might discard a higher "now" value in deference to a slightly lower but freshly
clanger@49260 1100 // installed obsv value. That's entirely benign -- it admits no new orderings compared
clanger@49260 1101 // to (a) or (b) -- and greatly reduces coherence traffic.
clanger@49260 1102 // We might also condition (c) on the magnitude of the delta between obsv and now.
clanger@49260 1103 // Avoiding excessive CAS operations to hot RW locations is critical.
clanger@49260 1104 // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate
clanger@49260 1105 return (prev == obsv) ? now : obsv;
goetz@28187 1106 } else {
clanger@49260 1107 if (rc != RTC_POWER) {
simonis@22831 1108 rc = time_base_to_time(&time, TIMEBASE_SZ);
clanger@49260 1109 assert(rc != -1, "error calling time_base_to_time()");
simonis@22831 1110 }
clanger@49260 1111 return jlong(time.tb_high) * NANOSECS_PER_SEC + jlong(time.tb_low);
simonis@22831 1112 }
simonis@22831 1113 }
simonis@22831 1114
simonis@22831 1115 void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
simonis@23213 1116 info_ptr->max_value = ALL_64_BITS;
simonis@23213 1117 // mread_real_time() is monotonic (see 'os::javaTimeNanos()')
simonis@23213 1118 info_ptr->may_skip_backward = false;
simonis@23213 1119 info_ptr->may_skip_forward = false;
simonis@22831 1120 info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time
simonis@22831 1121 }
simonis@22831 1122
simonis@22831 1123 // Return the real, user, and system times in seconds from an
simonis@22831 1124 // arbitrary fixed point in the past.
simonis@22831 1125 bool os::getTimesSecs(double* process_real_time,
simonis@22831 1126 double* process_user_time,
simonis@22831 1127 double* process_system_time) {
goetz@22867 1128 struct tms ticks;
goetz@22867 1129 clock_t real_ticks = times(&ticks);
goetz@22867 1130
goetz@22867 1131 if (real_ticks == (clock_t) (-1)) {
goetz@22867 1132 return false;
goetz@22867 1133 } else {
goetz@22867 1134 double ticks_per_second = (double) clock_tics_per_sec;
goetz@22867 1135 *process_user_time = ((double) ticks.tms_utime) / ticks_per_second;
goetz@22867 1136 *process_system_time = ((double) ticks.tms_stime) / ticks_per_second;
goetz@22867 1137 *process_real_time = ((double) real_ticks) / ticks_per_second;
goetz@22867 1138
goetz@22867 1139 return true;
goetz@22867 1140 }
simonis@22831 1141 }
simonis@22831 1142
simonis@22831 1143 char * os::local_time_string(char *buf, size_t buflen) {
simonis@22831 1144 struct tm t;
simonis@22831 1145 time_t long_time;
simonis@22831 1146 time(&long_time);
simonis@22831 1147 localtime_r(&long_time, &t);
simonis@22831 1148 jio_snprintf(buf, buflen, "%d-%02d-%02d %02d:%02d:%02d",
simonis@22831 1149 t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
simonis@22831 1150 t.tm_hour, t.tm_min, t.tm_sec);
simonis@22831 1151 return buf;
simonis@22831 1152 }
simonis@22831 1153
simonis@22831 1154 struct tm* os::localtime_pd(const time_t* clock, struct tm* res) {
simonis@22831 1155 return localtime_r(clock, res);
simonis@22831 1156 }
simonis@22831 1157
simonis@22831 1158 ////////////////////////////////////////////////////////////////////////////////
simonis@22831 1159 // runtime exit support
simonis@22831 1160
simonis@22831 1161 // Note: os::shutdown() might be called very early during initialization, or
simonis@22831 1162 // called from signal handler. Before adding something to os::shutdown(), make
simonis@22831 1163 // sure it is async-safe and can handle partially initialized VM.
simonis@22831 1164 void os::shutdown() {
simonis@22831 1165
simonis@22831 1166 // allow PerfMemory to attempt cleanup of any persistent resources
simonis@22831 1167 perfMemory_exit();
simonis@22831 1168
simonis@22831 1169 // needs to remove object in file system
simonis@22831 1170 AttachListener::abort();
simonis@22831 1171
simonis@22831 1172 // flush buffered output, finish log files
simonis@22831 1173 ostream_abort();
simonis@22831 1174
simonis@22831 1175 // Check for abort hook
simonis@22831 1176 abort_hook_t abort_hook = Arguments::abort_hook();
simonis@22831 1177 if (abort_hook != NULL) {
simonis@22831 1178 abort_hook();
simonis@22831 1179 }
simonis@22831 1180 }
simonis@22831 1181
simonis@22831 1182 // Note: os::abort() might be called very early during initialization, or
simonis@22831 1183 // called from signal handler. Before adding something to os::abort(), make
simonis@22831 1184 // sure it is async-safe and can handle partially initialized VM.
stuefe@35077 1185 void os::abort(bool dump_core, void* siginfo, const void* context) {
simonis@22831 1186 os::shutdown();
simonis@22831 1187 if (dump_core) {
simonis@22831 1188 #ifndef PRODUCT
simonis@22831 1189 fdStream out(defaultStream::output_fd());
simonis@22831 1190 out.print_raw("Current thread is ");
simonis@22831 1191 char buf[16];
simonis@22831 1192 jio_snprintf(buf, sizeof(buf), UINTX_FORMAT, os::current_thread_id());
simonis@22831 1193 out.print_raw_cr(buf);
simonis@22831 1194 out.print_raw_cr("Dumping core ...");
simonis@22831 1195 #endif
simonis@22831 1196 ::abort(); // dump core
simonis@22831 1197 }
simonis@22831 1198
simonis@22831 1199 ::exit(1);
simonis@22831 1200 }
simonis@22831 1201
simonis@22831 1202 // Die immediately, no exit hook, no abort hook, no cleanup.
simonis@22831 1203 void os::die() {
simonis@22831 1204 ::abort();
simonis@22831 1205 }
simonis@22831 1206
simonis@22831 1207 // This method is a copy of JDK's sysGetLastErrorString
simonis@22831 1208 // from src/solaris/hpi/src/system_md.c
simonis@22831 1209
simonis@22831 1210 size_t os::lasterror(char *buf, size_t len) {
goetz@28187 1211 if (errno == 0) return 0;
simonis@22831 1212
stuefe@37113 1213 const char *s = os::strerror(errno);
simonis@22831 1214 size_t n = ::strlen(s);
simonis@22831 1215 if (n >= len) {
simonis@22831 1216 n = len - 1;
simonis@22831 1217 }
simonis@22831 1218 ::strncpy(buf, s, n);
simonis@22831 1219 buf[n] = '\0';
simonis@22831 1220 return n;
simonis@22831 1221 }
simonis@22831 1222
stuefe@34647 1223 intx os::current_thread_id() {
stuefe@34647 1224 return (intx)pthread_self();
stuefe@34647 1225 }
goetz@28187 1226
simonis@22831 1227 int os::current_process_id() {
stuefe@34647 1228 return getpid();
simonis@22831 1229 }
simonis@22831 1230
simonis@22831 1231 // DLL functions
simonis@22831 1232
simonis@22831 1233 const char* os::dll_file_extension() { return ".so"; }
simonis@22831 1234
simonis@22831 1235 // This must be hard coded because it's the system's temporary
simonis@22831 1236 // directory not the java application's temp directory, ala java.io.tmpdir.
simonis@22831 1237 const char* os::get_temp_directory() { return "/tmp"; }
simonis@22831 1238
simonis@22831 1239 // Check if addr is inside libjvm.so.
simonis@22831 1240 bool os::address_is_in_vm(address addr) {
simonis@22831 1241
simonis@22831 1242 // Input could be a real pc or a function pointer literal. The latter
simonis@22831 1243 // would be a function descriptor residing in the data segment of a module.
stuefe@33743 1244 loaded_module_t lm;
stuefe@33743 1245 if (LoadedLibraries::find_for_text_address(addr, &lm) != NULL) {
stuefe@33743 1246 return lm.is_in_vm;
stuefe@33743 1247 } else if (LoadedLibraries::find_for_data_address(addr, &lm) != NULL) {
stuefe@33743 1248 return lm.is_in_vm;
simonis@22831 1249 } else {
stuefe@33743 1250 return false;
stuefe@33743 1251 }
stuefe@33743 1252
simonis@22831 1253 }
simonis@22831 1254
simonis@22831 1255 // Resolve an AIX function descriptor literal to a code pointer.
simonis@22831 1256 // If the input is a valid code pointer to a text segment of a loaded module,
simonis@22831 1257 // it is returned unchanged.
simonis@22831 1258 // If the input is a valid AIX function descriptor, it is resolved to the
simonis@22831 1259 // code entry point.
simonis@22831 1260 // If the input is neither a valid function descriptor nor a valid code pointer,
simonis@22831 1261 // NULL is returned.
simonis@22831 1262 static address resolve_function_descriptor_to_code_pointer(address p) {
simonis@22831 1263
stuefe@33743 1264 if (LoadedLibraries::find_for_text_address(p, NULL) != NULL) {
stuefe@33743 1265 // It is a real code pointer.
simonis@22831 1266 return p;
stuefe@33743 1267 } else if (LoadedLibraries::find_for_data_address(p, NULL) != NULL) {
stuefe@33743 1268 // Pointer to data segment, potential function descriptor.
stuefe@33743 1269 address code_entry = (address)(((FunctionDescriptor*)p)->entry());
stuefe@33743 1270 if (LoadedLibraries::find_for_text_address(code_entry, NULL) != NULL) {
stuefe@33743 1271 // It is a function descriptor.
stuefe@33743 1272 return code_entry;
simonis@22831 1273 }
simonis@22831 1274 }
stuefe@33743 1275
simonis@22831 1276 return NULL;
simonis@22831 1277 }
simonis@22831 1278
simonis@22831 1279 bool os::dll_address_to_function_name(address addr, char *buf,
bdelsart@31352 1280 int buflen, int *offset,
bdelsart@31352 1281 bool demangle) {
simonis@22831 1282 if (offset) {
simonis@22831 1283 *offset = -1;
simonis@22831 1284 }
goetz@28187 1285 // Buf is not optional, but offset is optional.
goetz@28187 1286 assert(buf != NULL, "sanity check");
goetz@28187 1287 buf[0] = '\0';
simonis@22831 1288
simonis@22831 1289 // Resolve function ptr literals first.
simonis@22831 1290 addr = resolve_function_descriptor_to_code_pointer(addr);
simonis@22831 1291 if (!addr) {
simonis@22831 1292 return false;
simonis@22831 1293 }
simonis@22831 1294
stuefe@35515 1295 return AixSymbols::get_function_name(addr, buf, buflen, offset, NULL, demangle);
simonis@22831 1296 }
simonis@22831 1297
simonis@22831 1298 bool os::dll_address_to_library_name(address addr, char* buf,
simonis@22831 1299 int buflen, int* offset) {
simonis@22831 1300 if (offset) {
simonis@22831 1301 *offset = -1;
simonis@22831 1302 }
goetz@28187 1303 // Buf is not optional, but offset is optional.
goetz@28187 1304 assert(buf != NULL, "sanity check");
goetz@28187 1305 buf[0] = '\0';
simonis@22831 1306
simonis@22831 1307 // Resolve function ptr literals first.
simonis@22831 1308 addr = resolve_function_descriptor_to_code_pointer(addr);
simonis@22831 1309 if (!addr) {
simonis@22831 1310 return false;
simonis@22831 1311 }
simonis@22831 1312
stuefe@35515 1313 return AixSymbols::get_module_name(addr, buf, buflen);
simonis@22831 1314 }
simonis@22831 1315
simonis@22831 1316 // Loads .dll/.so and in case of error it checks if .dll/.so was built
goetz@28187 1317 // for the same architecture as Hotspot is running on.
simonis@22831 1318 void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
simonis@22831 1319
simonis@22831 1320 if (ebuf && ebuflen > 0) {
simonis@22831 1321 ebuf[0] = '\0';
simonis@22831 1322 ebuf[ebuflen - 1] = '\0';
simonis@22831 1323 }
simonis@22831 1324
simonis@22831 1325 if (!filename || strlen(filename) == 0) {
simonis@22831 1326 ::strncpy(ebuf, "dll_load: empty filename specified", ebuflen - 1);
simonis@22831 1327 return NULL;
simonis@22831 1328 }
simonis@22831 1329
simonis@22831 1330 // RTLD_LAZY is currently not implemented. The dl is loaded immediately with all its dependants.
simonis@22831 1331 void * result= ::dlopen(filename, RTLD_LAZY);
simonis@22831 1332 if (result != NULL) {
simonis@22831 1333 // Reload dll cache. Don't do this in signal handling.
simonis@22831 1334 LoadedLibraries::reload();
simonis@22831 1335 return result;
simonis@22831 1336 } else {
simonis@22831 1337 // error analysis when dlopen fails
simonis@22831 1338 const char* const error_report = ::dlerror();
simonis@22831 1339 if (error_report && ebuf && ebuflen > 0) {
simonis@22831 1340 snprintf(ebuf, ebuflen - 1, "%s, LIBPATH=%s, LD_LIBRARY_PATH=%s : %s",
simonis@22831 1341 filename, ::getenv("LIBPATH"), ::getenv("LD_LIBRARY_PATH"), error_report);
simonis@22831 1342 }
simonis@22831 1343 }
simonis@22831 1344 return NULL;
simonis@22831 1345 }
simonis@22831 1346
simonis@22831 1347 void* os::dll_lookup(void* handle, const char* name) {
simonis@22831 1348 void* res = dlsym(handle, name);
simonis@22831 1349 return res;
simonis@22831 1350 }
simonis@22831 1351
simonis@22880 1352 void* os::get_default_process_handle() {
simonis@22880 1353 return (void*)::dlopen(NULL, RTLD_LAZY);
simonis@22880 1354 }
simonis@22880 1355
simonis@22831 1356 void os::print_dll_info(outputStream *st) {
simonis@22831 1357 st->print_cr("Dynamic libraries:");
simonis@22831 1358 LoadedLibraries::print(st);
simonis@22831 1359 }
simonis@22831 1360
coleenp@31963 1361 void os::get_summary_os_info(char* buf, size_t buflen) {
coleenp@31963 1362 // There might be something more readable than uname results for AIX.
coleenp@31963 1363 struct utsname name;
coleenp@31963 1364 uname(&name);
coleenp@31963 1365 snprintf(buf, buflen, "%s %s", name.release, name.version);
coleenp@31963 1366 }
coleenp@31963 1367
mdoerr@50709 1368 int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
mdoerr@50709 1369 // Not yet implemented.
mdoerr@50709 1370 return 0;
mdoerr@50709 1371 }
mdoerr@50709 1372
mdoerr@50709 1373 void os::print_os_info_brief(outputStream* st) {
mdoerr@50709 1374 uint32_t ver = os::Aix::os_version();
mdoerr@50709 1375 st->print_cr("AIX kernel version %u.%u.%u.%u",
mdoerr@50709 1376 (ver >> 24) & 0xFF, (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
mdoerr@50709 1377
mdoerr@50709 1378 os::Posix::print_uname_info(st);
mdoerr@50709 1379
mdoerr@50709 1380 // Linux uses print_libversion_info(st); here.
mdoerr@50709 1381 }
mdoerr@50709 1382
simonis@22831 1383 void os::print_os_info(outputStream* st) {
simonis@22831 1384 st->print("OS:");
simonis@22831 1385
simonis@22831 1386 st->print("uname:");
simonis@22831 1387 struct utsname name;
simonis@22831 1388 uname(&name);
simonis@22831 1389 st->print(name.sysname); st->print(" ");
simonis@22831 1390 st->print(name.nodename); st->print(" ");
simonis@22831 1391 st->print(name.release); st->print(" ");
simonis@22831 1392 st->print(name.version); st->print(" ");
simonis@22831 1393 st->print(name.machine);
simonis@22831 1394 st->cr();
simonis@22831 1395
mdoerr@35063 1396 uint32_t ver = os::Aix::os_version();
mdoerr@35063 1397 st->print_cr("AIX kernel version %u.%u.%u.%u",
mdoerr@35063 1398 (ver >> 24) & 0xFF, (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
mdoerr@35063 1399
mikael@46508 1400 os::Posix::print_rlimit_info(st);
simonis@22831 1401
simonis@22831 1402 // load average
simonis@22831 1403 st->print("load average:");
simonis@22831 1404 double loadavg[3] = {-1.L, -1.L, -1.L};
simonis@22831 1405 os::loadavg(loadavg, 3);
simonis@22831 1406 st->print("%0.02f %0.02f %0.02f", loadavg[0], loadavg[1], loadavg[2]);
simonis@22831 1407 st->cr();
stuefe@34647 1408
stuefe@34647 1409 // print wpar info
stuefe@34647 1410 libperfstat::wparinfo_t wi;
stuefe@34647 1411 if (libperfstat::get_wparinfo(&wi)) {
stuefe@34647 1412 st->print_cr("wpar info");
stuefe@34647 1413 st->print_cr("name: %s", wi.name);
stuefe@34647 1414 st->print_cr("id: %d", wi.wpar_id);
stuefe@34647 1415 st->print_cr("type: %s", (wi.app_wpar ? "application" : "system"));
stuefe@34647 1416 }
stuefe@34647 1417
stuefe@34647 1418 // print partition info
stuefe@34647 1419 libperfstat::partitioninfo_t pi;
stuefe@34647 1420 if (libperfstat::get_partitioninfo(&pi)) {
stuefe@34647 1421 st->print_cr("partition info");
stuefe@34647 1422 st->print_cr(" name: %s", pi.name);
stuefe@34647 1423 }
stuefe@34647 1424
simonis@22831 1425 }
simonis@22831 1426
simonis@22831 1427 void os::print_memory_info(outputStream* st) {
simonis@22831 1428
simonis@22831 1429 st->print_cr("Memory:");
simonis@22831 1430
stuefe@34647 1431 st->print_cr(" Base page size (sysconf _SC_PAGESIZE): %s",
stuefe@34647 1432 describe_pagesize(g_multipage_support.pagesize));
stuefe@34647 1433 st->print_cr(" Data page size (C-Heap, bss, etc): %s",
stuefe@34647 1434 describe_pagesize(g_multipage_support.datapsize));
stuefe@34647 1435 st->print_cr(" Text page size: %s",
stuefe@34647 1436 describe_pagesize(g_multipage_support.textpsize));
stuefe@34647 1437 st->print_cr(" Thread stack page size (pthread): %s",
stuefe@34647 1438 describe_pagesize(g_multipage_support.pthr_stack_pagesize));
goetz@30198 1439 st->print_cr(" Default shared memory page size: %s",
goetz@30198 1440 describe_pagesize(g_multipage_support.shmpsize));
goetz@30198 1441 st->print_cr(" Can use 64K pages dynamically with shared meory: %s",
goetz@30198 1442 (g_multipage_support.can_use_64K_pages ? "yes" :"no"));
goetz@30198 1443 st->print_cr(" Can use 16M pages dynamically with shared memory: %s",
goetz@30198 1444 (g_multipage_support.can_use_16M_pages ? "yes" :"no"));
stuefe@34647 1445 st->print_cr(" Multipage error: %d",
stuefe@34647 1446 g_multipage_support.error);
stuefe@34647 1447 st->cr();
stuefe@34647 1448 st->print_cr(" os::vm_page_size: %s", describe_pagesize(os::vm_page_size()));
simonis@22831 1449
simonis@22831 1450 // print out LDR_CNTRL because it affects the default page sizes
simonis@22831 1451 const char* const ldr_cntrl = ::getenv("LDR_CNTRL");
simonis@22831 1452 st->print_cr(" LDR_CNTRL=%s.", ldr_cntrl ? ldr_cntrl : "<unset>");
simonis@22831 1453
stuefe@34647 1454 // Print out EXTSHM because it is an unsupported setting.
simonis@22831 1455 const char* const extshm = ::getenv("EXTSHM");
simonis@22831 1456 st->print_cr(" EXTSHM=%s.", extshm ? extshm : "<unset>");
goetz@30198 1457 if ( (strcmp(extshm, "on") == 0) || (strcmp(extshm, "ON") == 0) ) {
goetz@30198 1458 st->print_cr(" *** Unsupported! Please remove EXTSHM from your environment! ***");
goetz@30198 1459 }
simonis@22831 1460
stuefe@34647 1461 // Print out AIXTHREAD_GUARDPAGES because it affects the size of pthread stacks.
stuefe@34647 1462 const char* const aixthread_guardpages = ::getenv("AIXTHREAD_GUARDPAGES");
stuefe@34647 1463 st->print_cr(" AIXTHREAD_GUARDPAGES=%s.",
stuefe@34647 1464 aixthread_guardpages ? aixthread_guardpages : "<unset>");
stuefe@50558 1465 st->cr();
stuefe@34647 1466
simonis@22831 1467 os::Aix::meminfo_t mi;
simonis@22831 1468 if (os::Aix::get_meminfo(&mi)) {
simonis@22831 1469 if (os::Aix::on_aix()) {
stuefe@34647 1470 st->print_cr("physical total : " SIZE_FORMAT, mi.real_total);
stuefe@34647 1471 st->print_cr("physical free : " SIZE_FORMAT, mi.real_free);
stuefe@34647 1472 st->print_cr("swap total : " SIZE_FORMAT, mi.pgsp_total);
stuefe@34647 1473 st->print_cr("swap free : " SIZE_FORMAT, mi.pgsp_free);
simonis@22831 1474 } else {
stuefe@34647 1475 // PASE - Numbers are result of QWCRSSTS; they mean:
stuefe@34647 1476 // real_total: Sum of all system pools
stuefe@34647 1477 // real_free: always 0
stuefe@34647 1478 // pgsp_total: we take the size of the system ASP
stuefe@34647 1479 // pgsp_free: size of system ASP times percentage of system ASP unused
stuefe@34647 1480 st->print_cr("physical total : " SIZE_FORMAT, mi.real_total);
stuefe@34647 1481 st->print_cr("system asp total : " SIZE_FORMAT, mi.pgsp_total);
clanger@49159 1482 st->print_cr("%% system asp used : %.2f",
stuefe@34647 1483 mi.pgsp_total ? (100.0f * (mi.pgsp_total - mi.pgsp_free) / mi.pgsp_total) : -1.0f);
simonis@22831 1484 }
stuefe@34647 1485 }
stuefe@34647 1486 st->cr();
stuefe@34647 1487
stuefe@50558 1488 // Print program break.
stuefe@50558 1489 st->print_cr("Program break at VM startup: " PTR_FORMAT ".", p2i(g_brk_at_startup));
stuefe@50558 1490 address brk_now = (address)::sbrk(0);
stuefe@50558 1491 if (brk_now != (address)-1) {
stuefe@50558 1492 st->print_cr("Program break now : " PTR_FORMAT " (distance: " SIZE_FORMAT "k).",
stuefe@50558 1493 p2i(brk_now), (size_t)((brk_now - g_brk_at_startup) / K));
stuefe@50558 1494 }
stuefe@50558 1495 st->print_cr("MaxExpectedDataSegmentSize : " SIZE_FORMAT "k.", MaxExpectedDataSegmentSize / K);
stuefe@50558 1496 st->cr();
stuefe@50558 1497
stuefe@34647 1498 // Print segments allocated with os::reserve_memory.
stuefe@34647 1499 st->print_cr("internal virtual memory regions used by vm:");
stuefe@34647 1500 vmembk_print_on(st);
simonis@22831 1501 }
simonis@22831 1502
coleenp@31963 1503 // Get a string for the cpuinfo that is a summary of the cpu type
coleenp@31963 1504 void os::get_summary_cpu_info(char* buf, size_t buflen) {
clanger@49206 1505 // read _system_configuration.version
clanger@49206 1506 switch (_system_configuration.version) {
clanger@49206 1507 case PV_8:
clanger@49206 1508 strncpy(buf, "Power PC 8", buflen);
clanger@49206 1509 break;
clanger@49206 1510 case PV_7:
clanger@49206 1511 strncpy(buf, "Power PC 7", buflen);
clanger@49206 1512 break;
clanger@49206 1513 case PV_6_1:
clanger@49206 1514 strncpy(buf, "Power PC 6 DD1.x", buflen);
clanger@49206 1515 break;
clanger@49206 1516 case PV_6:
clanger@49206 1517 strncpy(buf, "Power PC 6", buflen);
clanger@49206 1518 break;
clanger@49206 1519 case PV_5:
clanger@49206 1520 strncpy(buf, "Power PC 5", buflen);
clanger@49206 1521 break;
clanger@49206 1522 case PV_5_2:
clanger@49206 1523 strncpy(buf, "Power PC 5_2", buflen);
clanger@49206 1524 break;
clanger@49206 1525 case PV_5_3:
clanger@49206 1526 strncpy(buf, "Power PC 5_3", buflen);
clanger@49206 1527 break;
clanger@49206 1528 case PV_5_Compat:
clanger@49206 1529 strncpy(buf, "PV_5_Compat", buflen);
clanger@49206 1530 break;
clanger@49206 1531 case PV_6_Compat:
clanger@49206 1532 strncpy(buf, "PV_6_Compat", buflen);
clanger@49206 1533 break;
clanger@49206 1534 case PV_7_Compat:
clanger@49206 1535 strncpy(buf, "PV_7_Compat", buflen);
clanger@49206 1536 break;
clanger@49206 1537 case PV_8_Compat:
clanger@49206 1538 strncpy(buf, "PV_8_Compat", buflen);
clanger@49206 1539 break;
clanger@49206 1540 default:
clanger@49206 1541 strncpy(buf, "unknown", buflen);
coleenp@31963 1542 }
coleenp@31963 1543 }
coleenp@31963 1544
coleenp@31356 1545 void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
clanger@49206 1546 // Nothing to do beyond of what os::print_cpu_info() does.
simonis@22831 1547 }
simonis@22831 1548
simonis@22831 1549 static void print_signal_handler(outputStream* st, int sig,
simonis@22831 1550 char* buf, size_t buflen);
simonis@22831 1551
simonis@22831 1552 void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
simonis@22831 1553 st->print_cr("Signal Handlers:");
simonis@22831 1554 print_signal_handler(st, SIGSEGV, buf, buflen);
simonis@22831 1555 print_signal_handler(st, SIGBUS , buf, buflen);
simonis@22831 1556 print_signal_handler(st, SIGFPE , buf, buflen);
simonis@22831 1557 print_signal_handler(st, SIGPIPE, buf, buflen);
simonis@22831 1558 print_signal_handler(st, SIGXFSZ, buf, buflen);
simonis@22831 1559 print_signal_handler(st, SIGILL , buf, buflen);
simonis@22831 1560 print_signal_handler(st, SR_signum, buf, buflen);
simonis@22831 1561 print_signal_handler(st, SHUTDOWN1_SIGNAL, buf, buflen);
simonis@22831 1562 print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen);
simonis@22831 1563 print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen);
simonis@22831 1564 print_signal_handler(st, BREAK_SIGNAL, buf, buflen);
simonis@22831 1565 print_signal_handler(st, SIGTRAP, buf, buflen);
stuefe@43463 1566 // We also want to know if someone else adds a SIGDANGER handler because
stuefe@43463 1567 // that will interfere with OOM killling.
simonis@22831 1568 print_signal_handler(st, SIGDANGER, buf, buflen);
simonis@22831 1569 }
simonis@22831 1570
simonis@22831 1571 static char saved_jvm_path[MAXPATHLEN] = {0};
simonis@22831 1572
goetz@28187 1573 // Find the full path to the current module, libjvm.so.
simonis@22831 1574 void os::jvm_path(char *buf, jint buflen) {
simonis@22831 1575 // Error checking.
simonis@22831 1576 if (buflen < MAXPATHLEN) {
simonis@22831 1577 assert(false, "must use a large-enough buffer");
simonis@22831 1578 buf[0] = '\0';
simonis@22831 1579 return;
simonis@22831 1580 }
simonis@22831 1581 // Lazy resolve the path to current module.
simonis@22831 1582 if (saved_jvm_path[0] != 0) {
simonis@22831 1583 strcpy(buf, saved_jvm_path);
simonis@22831 1584 return;
simonis@22831 1585 }
simonis@22831 1586
simonis@22831 1587 Dl_info dlinfo;
simonis@22831 1588 int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo);
simonis@22831 1589 assert(ret != 0, "cannot locate libjvm");
stuefe@46331 1590 char* rp = os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen);
simonis@22831 1591 assert(rp != NULL, "error in realpath(): maybe the 'path' argument is too long?");
simonis@22831 1592
stuefe@46524 1593 if (Arguments::sun_java_launcher_is_altjvm()) {
stuefe@46524 1594 // Support for the java launcher's '-XXaltjvm=<path>' option. Typical
stuefe@46524 1595 // value for buf is "<JAVA_HOME>/jre/lib/<vmtype>/libjvm.so".
stuefe@46524 1596 // If "/jre/lib/" appears at the right place in the string, then
stuefe@46524 1597 // assume we are installed in a JDK and we're done. Otherwise, check
stuefe@46524 1598 // for a JAVA_HOME environment variable and fix up the path so it
stuefe@46524 1599 // looks like libjvm.so is installed there (append a fake suffix
stuefe@46524 1600 // hotspot/libjvm.so).
stuefe@46524 1601 const char *p = buf + strlen(buf) - 1;
stuefe@46524 1602 for (int count = 0; p > buf && count < 4; ++count) {
stuefe@46524 1603 for (--p; p > buf && *p != '/'; --p)
stuefe@46524 1604 /* empty */ ;
stuefe@46524 1605 }
stuefe@46524 1606
stuefe@46524 1607 if (strncmp(p, "/jre/lib/", 9) != 0) {
stuefe@46524 1608 // Look for JAVA_HOME in the environment.
stuefe@46524 1609 char* java_home_var = ::getenv("JAVA_HOME");
stuefe@46524 1610 if (java_home_var != NULL && java_home_var[0] != 0) {
stuefe@46524 1611 char* jrelib_p;
stuefe@46524 1612 int len;
stuefe@46524 1613
stuefe@46524 1614 // Check the current module name "libjvm.so".
stuefe@46524 1615 p = strrchr(buf, '/');
stuefe@46524 1616 if (p == NULL) {
stuefe@46524 1617 return;
stuefe@46524 1618 }
stuefe@46524 1619 assert(strstr(p, "/libjvm") == p, "invalid library name");
stuefe@46524 1620
stuefe@46524 1621 rp = os::Posix::realpath(java_home_var, buf, buflen);
stuefe@46524 1622 if (rp == NULL) {
stuefe@46524 1623 return;
stuefe@46524 1624 }
stuefe@46524 1625
stuefe@46524 1626 // determine if this is a legacy image or modules image
stuefe@46524 1627 // modules image doesn't have "jre" subdirectory
stuefe@46524 1628 len = strlen(buf);
stuefe@46524 1629 assert(len < buflen, "Ran out of buffer room");
stuefe@46524 1630 jrelib_p = buf + len;
stuefe@46524 1631 snprintf(jrelib_p, buflen-len, "/jre/lib");
stuefe@46524 1632 if (0 != access(buf, F_OK)) {
stuefe@46524 1633 snprintf(jrelib_p, buflen-len, "/lib");
stuefe@46524 1634 }
stuefe@46524 1635
stuefe@46524 1636 if (0 == access(buf, F_OK)) {
stuefe@46524 1637 // Use current module name "libjvm.so"
stuefe@46524 1638 len = strlen(buf);
stuefe@46524 1639 snprintf(buf + len, buflen-len, "/hotspot/libjvm.so");
stuefe@46524 1640 } else {
stuefe@46524 1641 // Go back to path of .so
stuefe@46524 1642 rp = os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen);
stuefe@46524 1643 if (rp == NULL) {
stuefe@46524 1644 return;
stuefe@46524 1645 }
stuefe@46524 1646 }
stuefe@46524 1647 }
stuefe@46524 1648 }
stuefe@46524 1649 }
stuefe@46524 1650
goetz@27471 1651 strncpy(saved_jvm_path, buf, sizeof(saved_jvm_path));
goetz@27471 1652 saved_jvm_path[sizeof(saved_jvm_path) - 1] = '\0';
simonis@22831 1653 }
simonis@22831 1654
simonis@22831 1655 void os::print_jni_name_prefix_on(outputStream* st, int args_size) {
simonis@22831 1656 // no prefix required, not even "_"
simonis@22831 1657 }
simonis@22831 1658
simonis@22831 1659 void os::print_jni_name_suffix_on(outputStream* st, int args_size) {
simonis@22831 1660 // no suffix required
simonis@22831 1661 }
simonis@22831 1662
simonis@22831 1663 ////////////////////////////////////////////////////////////////////////////////
simonis@22831 1664 // sun.misc.Signal support
simonis@22831 1665
simonis@22831 1666 static volatile jint sigint_count = 0;
simonis@22831 1667
simonis@22831 1668 static void
simonis@22831 1669 UserHandler(int sig, void *siginfo, void *context) {
simonis@22831 1670 // 4511530 - sem_post is serialized and handled by the manager thread. When
simonis@22831 1671 // the program is interrupted by Ctrl-C, SIGINT is sent to every thread. We
simonis@22831 1672 // don't want to flood the manager thread with sem_post requests.
simonis@22831 1673 if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1)
simonis@22831 1674 return;
simonis@22831 1675
simonis@22831 1676 // Ctrl-C is pressed during error reporting, likely because the error
simonis@22831 1677 // handler fails to abort. Let VM die immediately.
coleenp@46589 1678 if (sig == SIGINT && VMError::is_error_reported()) {
simonis@22831 1679 os::die();
simonis@22831 1680 }
simonis@22831 1681
simonis@22831 1682 os::signal_notify(sig);
simonis@22831 1683 }
simonis@22831 1684
simonis@22831 1685 void* os::user_handler() {
simonis@22831 1686 return CAST_FROM_FN_PTR(void*, UserHandler);
simonis@22831 1687 }
simonis@22831 1688
simonis@22831 1689 extern "C" {
simonis@22831 1690 typedef void (*sa_handler_t)(int);
simonis@22831 1691 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
simonis@22831 1692 }
simonis@22831 1693
simonis@22831 1694 void* os::signal(int signal_number, void* handler) {
simonis@22831 1695 struct sigaction sigAct, oldSigAct;
simonis@22831 1696
simonis@22831 1697 sigfillset(&(sigAct.sa_mask));
simonis@22831 1698
simonis@22831 1699 // Do not block out synchronous signals in the signal handler.
simonis@22831 1700 // Blocking synchronous signals only makes sense if you can really
simonis@22831 1701 // be sure that those signals won't happen during signal handling,
goetz@28187 1702 // when the blocking applies. Normal signal handlers are lean and
simonis@22831 1703 // do not cause signals. But our signal handlers tend to be "risky"
simonis@22831 1704 // - secondary SIGSEGV, SIGILL, SIGBUS' may and do happen.
simonis@22831 1705 // On AIX, PASE there was a case where a SIGSEGV happened, followed
simonis@22831 1706 // by a SIGILL, which was blocked due to the signal mask. The process
simonis@22831 1707 // just hung forever. Better to crash from a secondary signal than to hang.
simonis@22831 1708 sigdelset(&(sigAct.sa_mask), SIGSEGV);
simonis@22831 1709 sigdelset(&(sigAct.sa_mask), SIGBUS);
simonis@22831 1710 sigdelset(&(sigAct.sa_mask), SIGILL);
simonis@22831 1711 sigdelset(&(sigAct.sa_mask), SIGFPE);
simonis@22831 1712 sigdelset(&(sigAct.sa_mask), SIGTRAP);
simonis@22831 1713
simonis@22831 1714 sigAct.sa_flags = SA_RESTART|SA_SIGINFO;
simonis@22831 1715
simonis@22831 1716 sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler);
simonis@22831 1717
simonis@22831 1718 if (sigaction(signal_number, &sigAct, &oldSigAct)) {
simonis@22831 1719 // -1 means registration failed
simonis@22831 1720 return (void *)-1;
simonis@22831 1721 }
simonis@22831 1722
simonis@22831 1723 return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler);
simonis@22831 1724 }
simonis@22831 1725
simonis@22831 1726 void os::signal_raise(int signal_number) {
simonis@22831 1727 ::raise(signal_number);
simonis@22831 1728 }
simonis@22831 1729
simonis@22831 1730 //
simonis@22831 1731 // The following code is moved from os.cpp for making this
simonis@22831 1732 // code platform specific, which it is by its very nature.
simonis@22831 1733 //
simonis@22831 1734
simonis@22831 1735 // Will be modified when max signal is changed to be dynamic
simonis@22831 1736 int os::sigexitnum_pd() {
simonis@22831 1737 return NSIG;
simonis@22831 1738 }
simonis@22831 1739
simonis@22831 1740 // a counter for each possible signal value
simonis@22831 1741 static volatile jint pending_signals[NSIG+1] = { 0 };
simonis@22831 1742
stuefe@34647 1743 // Wrapper functions for: sem_init(), sem_post(), sem_wait()
stuefe@34647 1744 // On AIX, we use sem_init(), sem_post(), sem_wait()
stuefe@34647 1745 // On Pase, we need to use msem_lock() and msem_unlock(), because Posix Semaphores
stuefe@34647 1746 // do not seem to work at all on PASE (unimplemented, will cause SIGILL).
stuefe@34647 1747 // Note that just using msem_.. APIs for both PASE and AIX is not an option either, as
stuefe@34647 1748 // on AIX, msem_..() calls are suspected of causing problems.
simonis@22831 1749 static sem_t sig_sem;
stuefe@34647 1750 static msemaphore* p_sig_msem = 0;
stuefe@34647 1751
stuefe@34647 1752 static void local_sem_init() {
stuefe@34647 1753 if (os::Aix::on_aix()) {
stuefe@34647 1754 int rc = ::sem_init(&sig_sem, 0, 0);
stuefe@34647 1755 guarantee(rc != -1, "sem_init failed");
stuefe@34647 1756 } else {
stuefe@34647 1757 // Memory semaphores must live in shared mem.
stuefe@34647 1758 guarantee0(p_sig_msem == NULL);
stuefe@34647 1759 p_sig_msem = (msemaphore*)os::reserve_memory(sizeof(msemaphore), NULL);
stuefe@34647 1760 guarantee(p_sig_msem, "Cannot allocate memory for memory semaphore");
stuefe@34647 1761 guarantee(::msem_init(p_sig_msem, 0) == p_sig_msem, "msem_init failed");
stuefe@34647 1762 }
stuefe@34647 1763 }
stuefe@34647 1764
stuefe@34647 1765 static void local_sem_post() {
stuefe@34647 1766 static bool warn_only_once = false;
stuefe@34647 1767 if (os::Aix::on_aix()) {
stuefe@34647 1768 int rc = ::sem_post(&sig_sem);
stuefe@34647 1769 if (rc == -1 && !warn_only_once) {
stuefe@37113 1770 trcVerbose("sem_post failed (errno = %d, %s)", errno, os::errno_name(errno));
stuefe@34647 1771 warn_only_once = true;
stuefe@34647 1772 }
stuefe@34647 1773 } else {
stuefe@34647 1774 guarantee0(p_sig_msem != NULL);
stuefe@34647 1775 int rc = ::msem_unlock(p_sig_msem, 0);
stuefe@34647 1776 if (rc == -1 && !warn_only_once) {
stuefe@37113 1777 trcVerbose("msem_unlock failed (errno = %d, %s)", errno, os::errno_name(errno));
stuefe@34647 1778 warn_only_once = true;
stuefe@34647 1779 }
stuefe@34647 1780 }
stuefe@34647 1781 }
stuefe@34647 1782
stuefe@34647 1783 static void local_sem_wait() {
stuefe@34647 1784 static bool warn_only_once = false;
stuefe@34647 1785 if (os::Aix::on_aix()) {
stuefe@34647 1786 int rc = ::sem_wait(&sig_sem);
stuefe@34647 1787 if (rc == -1 && !warn_only_once) {
stuefe@37113 1788 trcVerbose("sem_wait failed (errno = %d, %s)", errno, os::errno_name(errno));
stuefe@34647 1789 warn_only_once = true;
stuefe@34647 1790 }
stuefe@34647 1791 } else {
stuefe@34647 1792 guarantee0(p_sig_msem != NULL); // must init before use
stuefe@34647 1793 int rc = ::msem_lock(p_sig_msem, 0);
stuefe@34647 1794 if (rc == -1 && !warn_only_once) {
stuefe@37113 1795 trcVerbose("msem_lock failed (errno = %d, %s)", errno, os::errno_name(errno));
stuefe@34647 1796 warn_only_once = true;
stuefe@34647 1797 }
stuefe@34647 1798 }
stuefe@34647 1799 }
simonis@22831 1800
coleenp@50768 1801 static void jdk_misc_signal_init() {
simonis@22831 1802 // Initialize signal structures
simonis@22831 1803 ::memset((void*)pending_signals, 0, sizeof(pending_signals));
simonis@22831 1804
simonis@22831 1805 // Initialize signal semaphore
stuefe@34647 1806 local_sem_init();
simonis@22831 1807 }
simonis@22831 1808
simonis@22831 1809 void os::signal_notify(int sig) {
simonis@22831 1810 Atomic::inc(&pending_signals[sig]);
stuefe@34647 1811 local_sem_post();
simonis@22831 1812 }
simonis@22831 1813
coleenp@48955 1814 static int check_pending_signals() {
simonis@22831 1815 Atomic::store(0, &sigint_count);
simonis@22831 1816 for (;;) {
simonis@22831 1817 for (int i = 0; i < NSIG + 1; i++) {
simonis@22831 1818 jint n = pending_signals[i];
simonis@22831 1819 if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) {
simonis@22831 1820 return i;
simonis@22831 1821 }
simonis@22831 1822 }
simonis@22831 1823 JavaThread *thread = JavaThread::current();
simonis@22831 1824 ThreadBlockInVM tbivm(thread);
simonis@22831 1825
simonis@22831 1826 bool threadIsSuspended;
simonis@22831 1827 do {
simonis@22831 1828 thread->set_suspend_equivalent();
simonis@22831 1829 // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
simonis@22831 1830
stuefe@34647 1831 local_sem_wait();
simonis@22831 1832
simonis@22831 1833 // were we externally suspended while we were waiting?
simonis@22831 1834 threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
simonis@22831 1835 if (threadIsSuspended) {
simonis@22831 1836 //
simonis@22831 1837 // The semaphore has been incremented, but while we were waiting
simonis@22831 1838 // another thread suspended us. We don't want to continue running
simonis@22831 1839 // while suspended because that would surprise the thread that
simonis@22831 1840 // suspended us.
simonis@22831 1841 //
stuefe@34647 1842
stuefe@34647 1843 local_sem_post();
simonis@22831 1844
simonis@22831 1845 thread->java_suspend_self();
simonis@22831 1846 }
simonis@22831 1847 } while (threadIsSuspended);
simonis@22831 1848 }
simonis@22831 1849 }
simonis@22831 1850
simonis@22831 1851 int os::signal_wait() {
coleenp@48955 1852 return check_pending_signals();
simonis@22831 1853 }
simonis@22831 1854
simonis@22831 1855 ////////////////////////////////////////////////////////////////////////////////
simonis@22831 1856 // Virtual Memory
simonis@22831 1857
goetz@30198 1858 // We need to keep small simple bookkeeping for os::reserve_memory and friends.
goetz@30198 1859
goetz@30198 1860 #define VMEM_MAPPED 1
goetz@30198 1861 #define VMEM_SHMATED 2
goetz@30198 1862
goetz@30198 1863 struct vmembk_t {
goetz@30198 1864 int type; // 1 - mmap, 2 - shmat
goetz@30198 1865 char* addr;
goetz@30198 1866 size_t size; // Real size, may be larger than usersize.
goetz@30198 1867 size_t pagesize; // page size of area
goetz@30198 1868 vmembk_t* next;
goetz@30198 1869
goetz@30198 1870 bool contains_addr(char* p) const {
goetz@30198 1871 return p >= addr && p < (addr + size);
goetz@30198 1872 }
goetz@30198 1873
goetz@30198 1874 bool contains_range(char* p, size_t s) const {
goetz@30198 1875 return contains_addr(p) && contains_addr(p + s - 1);
goetz@30198 1876 }
goetz@30198 1877
goetz@30198 1878 void print_on(outputStream* os) const {
goetz@30198 1879 os->print("[" PTR_FORMAT " - " PTR_FORMAT "] (" UINTX_FORMAT
goetz@30198 1880 " bytes, %d %s pages), %s",
goetz@30198 1881 addr, addr + size - 1, size, size / pagesize, describe_pagesize(pagesize),
goetz@30198 1882 (type == VMEM_SHMATED ? "shmat" : "mmap")
goetz@30198 1883 );
goetz@30198 1884 }
goetz@30198 1885
goetz@30198 1886 // Check that range is a sub range of memory block (or equal to memory block);
goetz@30198 1887 // also check that range is fully page aligned to the page size if the block.
goetz@30198 1888 void assert_is_valid_subrange(char* p, size_t s) const {
goetz@30198 1889 if (!contains_range(p, s)) {
stuefe@34647 1890 trcVerbose("[" PTR_FORMAT " - " PTR_FORMAT "] is not a sub "
stuefe@34647 1891 "range of [" PTR_FORMAT " - " PTR_FORMAT "].",
stuefe@34647 1892 p, p + s, addr, addr + size);
goetz@30198 1893 guarantee0(false);
simonis@22831 1894 }
goetz@30198 1895 if (!is_aligned_to(p, pagesize) || !is_aligned_to(p + s, pagesize)) {
stuefe@34647 1896 trcVerbose("range [" PTR_FORMAT " - " PTR_FORMAT "] is not"
stuefe@34647 1897 " aligned to pagesize (%lu)", p, p + s, (unsigned long) pagesize);
goetz@30198 1898 guarantee0(false);
simonis@22831 1899 }
simonis@22831 1900 }
simonis@22831 1901 };
simonis@22831 1902
goetz@30198 1903 static struct {
goetz@30198 1904 vmembk_t* first;
goetz@30198 1905 MiscUtils::CritSect cs;
goetz@30198 1906 } vmem;
goetz@30198 1907
goetz@30198 1908 static void vmembk_add(char* addr, size_t size, size_t pagesize, int type) {
goetz@30198 1909 vmembk_t* p = (vmembk_t*) ::malloc(sizeof(vmembk_t));
goetz@30198 1910 assert0(p);
goetz@30198 1911 if (p) {
goetz@30198 1912 MiscUtils::AutoCritSect lck(&vmem.cs);
goetz@30198 1913 p->addr = addr; p->size = size;
goetz@30198 1914 p->pagesize = pagesize;
goetz@30198 1915 p->type = type;
goetz@30198 1916 p->next = vmem.first;
goetz@30198 1917 vmem.first = p;
goetz@30198 1918 }
goetz@30198 1919 }
goetz@30198 1920
goetz@30198 1921 static vmembk_t* vmembk_find(char* addr) {
goetz@30198 1922 MiscUtils::AutoCritSect lck(&vmem.cs);
goetz@30198 1923 for (vmembk_t* p = vmem.first; p; p = p->next) {
goetz@30198 1924 if (p->addr <= addr && (p->addr + p->size) > addr) {
goetz@30198 1925 return p;
simonis@22831 1926 }
goetz@30198 1927 }
goetz@30198 1928 return NULL;
goetz@30198 1929 }
goetz@30198 1930
goetz@30198 1931 static void vmembk_remove(vmembk_t* p0) {
goetz@30198 1932 MiscUtils::AutoCritSect lck(&vmem.cs);
goetz@30198 1933 assert0(p0);
goetz@30198 1934 assert0(vmem.first); // List should not be empty.
goetz@30198 1935 for (vmembk_t** pp = &(vmem.first); *pp; pp = &((*pp)->next)) {
goetz@30198 1936 if (*pp == p0) {
goetz@30198 1937 *pp = p0->next;
goetz@30198 1938 ::free(p0);
simonis@22831 1939 return;
simonis@22831 1940 }
goetz@30198 1941 }
goetz@30198 1942 assert0(false); // Not found?
goetz@30198 1943 }
goetz@30198 1944
goetz@30198 1945 static void vmembk_print_on(outputStream* os) {
goetz@30198 1946 MiscUtils::AutoCritSect lck(&vmem.cs);
goetz@30198 1947 for (vmembk_t* vmi = vmem.first; vmi; vmi = vmi->next) {
goetz@30198 1948 vmi->print_on(os);
goetz@30198 1949 os->cr();
goetz@30198 1950 }
goetz@30198 1951 }
goetz@30198 1952
goetz@30198 1953 // Reserve and attach a section of System V memory.
goetz@30198 1954 // If <requested_addr> is not NULL, function will attempt to attach the memory at the given
goetz@30198 1955 // address. Failing that, it will attach the memory anywhere.
goetz@30198 1956 // If <requested_addr> is NULL, function will attach the memory anywhere.
goetz@30198 1957 //
goetz@30198 1958 // <alignment_hint> is being ignored by this function. It is very probable however that the
goetz@30198 1959 // alignment requirements are met anyway, because shmat() attaches at 256M boundaries.
goetz@30198 1960 // Should this be not enogh, we can put more work into it.
goetz@30198 1961 static char* reserve_shmated_memory (
goetz@30198 1962 size_t bytes,
goetz@30198 1963 char* requested_addr,
goetz@30198 1964 size_t alignment_hint) {
goetz@30198 1965
goetz@30198 1966 trcVerbose("reserve_shmated_memory " UINTX_FORMAT " bytes, wishaddress "
goetz@30198 1967 PTR_FORMAT ", alignment_hint " UINTX_FORMAT "...",
goetz@30198 1968 bytes, requested_addr, alignment_hint);
goetz@30198 1969
goetz@30198 1970 // Either give me wish address or wish alignment but not both.
goetz@30198 1971 assert0(!(requested_addr != NULL && alignment_hint != 0));
goetz@30198 1972
goetz@30198 1973 // We must prevent anyone from attaching too close to the
goetz@30198 1974 // BRK because that may cause malloc OOM.
goetz@30198 1975 if (requested_addr != NULL && is_close_to_brk((address)requested_addr)) {
goetz@30198 1976 trcVerbose("Wish address " PTR_FORMAT " is too close to the BRK segment. "
goetz@30198 1977 "Will attach anywhere.", requested_addr);
goetz@30198 1978 // Act like the OS refused to attach there.
goetz@30198 1979 requested_addr = NULL;
goetz@30198 1980 }
goetz@30198 1981
goetz@30198 1982 // For old AS/400's (V5R4 and older) we should not even be here - System V shared memory is not
goetz@30198 1983 // really supported (max size 4GB), so reserve_mmapped_memory should have been used instead.
goetz@30198 1984 if (os::Aix::on_pase_V5R4_or_older()) {
goetz@30198 1985 ShouldNotReachHere();
goetz@30198 1986 }
goetz@30198 1987
goetz@30198 1988 // Align size of shm up to 64K to avoid errors if we later try to change the page size.
stefank@46619 1989 const size_t size = align_up(bytes, 64*K);
goetz@30198 1990
goetz@30198 1991 // Reserve the shared segment.
goetz@30198 1992 int shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | S_IRUSR | S_IWUSR);
goetz@30198 1993 if (shmid == -1) {
stuefe@34647 1994 trcVerbose("shmget(.., " UINTX_FORMAT ", ..) failed (errno: %d).", size, errno);
goetz@30198 1995 return NULL;
goetz@30198 1996 }
goetz@30198 1997
goetz@30198 1998 // Important note:
goetz@30198 1999 // It is very important that we, upon leaving this function, do not leave a shm segment alive.
goetz@30198 2000 // We must right after attaching it remove it from the system. System V shm segments are global and
goetz@30198 2001 // survive the process.
goetz@30198 2002 // So, from here on: Do not assert, do not return, until we have called shmctl(IPC_RMID) (A).
goetz@30198 2003
goetz@30198 2004 struct shmid_ds shmbuf;
goetz@30198 2005 memset(&shmbuf, 0, sizeof(shmbuf));
simonis@42061 2006 shmbuf.shm_pagesize = 64*K;
goetz@30198 2007 if (shmctl(shmid, SHM_PAGESIZE, &shmbuf) != 0) {
goetz@30198 2008 trcVerbose("Failed to set page size (need " UINTX_FORMAT " 64K pages) - shmctl failed with %d.",
simonis@42061 2009 size / (64*K), errno);
goetz@30198 2010 // I want to know if this ever happens.
goetz@30198 2011 assert(false, "failed to set page size for shmat");
goetz@30198 2012 }
goetz@30198 2013
goetz@30198 2014 // Now attach the shared segment.
goetz@30198 2015 // Note that I attach with SHM_RND - which means that the requested address is rounded down, if
goetz@30198 2016 // needed, to the next lowest segment boundary. Otherwise the attach would fail if the address
goetz@30198 2017 // were not a segment boundary.
goetz@30198 2018 char* const addr = (char*) shmat(shmid, requested_addr, SHM_RND);
goetz@30198 2019 const int errno_shmat = errno;
goetz@30198 2020
goetz@30198 2021 // (A) Right after shmat and before handing shmat errors delete the shm segment.
goetz@30198 2022 if (::shmctl(shmid, IPC_RMID, NULL) == -1) {
stuefe@34647 2023 trcVerbose("shmctl(%u, IPC_RMID) failed (%d)\n", shmid, errno);
goetz@30198 2024 assert(false, "failed to remove shared memory segment!");
goetz@30198 2025 }
goetz@30198 2026
goetz@30198 2027 // Handle shmat error. If we failed to attach, just return.
goetz@30198 2028 if (addr == (char*)-1) {
goetz@30198 2029 trcVerbose("Failed to attach segment at " PTR_FORMAT " (%d).", requested_addr, errno_shmat);
goetz@30198 2030 return NULL;
goetz@30198 2031 }
goetz@30198 2032
goetz@30198 2033 // Just for info: query the real page size. In case setting the page size did not
goetz@30198 2034 // work (see above), the system may have given us something other then 4K (LDR_CNTRL).
goetz@30198 2035 const size_t real_pagesize = os::Aix::query_pagesize(addr);
goetz@30198 2036 if (real_pagesize != shmbuf.shm_pagesize) {
goetz@30198 2037 trcVerbose("pagesize is, surprisingly, %h.", real_pagesize);
goetz@30198 2038 }
goetz@30198 2039
goetz@30198 2040 if (addr) {
goetz@30198 2041 trcVerbose("shm-allocated " PTR_FORMAT " .. " PTR_FORMAT " (" UINTX_FORMAT " bytes, " UINTX_FORMAT " %s pages)",
goetz@30198 2042 addr, addr + size - 1, size, size/real_pagesize, describe_pagesize(real_pagesize));
goetz@30198 2043 } else {
goetz@30198 2044 if (requested_addr != NULL) {
goetz@30198 2045 trcVerbose("failed to shm-allocate " UINTX_FORMAT " bytes at with address " PTR_FORMAT ".", size, requested_addr);
goetz@30198 2046 } else {
goetz@30198 2047 trcVerbose("failed to shm-allocate " UINTX_FORMAT " bytes at any address.", size);
simonis@22831 2048 }
goetz@30198 2049 }
goetz@30198 2050
goetz@30198 2051 // book-keeping
goetz@30198 2052 vmembk_add(addr, size, real_pagesize, VMEM_SHMATED);
goetz@30198 2053 assert0(is_aligned_to(addr, os::vm_page_size()));
goetz@30198 2054
goetz@30198 2055 return addr;
goetz@30198 2056 }
goetz@30198 2057
goetz@30198 2058 static bool release_shmated_memory(char* addr, size_t size) {
goetz@30198 2059
goetz@30198 2060 trcVerbose("release_shmated_memory [" PTR_FORMAT " - " PTR_FORMAT "].",
goetz@30198 2061 addr, addr + size - 1);
goetz@30198 2062
goetz@30198 2063 bool rc = false;
goetz@30198 2064
goetz@30198 2065 // TODO: is there a way to verify shm size without doing bookkeeping?
goetz@30198 2066 if (::shmdt(addr) != 0) {
goetz@30198 2067 trcVerbose("error (%d).", errno);
goetz@30198 2068 } else {
goetz@30198 2069 trcVerbose("ok.");
goetz@30198 2070 rc = true;
goetz@30198 2071 }
goetz@30198 2072 return rc;
goetz@30198 2073 }
goetz@30198 2074
goetz@30198 2075 static bool uncommit_shmated_memory(char* addr, size_t size) {
goetz@30198 2076 trcVerbose("uncommit_shmated_memory [" PTR_FORMAT " - " PTR_FORMAT "].",
goetz@30198 2077 addr, addr + size - 1);
goetz@30198 2078
goetz@30198 2079 const bool rc = my_disclaim64(addr, size);
goetz@30198 2080
goetz@30198 2081 if (!rc) {
goetz@30198 2082 trcVerbose("my_disclaim64(" PTR_FORMAT ", " UINTX_FORMAT ") failed.\n", addr, size);
goetz@30198 2083 return false;
goetz@30198 2084 }
goetz@30198 2085 return true;
goetz@30198 2086 }
goetz@30198 2087
stuefe@34647 2088 //////////////////////////////// mmap-based routines /////////////////////////////////
stuefe@34647 2089
goetz@30198 2090 // Reserve memory via mmap.
goetz@30198 2091 // If <requested_addr> is given, an attempt is made to attach at the given address.
goetz@30198 2092 // Failing that, memory is allocated at any address.
goetz@30198 2093 // If <alignment_hint> is given and <requested_addr> is NULL, an attempt is made to
goetz@30198 2094 // allocate at an address aligned with the given alignment. Failing that, memory
goetz@30198 2095 // is aligned anywhere.
goetz@30198 2096 static char* reserve_mmaped_memory(size_t bytes, char* requested_addr, size_t alignment_hint) {
goetz@30198 2097 trcVerbose("reserve_mmaped_memory " UINTX_FORMAT " bytes, wishaddress " PTR_FORMAT ", "
goetz@30198 2098 "alignment_hint " UINTX_FORMAT "...",
goetz@30198 2099 bytes, requested_addr, alignment_hint);
goetz@30198 2100
goetz@30198 2101 // If a wish address is given, but not aligned to 4K page boundary, mmap will fail.
goetz@30198 2102 if (requested_addr && !is_aligned_to(requested_addr, os::vm_page_size()) != 0) {
goetz@30198 2103 trcVerbose("Wish address " PTR_FORMAT " not aligned to page boundary.", requested_addr);
goetz@30198 2104 return NULL;
goetz@30198 2105 }
goetz@30198 2106
goetz@30198 2107 // We must prevent anyone from attaching too close to the
goetz@30198 2108 // BRK because that may cause malloc OOM.
goetz@30198 2109 if (requested_addr != NULL && is_close_to_brk((address)requested_addr)) {
goetz@30198 2110 trcVerbose("Wish address " PTR_FORMAT " is too close to the BRK segment. "
goetz@30198 2111 "Will attach anywhere.", requested_addr);
goetz@30198 2112 // Act like the OS refused to attach there.
goetz@30198 2113 requested_addr = NULL;
goetz@30198 2114 }
goetz@30198 2115
goetz@30198 2116 // Specify one or the other but not both.
goetz@30198 2117 assert0(!(requested_addr != NULL && alignment_hint > 0));
goetz@30198 2118
goetz@30198 2119 // In 64K mode, we claim the global page size (os::vm_page_size())
goetz@30198 2120 // is 64K. This is one of the few points where that illusion may
goetz@30198 2121 // break, because mmap() will always return memory aligned to 4K. So
goetz@30198 2122 // we must ensure we only ever return memory aligned to 64k.
goetz@30198 2123 if (alignment_hint) {
goetz@30198 2124 alignment_hint = lcm(alignment_hint, os::vm_page_size());
goetz@30198 2125 } else {
goetz@30198 2126 alignment_hint = os::vm_page_size();
goetz@30198 2127 }
goetz@30198 2128
goetz@30198 2129 // Size shall always be a multiple of os::vm_page_size (esp. in 64K mode).
stefank@46619 2130 const size_t size = align_up(bytes, os::vm_page_size());
goetz@30198 2131
goetz@30198 2132 // alignment: Allocate memory large enough to include an aligned range of the right size and
goetz@30198 2133 // cut off the leading and trailing waste pages.
goetz@30198 2134 assert0(alignment_hint != 0 && is_aligned_to(alignment_hint, os::vm_page_size())); // see above
goetz@30198 2135 const size_t extra_size = size + alignment_hint;
goetz@30198 2136
goetz@30198 2137 // Note: MAP_SHARED (instead of MAP_PRIVATE) needed to be able to
goetz@30198 2138 // later use msync(MS_INVALIDATE) (see os::uncommit_memory).
goetz@30198 2139 int flags = MAP_ANONYMOUS | MAP_SHARED;
goetz@30198 2140
goetz@30198 2141 // MAP_FIXED is needed to enforce requested_addr - manpage is vague about what
goetz@30198 2142 // it means if wishaddress is given but MAP_FIXED is not set.
goetz@30198 2143 //
goetz@30198 2144 // Important! Behaviour differs depending on whether SPEC1170 mode is active or not.
goetz@30198 2145 // SPEC1170 mode active: behaviour like POSIX, MAP_FIXED will clobber existing mappings.
goetz@30198 2146 // SPEC1170 mode not active: behaviour, unlike POSIX, is that no existing mappings will
goetz@30198 2147 // get clobbered.
goetz@30198 2148 if (requested_addr != NULL) {
goetz@30198 2149 if (!os::Aix::xpg_sus_mode()) { // not SPEC1170 Behaviour
goetz@30198 2150 flags |= MAP_FIXED;
goetz@30198 2151 }
goetz@30198 2152 }
goetz@30198 2153
goetz@30198 2154 char* addr = (char*)::mmap(requested_addr, extra_size,
goetz@30198 2155 PROT_READ|PROT_WRITE|PROT_EXEC, flags, -1, 0);
goetz@30198 2156
goetz@30198 2157 if (addr == MAP_FAILED) {
goetz@30198 2158 trcVerbose("mmap(" PTR_FORMAT ", " UINTX_FORMAT ", ..) failed (%d)", requested_addr, size, errno);
goetz@30198 2159 return NULL;
goetz@30198 2160 }
goetz@30198 2161
goetz@30198 2162 // Handle alignment.
stefank@46619 2163 char* const addr_aligned = align_up(addr, alignment_hint);
goetz@30198 2164 const size_t waste_pre = addr_aligned - addr;
goetz@30198 2165 char* const addr_aligned_end = addr_aligned + size;
goetz@30198 2166 const size_t waste_post = extra_size - waste_pre - size;
goetz@30198 2167 if (waste_pre > 0) {
goetz@30198 2168 ::munmap(addr, waste_pre);
goetz@30198 2169 }
goetz@30198 2170 if (waste_post > 0) {
goetz@30198 2171 ::munmap(addr_aligned_end, waste_post);
goetz@30198 2172 }
goetz@30198 2173 addr = addr_aligned;
goetz@30198 2174
goetz@30198 2175 if (addr) {
goetz@30198 2176 trcVerbose("mmap-allocated " PTR_FORMAT " .. " PTR_FORMAT " (" UINTX_FORMAT " bytes)",
goetz@30198 2177 addr, addr + bytes, bytes);
goetz@30198 2178 } else {
goetz@30198 2179 if (requested_addr != NULL) {
goetz@30198 2180 trcVerbose("failed to mmap-allocate " UINTX_FORMAT " bytes at wish address " PTR_FORMAT ".", bytes, requested_addr);
goetz@30198 2181 } else {
goetz@30198 2182 trcVerbose("failed to mmap-allocate " UINTX_FORMAT " bytes at any address.", bytes);
goetz@30198 2183 }
goetz@30198 2184 }
goetz@30198 2185
goetz@30198 2186 // bookkeeping
simonis@42061 2187 vmembk_add(addr, size, 4*K, VMEM_MAPPED);
goetz@30198 2188
goetz@30198 2189 // Test alignment, see above.
goetz@30198 2190 assert0(is_aligned_to(addr, os::vm_page_size()));
goetz@30198 2191
goetz@30198 2192 return addr;
goetz@30198 2193 }
goetz@30198 2194
goetz@30198 2195 static bool release_mmaped_memory(char* addr, size_t size) {
goetz@30198 2196 assert0(is_aligned_to(addr, os::vm_page_size()));
goetz@30198 2197 assert0(is_aligned_to(size, os::vm_page_size()));
goetz@30198 2198
goetz@30198 2199 trcVerbose("release_mmaped_memory [" PTR_FORMAT " - " PTR_FORMAT "].",
goetz@30198 2200 addr, addr + size - 1);
goetz@30198 2201 bool rc = false;
goetz@30198 2202
goetz@30198 2203 if (::munmap(addr, size) != 0) {
goetz@30198 2204 trcVerbose("failed (%d)\n", errno);
goetz@30198 2205 rc = false;
goetz@30198 2206 } else {
goetz@30198 2207 trcVerbose("ok.");
goetz@30198 2208 rc = true;
goetz@30198 2209 }
goetz@30198 2210
goetz@30198 2211 return rc;
goetz@30198 2212 }
goetz@30198 2213
goetz@30198 2214 static bool uncommit_mmaped_memory(char* addr, size_t size) {
goetz@30198 2215
goetz@30198 2216 assert0(is_aligned_to(addr, os::vm_page_size()));
goetz@30198 2217 assert0(is_aligned_to(size, os::vm_page_size()));
goetz@30198 2218
goetz@30198 2219 trcVerbose("uncommit_mmaped_memory [" PTR_FORMAT " - " PTR_FORMAT "].",
goetz@30198 2220 addr, addr + size - 1);
goetz@30198 2221 bool rc = false;
goetz@30198 2222
goetz@30198 2223 // Uncommit mmap memory with msync MS_INVALIDATE.
goetz@30198 2224 if (::msync(addr, size, MS_INVALIDATE) != 0) {
goetz@30198 2225 trcVerbose("failed (%d)\n", errno);
goetz@30198 2226 rc = false;
goetz@30198 2227 } else {
goetz@30198 2228 trcVerbose("ok.");
goetz@30198 2229 rc = true;
goetz@30198 2230 }
goetz@30198 2231
goetz@30198 2232 return rc;
goetz@30198 2233 }
simonis@22831 2234
simonis@22831 2235 int os::vm_page_size() {
goetz@30198 2236 // Seems redundant as all get out.
simonis@22831 2237 assert(os::Aix::page_size() != -1, "must call os::init");
simonis@22831 2238 return os::Aix::page_size();
simonis@22831 2239 }
simonis@22831 2240
simonis@22831 2241 // Aix allocates memory by pages.
simonis@22831 2242 int os::vm_allocation_granularity() {
simonis@22831 2243 assert(os::Aix::page_size() != -1, "must call os::init");
simonis@22831 2244 return os::Aix::page_size();
simonis@22831 2245 }
simonis@22831 2246
goetz@30198 2247 #ifdef PRODUCT
goetz@30198 2248 static void warn_fail_commit_memory(char* addr, size_t size, bool exec,
goetz@30198 2249 int err) {
goetz@30198 2250 warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
goetz@30198 2251 ", %d) failed; error='%s' (errno=%d)", addr, size, exec,
stuefe@37113 2252 os::errno_name(err), err);
goetz@30198 2253 }
goetz@30198 2254 #endif
simonis@22831 2255
simonis@22831 2256 void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec,
simonis@22831 2257 const char* mesg) {
simonis@22831 2258 assert(mesg != NULL, "mesg must be specified");
goetz@30198 2259 if (!pd_commit_memory(addr, size, exec)) {
goetz@30198 2260 // Add extra info in product mode for vm_exit_out_of_memory():
goetz@30198 2261 PRODUCT_ONLY(warn_fail_commit_memory(addr, size, exec, errno);)
david@33105 2262 vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "%s", mesg);
goetz@30198 2263 }
goetz@30198 2264 }
goetz@30198 2265
goetz@30198 2266 bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
goetz@30198 2267
stuefe@34624 2268 assert(is_aligned_to(addr, os::vm_page_size()),
stuefe@34624 2269 "addr " PTR_FORMAT " not aligned to vm_page_size (" PTR_FORMAT ")",
stuefe@34624 2270 p2i(addr), os::vm_page_size());
stuefe@34624 2271 assert(is_aligned_to(size, os::vm_page_size()),
stuefe@34624 2272 "size " PTR_FORMAT " not aligned to vm_page_size (" PTR_FORMAT ")",
stuefe@34624 2273 size, os::vm_page_size());
goetz@30198 2274
goetz@30198 2275 vmembk_t* const vmi = vmembk_find(addr);
stuefe@34647 2276 guarantee0(vmi);
goetz@30198 2277 vmi->assert_is_valid_subrange(addr, size);
goetz@30198 2278
goetz@30198 2279 trcVerbose("commit_memory [" PTR_FORMAT " - " PTR_FORMAT "].", addr, addr + size - 1);
goetz@30198 2280
stuefe@34647 2281 if (UseExplicitCommit) {
stuefe@34647 2282 // AIX commits memory on touch. So, touch all pages to be committed.
simonis@42061 2283 for (char* p = addr; p < (addr + size); p += 4*K) {
stuefe@34647 2284 *p = '\0';
stuefe@34647 2285 }
stuefe@34647 2286 }
stuefe@34647 2287
goetz@30198 2288 return true;
goetz@30198 2289 }
goetz@30198 2290
goetz@30198 2291 bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint, bool exec) {
goetz@30198 2292 return pd_commit_memory(addr, size, exec);
simonis@22831 2293 }
simonis@22831 2294
simonis@22831 2295 void os::pd_commit_memory_or_exit(char* addr, size_t size,
simonis@22831 2296 size_t alignment_hint, bool exec,
simonis@22831 2297 const char* mesg) {
goetz@30198 2298 // Alignment_hint is ignored on this OS.
goetz@30198 2299 pd_commit_memory_or_exit(addr, size, exec, mesg);
simonis@22831 2300 }
simonis@22831 2301
simonis@22831 2302 bool os::pd_uncommit_memory(char* addr, size_t size) {
stuefe@34624 2303 assert(is_aligned_to(addr, os::vm_page_size()),
stuefe@34624 2304 "addr " PTR_FORMAT " not aligned to vm_page_size (" PTR_FORMAT ")",
stuefe@34624 2305 p2i(addr), os::vm_page_size());
stuefe@34624 2306 assert(is_aligned_to(size, os::vm_page_size()),
stuefe@34624 2307 "size " PTR_FORMAT " not aligned to vm_page_size (" PTR_FORMAT ")",
stuefe@34624 2308 size, os::vm_page_size());
goetz@30198 2309
goetz@30198 2310 // Dynamically do different things for mmap/shmat.
goetz@30198 2311 const vmembk_t* const vmi = vmembk_find(addr);
stuefe@34647 2312 guarantee0(vmi);
goetz@30198 2313 vmi->assert_is_valid_subrange(addr, size);
goetz@30198 2314
goetz@30198 2315 if (vmi->type == VMEM_SHMATED) {
goetz@30198 2316 return uncommit_shmated_memory(addr, size);
goetz@30198 2317 } else {
goetz@30198 2318 return uncommit_mmaped_memory(addr, size);
goetz@30198 2319 }
simonis@22831 2320 }
simonis@22831 2321
simonis@22831 2322 bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
goetz@30198 2323 // Do not call this; no need to commit stack pages on AIX.
goetz@30198 2324 ShouldNotReachHere();
goetz@30198 2325 return true;
simonis@22831 2326 }
simonis@22831 2327
simonis@22831 2328 bool os::remove_stack_guard_pages(char* addr, size_t size) {
goetz@30198 2329 // Do not call this; no need to commit stack pages on AIX.
goetz@30198 2330 ShouldNotReachHere();
goetz@30198 2331 return true;
simonis@22831 2332 }
simonis@22831 2333
simonis@22831 2334 void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
simonis@22831 2335 }
simonis@22831 2336
simonis@22831 2337 void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) {
simonis@22831 2338 }
simonis@22831 2339
simonis@22831 2340 void os::numa_make_global(char *addr, size_t bytes) {
simonis@22831 2341 }
simonis@22831 2342
simonis@22831 2343 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
simonis@22831 2344 }
simonis@22831 2345
simonis@22831 2346 bool os::numa_topology_changed() {
simonis@22831 2347 return false;
simonis@22831 2348 }
simonis@22831 2349
simonis@22831 2350 size_t os::numa_get_groups_num() {
simonis@22831 2351 return 1;
simonis@22831 2352 }
simonis@22831 2353
simonis@22831 2354 int os::numa_get_group_id() {
simonis@22831 2355 return 0;
simonis@22831 2356 }
simonis@22831 2357
simonis@22831 2358 size_t os::numa_get_leaf_groups(int *ids, size_t size) {
simonis@22831 2359 if (size > 0) {
simonis@22831 2360 ids[0] = 0;
simonis@22831 2361 return 1;
simonis@22831 2362 }
simonis@22831 2363 return 0;
simonis@22831 2364 }
simonis@22831 2365
simonis@22831 2366 bool os::get_page_info(char *start, page_info* info) {
simonis@22831 2367 return false;
simonis@22831 2368 }
simonis@22831 2369
simonis@22831 2370 char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) {
simonis@22831 2371 return end;
simonis@22831 2372 }
simonis@22831 2373
simonis@22831 2374 // Reserves and attaches a shared memory segment.
simonis@22831 2375 // Will assert if a wish address is given and could not be obtained.
simonis@22831 2376 char* os::pd_reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) {
goetz@30198 2377
goetz@30198 2378 // All other Unices do a mmap(MAP_FIXED) if the addr is given,
goetz@30198 2379 // thereby clobbering old mappings at that place. That is probably
goetz@30198 2380 // not intended, never used and almost certainly an error were it
goetz@30198 2381 // ever be used this way (to try attaching at a specified address
goetz@30198 2382 // without clobbering old mappings an alternate API exists,
goetz@30198 2383 // os::attempt_reserve_memory_at()).
goetz@30198 2384 // Instead of mimicking the dangerous coding of the other platforms, here I
goetz@30198 2385 // just ignore the request address (release) or assert(debug).
goetz@30198 2386 assert0(requested_addr == NULL);
goetz@30198 2387
goetz@30198 2388 // Always round to os::vm_page_size(), which may be larger than 4K.
stefank@46619 2389 bytes = align_up(bytes, os::vm_page_size());
goetz@30198 2390 const size_t alignment_hint0 =
stefank@46619 2391 alignment_hint ? align_up(alignment_hint, os::vm_page_size()) : 0;
goetz@30198 2392
goetz@30198 2393 // In 4K mode always use mmap.
goetz@30198 2394 // In 64K mode allocate small sizes with mmap, large ones with 64K shmatted.
simonis@42061 2395 if (os::vm_page_size() == 4*K) {
goetz@30198 2396 return reserve_mmaped_memory(bytes, requested_addr, alignment_hint);
goetz@30198 2397 } else {
goetz@30198 2398 if (bytes >= Use64KPagesThreshold) {
goetz@30198 2399 return reserve_shmated_memory(bytes, requested_addr, alignment_hint);
goetz@30198 2400 } else {
goetz@30198 2401 return reserve_mmaped_memory(bytes, requested_addr, alignment_hint);
goetz@30198 2402 }
goetz@30198 2403 }
simonis@22831 2404 }
simonis@22831 2405
simonis@22831 2406 bool os::pd_release_memory(char* addr, size_t size) {
simonis@22831 2407
goetz@30198 2408 // Dynamically do different things for mmap/shmat.
goetz@30198 2409 vmembk_t* const vmi = vmembk_find(addr);
stuefe@34647 2410 guarantee0(vmi);
goetz@30198 2411
goetz@30198 2412 // Always round to os::vm_page_size(), which may be larger than 4K.
stefank@46619 2413 size = align_up(size, os::vm_page_size());
stefank@46619 2414 addr = align_up(addr, os::vm_page_size());
simonis@22831 2415
simonis@22831 2416 bool rc = false;
goetz@30198 2417 bool remove_bookkeeping = false;
goetz@30198 2418 if (vmi->type == VMEM_SHMATED) {
goetz@30198 2419 // For shmatted memory, we do:
goetz@30198 2420 // - If user wants to release the whole range, release the memory (shmdt).
goetz@30198 2421 // - If user only wants to release a partial range, uncommit (disclaim) that
goetz@30198 2422 // range. That way, at least, we do not use memory anymore (bust still page
goetz@30198 2423 // table space).
goetz@30198 2424 vmi->assert_is_valid_subrange(addr, size);
goetz@30198 2425 if (addr == vmi->addr && size == vmi->size) {
goetz@30198 2426 rc = release_shmated_memory(addr, size);
goetz@30198 2427 remove_bookkeeping = true;
goetz@30198 2428 } else {
goetz@30198 2429 rc = uncommit_shmated_memory(addr, size);
simonis@22831 2430 }
goetz@30198 2431 } else {
goetz@30198 2432 // User may unmap partial regions but region has to be fully contained.
goetz@30198 2433 #ifdef ASSERT
goetz@30198 2434 vmi->assert_is_valid_subrange(addr, size);
goetz@30198 2435 #endif
goetz@30198 2436 rc = release_mmaped_memory(addr, size);
goetz@30198 2437 remove_bookkeeping = true;
goetz@30198 2438 }
goetz@30198 2439
goetz@30198 2440 // update bookkeeping
goetz@30198 2441 if (rc && remove_bookkeeping) {
goetz@30198 2442 vmembk_remove(vmi);
simonis@22831 2443 }
simonis@22831 2444
simonis@22831 2445 return rc;
simonis@22831 2446 }
simonis@22831 2447
simonis@22831 2448 static bool checked_mprotect(char* addr, size_t size, int prot) {
simonis@22831 2449
simonis@22831 2450 // Little problem here: if SPEC1170 behaviour is off, mprotect() on AIX will
simonis@22831 2451 // not tell me if protection failed when trying to protect an un-protectable range.
simonis@22831 2452 //
simonis@22831 2453 // This means if the memory was allocated using shmget/shmat, protection wont work
simonis@22831 2454 // but mprotect will still return 0:
simonis@22831 2455 //
simonis@22831 2456 // See http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/mprotect.htm
simonis@22831 2457
simonis@22831 2458 bool rc = ::mprotect(addr, size, prot) == 0 ? true : false;
simonis@22831 2459
simonis@22831 2460 if (!rc) {
stuefe@37113 2461 const char* const s_errno = os::errno_name(errno);
simonis@22831 2462 warning("mprotect(" PTR_FORMAT "-" PTR_FORMAT ", 0x%X) failed (%s).", addr, addr + size, prot, s_errno);
simonis@22831 2463 return false;
simonis@22831 2464 }
simonis@22831 2465
simonis@22831 2466 // mprotect success check
simonis@22831 2467 //
simonis@22831 2468 // Mprotect said it changed the protection but can I believe it?
simonis@22831 2469 //
simonis@22831 2470 // To be sure I need to check the protection afterwards. Try to
simonis@22831 2471 // read from protected memory and check whether that causes a segfault.
simonis@22831 2472 //
simonis@22831 2473 if (!os::Aix::xpg_sus_mode()) {
simonis@22831 2474
stuefe@30234 2475 if (CanUseSafeFetch32()) {
simonis@22831 2476
simonis@22831 2477 const bool read_protected =
simonis@22831 2478 (SafeFetch32((int*)addr, 0x12345678) == 0x12345678 &&
simonis@22831 2479 SafeFetch32((int*)addr, 0x76543210) == 0x76543210) ? true : false;
simonis@22831 2480
simonis@22831 2481 if (prot & PROT_READ) {
simonis@22831 2482 rc = !read_protected;
simonis@22831 2483 } else {
simonis@22831 2484 rc = read_protected;
simonis@22831 2485 }
stuefe@34647 2486
stuefe@34647 2487 if (!rc) {
stuefe@34647 2488 if (os::Aix::on_pase()) {
stuefe@34647 2489 // There is an issue on older PASE systems where mprotect() will return success but the
stuefe@34647 2490 // memory will not be protected.
stuefe@34647 2491 // This has nothing to do with the problem of using mproect() on SPEC1170 incompatible
stuefe@34647 2492 // machines; we only see it rarely, when using mprotect() to protect the guard page of
stuefe@34647 2493 // a stack. It is an OS error.
stuefe@34647 2494 //
stuefe@34647 2495 // A valid strategy is just to try again. This usually works. :-/
stuefe@34647 2496
stuefe@34647 2497 ::usleep(1000);
stuefe@34647 2498 if (::mprotect(addr, size, prot) == 0) {
stuefe@34647 2499 const bool read_protected_2 =
stuefe@34647 2500 (SafeFetch32((int*)addr, 0x12345678) == 0x12345678 &&
stuefe@34647 2501 SafeFetch32((int*)addr, 0x76543210) == 0x76543210) ? true : false;
stuefe@34647 2502 rc = true;
stuefe@34647 2503 }
stuefe@34647 2504 }
stuefe@34647 2505 }
simonis@22831 2506 }
simonis@22831 2507 }
stuefe@34647 2508
stuefe@34647 2509 assert(rc == true, "mprotect failed.");
stuefe@34647 2510
simonis@22831 2511 return rc;
simonis@22831 2512 }
simonis@22831 2513
simonis@22831 2514 // Set protections specified
simonis@22831 2515 bool os::protect_memory(char* addr, size_t size, ProtType prot, bool is_committed) {
simonis@22831 2516 unsigned int p = 0;
simonis@22831 2517 switch (prot) {
simonis@22831 2518 case MEM_PROT_NONE: p = PROT_NONE; break;
simonis@22831 2519 case MEM_PROT_READ: p = PROT_READ; break;
simonis@22831 2520 case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break;
simonis@22831 2521 case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break;
simonis@22831 2522 default:
simonis@22831 2523 ShouldNotReachHere();
simonis@22831 2524 }
simonis@22831 2525 // is_committed is unused.
simonis@22831 2526 return checked_mprotect(addr, size, p);
simonis@22831 2527 }
simonis@22831 2528
simonis@22831 2529 bool os::guard_memory(char* addr, size_t size) {
simonis@22831 2530 return checked_mprotect(addr, size, PROT_NONE);
simonis@22831 2531 }
simonis@22831 2532
simonis@22831 2533 bool os::unguard_memory(char* addr, size_t size) {
simonis@22831 2534 return checked_mprotect(addr, size, PROT_READ|PROT_WRITE|PROT_EXEC);
simonis@22831 2535 }
simonis@22831 2536
simonis@22831 2537 // Large page support
simonis@22831 2538
simonis@22831 2539 static size_t _large_page_size = 0;
simonis@22831 2540
simonis@22831 2541 // Enable large page support if OS allows that.
simonis@22831 2542 void os::large_page_init() {
goetz@30198 2543 return; // Nothing to do. See query_multipage_support and friends.
goetz@30198 2544 }
simonis@22831 2545
simonis@22831 2546 char* os::reserve_memory_special(size_t bytes, size_t alignment, char* req_addr, bool exec) {
stuefe@34647 2547 // reserve_memory_special() is used to allocate large paged memory. On AIX, we implement
stuefe@34647 2548 // 64k paged memory reservation using the normal memory allocation paths (os::reserve_memory()),
stuefe@34647 2549 // so this is not needed.
stuefe@34647 2550 assert(false, "should not be called on AIX");
stuefe@34647 2551 return NULL;
simonis@22831 2552 }
simonis@22831 2553
simonis@22831 2554 bool os::release_memory_special(char* base, size_t bytes) {
goetz@30198 2555 // Detaching the SHM segment will also delete it, see reserve_memory_special().
simonis@22831 2556 Unimplemented();
simonis@22831 2557 return false;
simonis@22831 2558 }
simonis@22831 2559
simonis@22831 2560 size_t os::large_page_size() {
simonis@22831 2561 return _large_page_size;
simonis@22831 2562 }
simonis@22831 2563
simonis@22831 2564 bool os::can_commit_large_page_memory() {
goetz@30198 2565 // Does not matter, we do not support huge pages.
goetz@30198 2566 return false;
simonis@22831 2567 }
simonis@22831 2568
simonis@22831 2569 bool os::can_execute_large_page_memory() {
goetz@30198 2570 // Does not matter, we do not support huge pages.
goetz@30198 2571 return false;
simonis@22831 2572 }
simonis@22831 2573
kkharbas@48369 2574 char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) {
kkharbas@48369 2575 assert(file_desc >= 0, "file_desc is not valid");
kkharbas@48369 2576 char* result = NULL;
kkharbas@48369 2577
kkharbas@48369 2578 // Always round to os::vm_page_size(), which may be larger than 4K.
kkharbas@48369 2579 bytes = align_up(bytes, os::vm_page_size());
kkharbas@48369 2580 result = reserve_mmaped_memory(bytes, requested_addr, 0);
kkharbas@48369 2581
kkharbas@48369 2582 if (result != NULL) {
kkharbas@48369 2583 if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
kkharbas@48369 2584 vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
kkharbas@48369 2585 }
kkharbas@48369 2586 }
kkharbas@48369 2587 return result;
kkharbas@48369 2588 }
kkharbas@48369 2589
simonis@22831 2590 // Reserve memory at an arbitrary address, only if that area is
simonis@22831 2591 // available (and not reserved for something else).
simonis@22831 2592 char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
simonis@22831 2593 char* addr = NULL;
goetz@30198 2594
goetz@30198 2595 // Always round to os::vm_page_size(), which may be larger than 4K.
stefank@46619 2596 bytes = align_up(bytes, os::vm_page_size());
goetz@30198 2597
goetz@30198 2598 // In 4K mode always use mmap.
goetz@30198 2599 // In 64K mode allocate small sizes with mmap, large ones with 64K shmatted.
simonis@42061 2600 if (os::vm_page_size() == 4*K) {
goetz@30198 2601 return reserve_mmaped_memory(bytes, requested_addr, 0);
simonis@22831 2602 } else {
goetz@30198 2603 if (bytes >= Use64KPagesThreshold) {
goetz@30198 2604 return reserve_shmated_memory(bytes, requested_addr, 0);
goetz@30198 2605 } else {
goetz@30198 2606 return reserve_mmaped_memory(bytes, requested_addr, 0);
simonis@22831 2607 }
simonis@22831 2608 }
simonis@22831 2609
simonis@22831 2610 return addr;
simonis@22831 2611 }
simonis@22831 2612
simonis@22831 2613 size_t os::read(int fd, void *buf, unsigned int nBytes) {
simonis@22831 2614 return ::read(fd, buf, nBytes);
simonis@22831 2615 }
simonis@22831 2616
chegar@27562 2617 size_t os::read_at(int fd, void *buf, unsigned int nBytes, jlong offset) {
chegar@27562 2618 return ::pread(fd, buf, nBytes, offset);
chegar@27562 2619 }
chegar@27562 2620
goetz@22877 2621 void os::naked_short_sleep(jlong ms) {
goetz@22877 2622 struct timespec req;
goetz@22877 2623
goetz@22877 2624 assert(ms < 1000, "Un-interruptable sleep, short time use only");
goetz@22877 2625 req.tv_sec = 0;
goetz@22877 2626 if (ms > 0) {
goetz@22877 2627 req.tv_nsec = (ms % 1000) * 1000000;
goetz@22877 2628 }
goetz@22877 2629 else {
goetz@22877 2630 req.tv_nsec = 1;
goetz@22877 2631 }
goetz@22877 2632
goetz@22877 2633 nanosleep(&req, NULL);
goetz@22877 2634
goetz@22877 2635 return;
simonis@22831 2636 }
simonis@22831 2637
simonis@22831 2638 // Sleep forever; naked call to OS-specific sleep; use with CAUTION
simonis@22831 2639 void os::infinite_sleep() {
simonis@22831 2640 while (true) { // sleep forever ...
simonis@22831 2641 ::sleep(100); // ... 100 seconds at a time
simonis@22831 2642 }
simonis@22831 2643 }
simonis@22831 2644
simonis@22831 2645 // Used to convert frequent JVM_Yield() to nops
simonis@22831 2646 bool os::dont_yield() {
simonis@22831 2647 return DontYieldALot;
simonis@22831 2648 }
simonis@22831 2649
fparain@25477 2650 void os::naked_yield() {
simonis@22831 2651 sched_yield();
simonis@22831 2652 }
simonis@22831 2653
simonis@22831 2654 ////////////////////////////////////////////////////////////////////////////////
simonis@22831 2655 // thread priority support
simonis@22831 2656
simonis@22831 2657 // From AIX manpage to pthread_setschedparam
simonis@22831 2658 // (see: http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?
simonis@22831 2659 // topic=/com.ibm.aix.basetechref/doc/basetrf1/pthread_setschedparam.htm):
simonis@22831 2660 //
simonis@22831 2661 // "If schedpolicy is SCHED_OTHER, then sched_priority must be in the
simonis@22831 2662 // range from 40 to 80, where 40 is the least favored priority and 80
simonis@22831 2663 // is the most favored."
simonis@22831 2664 //
simonis@22831 2665 // (Actually, I doubt this even has an impact on AIX, as we do kernel
simonis@22831 2666 // scheduling there; however, this still leaves iSeries.)
simonis@22831 2667 //
simonis@22831 2668 // We use the same values for AIX and PASE.
simonis@22831 2669 int os::java_to_os_priority[CriticalPriority + 1] = {
simonis@22831 2670 54, // 0 Entry should never be used
simonis@22831 2671
simonis@22831 2672 55, // 1 MinPriority
simonis@22831 2673 55, // 2
simonis@22831 2674 56, // 3
simonis@22831 2675
simonis@22831 2676 56, // 4
simonis@22831 2677 57, // 5 NormPriority
simonis@22831 2678 57, // 6
simonis@22831 2679
simonis@22831 2680 58, // 7
simonis@22831 2681 58, // 8
simonis@22831 2682 59, // 9 NearMaxPriority
simonis@22831 2683
simonis@22831 2684 60, // 10 MaxPriority
simonis@22831 2685
simonis@22831 2686 60 // 11 CriticalPriority
simonis@22831 2687 };
simonis@22831 2688
simonis@22831 2689 OSReturn os::set_native_priority(Thread* thread, int newpri) {
simonis@22831 2690 if (!UseThreadPriorities) return OS_OK;
simonis@22831 2691 pthread_t thr = thread->osthread()->pthread_id();
simonis@22831 2692 int policy = SCHED_OTHER;
simonis@22831 2693 struct sched_param param;
simonis@22831 2694 param.sched_priority = newpri;
simonis@22831 2695 int ret = pthread_setschedparam(thr, policy, &param);
simonis@22831 2696
goetz@28187 2697 if (ret != 0) {
goetz@28187 2698 trcVerbose("Could not change priority for thread %d to %d (error %d, %s)",
stuefe@37113 2699 (int)thr, newpri, ret, os::errno_name(ret));
simonis@22831 2700 }
simonis@22831 2701 return (ret == 0) ? OS_OK : OS_ERR;
simonis@22831 2702 }
simonis@22831 2703
simonis@22831 2704 OSReturn os::get_native_priority(const Thread* const thread, int *priority_ptr) {
simonis@22831 2705 if (!UseThreadPriorities) {
simonis@22831 2706 *priority_ptr = java_to_os_priority[NormPriority];
simonis@22831 2707 return OS_OK;
simonis@22831 2708 }
simonis@22831 2709 pthread_t thr = thread->osthread()->pthread_id();
simonis@22831 2710 int policy = SCHED_OTHER;
simonis@22831 2711 struct sched_param param;
simonis@22831 2712 int ret = pthread_getschedparam(thr, &policy, &param);
simonis@22831 2713 *priority_ptr = param.sched_priority;
simonis@22831 2714
simonis@22831 2715 return (ret == 0) ? OS_OK : OS_ERR;
simonis@22831 2716 }
simonis@22831 2717
simonis@22831 2718 // Hint to the underlying OS that a task switch would not be good.
simonis@22831 2719 // Void return because it's a hint and can fail.
simonis@22831 2720 void os::hint_no_preempt() {}
simonis@22831 2721
simonis@22831 2722 ////////////////////////////////////////////////////////////////////////////////
simonis@22831 2723 // suspend/resume support
simonis@22831 2724
gziemski@47106 2725 // The low-level signal-based suspend/resume support is a remnant from the
simonis@22831 2726 // old VM-suspension that used to be for java-suspension, safepoints etc,
gziemski@47106 2727 // within hotspot. Currently used by JFR's OSThreadSampler
gziemski@47106 2728 //
simonis@22831 2729 // The remaining code is greatly simplified from the more general suspension
simonis@22831 2730 // code that used to be used.
simonis@22831 2731 //
simonis@22831 2732 // The protocol is quite simple:
simonis@22831 2733 // - suspend:
simonis@22831 2734 // - sends a signal to the target thread
simonis@22831 2735 // - polls the suspend state of the osthread using a yield loop
simonis@22831 2736 // - target thread signal handler (SR_handler) sets suspend state
simonis@22831 2737 // and blocks in sigsuspend until continued
simonis@22831 2738 // - resume:
simonis@22831 2739 // - sets target osthread state to continue
simonis@22831 2740 // - sends signal to end the sigsuspend loop in the SR_handler
simonis@22831 2741 //
dholmes@40377 2742 // Note that the SR_lock plays no role in this suspend/resume protocol,
dholmes@40377 2743 // but is checked for NULL in SR_handler as a thread termination indicator.
gziemski@47106 2744 // The SR_lock is, however, used by JavaThread::java_suspend()/java_resume() APIs.
simonis@22831 2745 //
gziemski@47106 2746 // Note that resume_clear_context() and suspend_save_context() are needed
gziemski@47106 2747 // by SR_handler(), so that fetch_frame_from_ucontext() works,
gziemski@47106 2748 // which in part is used by:
gziemski@47106 2749 // - Forte Analyzer: AsyncGetCallTrace()
gziemski@47106 2750 // - StackBanging: get_frame_at_stack_banging_point()
simonis@22831 2751
simonis@22831 2752 static void resume_clear_context(OSThread *osthread) {
simonis@22831 2753 osthread->set_ucontext(NULL);
simonis@22831 2754 osthread->set_siginfo(NULL);
simonis@22831 2755 }
simonis@22831 2756
simonis@22831 2757 static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontext_t* context) {
simonis@22831 2758 osthread->set_ucontext(context);
simonis@22831 2759 osthread->set_siginfo(siginfo);
simonis@22831 2760 }
simonis@22831 2761
simonis@22831 2762 //
simonis@22831 2763 // Handler function invoked when a thread's execution is suspended or
simonis@22831 2764 // resumed. We have to be careful that only async-safe functions are
simonis@22831 2765 // called here (Note: most pthread functions are not async safe and
simonis@22831 2766 // should be avoided.)
simonis@22831 2767 //
simonis@22831 2768 // Note: sigwait() is a more natural fit than sigsuspend() from an
simonis@22831 2769 // interface point of view, but sigwait() prevents the signal hander
simonis@22831 2770 // from being run. libpthread would get very confused by not having
simonis@22831 2771 // its signal handlers run and prevents sigwait()'s use with the
simonis@22831 2772 // mutex granting granting signal.
simonis@22831 2773 //
simonis@22831 2774 // Currently only ever called on the VMThread and JavaThreads (PC sampling).
simonis@22831 2775 //
simonis@22831 2776 static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) {
simonis@22831 2777 // Save and restore errno to avoid confusing native code with EINTR
simonis@22831 2778 // after sigsuspend.
simonis@22831 2779 int old_errno = errno;
simonis@22831 2780
dholmes@40377 2781 Thread* thread = Thread::current_or_null_safe();
dholmes@40377 2782 assert(thread != NULL, "Missing current thread in SR_handler");
dholmes@40377 2783
dholmes@40377 2784 // On some systems we have seen signal delivery get "stuck" until the signal
dholmes@40377 2785 // mask is changed as part of thread termination. Check that the current thread
dholmes@40377 2786 // has not already terminated (via SR_lock()) - else the following assertion
dholmes@40377 2787 // will fail because the thread is no longer a JavaThread as the ~JavaThread
dholmes@40377 2788 // destructor has completed.
dholmes@40377 2789
dholmes@40377 2790 if (thread->SR_lock() == NULL) {
dholmes@40377 2791 return;
dholmes@40377 2792 }
dholmes@40377 2793
dholmes@40377 2794 assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
dholmes@40377 2795
simonis@22831 2796 OSThread* osthread = thread->osthread();
simonis@22831 2797
simonis@22831 2798 os::SuspendResume::State current = osthread->sr.state();
simonis@22831 2799 if (current == os::SuspendResume::SR_SUSPEND_REQUEST) {
simonis@22831 2800 suspend_save_context(osthread, siginfo, context);
simonis@22831 2801
simonis@22831 2802 // attempt to switch the state, we assume we had a SUSPEND_REQUEST
simonis@22831 2803 os::SuspendResume::State state = osthread->sr.suspended();
simonis@22831 2804 if (state == os::SuspendResume::SR_SUSPENDED) {
simonis@22831 2805 sigset_t suspend_set; // signals for sigsuspend()
simonis@22831 2806
simonis@22831 2807 // get current set of blocked signals and unblock resume signal
simonis@22831 2808 pthread_sigmask(SIG_BLOCK, NULL, &suspend_set);
simonis@22831 2809 sigdelset(&suspend_set, SR_signum);
simonis@22831 2810
simonis@22831 2811 // wait here until we are resumed
simonis@22831 2812 while (1) {
simonis@22831 2813 sigsuspend(&suspend_set);
simonis@22831 2814
simonis@22831 2815 os::SuspendResume::State result = osthread->sr.running();
simonis@22831 2816 if (result == os::SuspendResume::SR_RUNNING) {
simonis@22831 2817 break;
simonis@22831 2818 }
simonis@22831 2819 }
simonis@22831 2820
simonis@22831 2821 } else if (state == os::SuspendResume::SR_RUNNING) {
simonis@22831 2822 // request was cancelled, continue
simonis@22831 2823 } else {
simonis@22831 2824 ShouldNotReachHere();
simonis@22831 2825 }
simonis@22831 2826
simonis@22831 2827 resume_clear_context(osthread);
simonis@22831 2828 } else if (current == os::SuspendResume::SR_RUNNING) {
simonis@22831 2829 // request was cancelled, continue
simonis@22831 2830 } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) {
simonis@22831 2831 // ignore
simonis@22831 2832 } else {
simonis@22831 2833 ShouldNotReachHere();
simonis@22831 2834 }
simonis@22831 2835
simonis@22831 2836 errno = old_errno;
simonis@22831 2837 }
simonis@22831 2838
simonis@22831 2839 static int SR_initialize() {
simonis@22831 2840 struct sigaction act;
simonis@22831 2841 char *s;
simonis@22831 2842 // Get signal number to use for suspend/resume
simonis@22831 2843 if ((s = ::getenv("_JAVA_SR_SIGNUM")) != 0) {
simonis@22831 2844 int sig = ::strtol(s, 0, 10);
goetz@34145 2845 if (sig > MAX2(SIGSEGV, SIGBUS) && // See 4355769.
goetz@34145 2846 sig < NSIG) { // Must be legal signal and fit into sigflags[].
simonis@22831 2847 SR_signum = sig;
goetz@34145 2848 } else {
goetz@34145 2849 warning("You set _JAVA_SR_SIGNUM=%d. It must be in range [%d, %d]. Using %d instead.",
goetz@34145 2850 sig, MAX2(SIGSEGV, SIGBUS)+1, NSIG-1, SR_signum);
simonis@22831 2851 }
simonis@22831 2852 }
simonis@22831 2853
simonis@22831 2854 assert(SR_signum > SIGSEGV && SR_signum > SIGBUS,
simonis@22831 2855 "SR_signum must be greater than max(SIGSEGV, SIGBUS), see 4355769");
simonis@22831 2856
simonis@22831 2857 sigemptyset(&SR_sigset);
simonis@22831 2858 sigaddset(&SR_sigset, SR_signum);
simonis@22831 2859
simonis@22831 2860 // Set up signal handler for suspend/resume.
simonis@22831 2861 act.sa_flags = SA_RESTART|SA_SIGINFO;
simonis@22831 2862 act.sa_handler = (void (*)(int)) SR_handler;
simonis@22831 2863
simonis@22831 2864 // SR_signum is blocked by default.
simonis@22831 2865 pthread_sigmask(SIG_BLOCK, NULL, &act.sa_mask);
simonis@22831 2866
simonis@22831 2867 if (sigaction(SR_signum, &act, 0) == -1) {
simonis@22831 2868 return -1;
simonis@22831 2869 }
simonis@22831 2870
simonis@22831 2871 // Save signal flag
simonis@22831 2872 os::Aix::set_our_sigflags(SR_signum, act.sa_flags);
simonis@22831 2873 return 0;
simonis@22831 2874 }
simonis@22831 2875
simonis@22831 2876 static int SR_finalize() {
simonis@22831 2877 return 0;
simonis@22831 2878 }
simonis@22831 2879
simonis@22831 2880 static int sr_notify(OSThread* osthread) {
simonis@22831 2881 int status = pthread_kill(osthread->pthread_id(), SR_signum);
simonis@22831 2882 assert_status(status == 0, status, "pthread_kill");
simonis@22831 2883 return status;
simonis@22831 2884 }
simonis@22831 2885
simonis@22831 2886 // "Randomly" selected value for how long we want to spin
simonis@22831 2887 // before bailing out on suspending a thread, also how often
simonis@22831 2888 // we send a signal to a thread we want to resume
simonis@22831 2889 static const int RANDOMLY_LARGE_INTEGER = 1000000;
simonis@22831 2890 static const int RANDOMLY_LARGE_INTEGER2 = 100;
simonis@22831 2891
simonis@22831 2892 // returns true on success and false on error - really an error is fatal
simonis@22831 2893 // but this seems the normal response to library errors
simonis@22831 2894 static bool do_suspend(OSThread* osthread) {
simonis@22831 2895 assert(osthread->sr.is_running(), "thread should be running");
simonis@22831 2896 // mark as suspended and send signal
simonis@22831 2897
simonis@22831 2898 if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) {
simonis@22831 2899 // failed to switch, state wasn't running?
simonis@22831 2900 ShouldNotReachHere();
simonis@22831 2901 return false;
simonis@22831 2902 }
simonis@22831 2903
simonis@22831 2904 if (sr_notify(osthread) != 0) {
simonis@22831 2905 // try to cancel, switch to running
simonis@22831 2906
simonis@22831 2907 os::SuspendResume::State result = osthread->sr.cancel_suspend();
simonis@22831 2908 if (result == os::SuspendResume::SR_RUNNING) {
simonis@22831 2909 // cancelled
simonis@22831 2910 return false;
simonis@22831 2911 } else if (result == os::SuspendResume::SR_SUSPENDED) {
simonis@22831 2912 // somehow managed to suspend
simonis@22831 2913 return true;
simonis@22831 2914 } else {
simonis@22831 2915 ShouldNotReachHere();
simonis@22831 2916 return false;
simonis@22831 2917 }
simonis@22831 2918 }
simonis@22831 2919
simonis@22831 2920 // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
simonis@22831 2921
simonis@22831 2922 for (int n = 0; !osthread->sr.is_suspended(); n++) {
simonis@22831 2923 for (int i = 0; i < RANDOMLY_LARGE_INTEGER2 && !osthread->sr.is_suspended(); i++) {
fparain@25477 2924 os::naked_yield();
simonis@22831 2925 }
simonis@22831 2926
simonis@22831 2927 // timeout, try to cancel the request
simonis@22831 2928 if (n >= RANDOMLY_LARGE_INTEGER) {
simonis@22831 2929 os::SuspendResume::State cancelled = osthread->sr.cancel_suspend();
simonis@22831 2930 if (cancelled == os::SuspendResume::SR_RUNNING) {
simonis@22831 2931 return false;
simonis@22831 2932 } else if (cancelled == os::SuspendResume::SR_SUSPENDED) {
simonis@22831 2933 return true;
simonis@22831 2934 } else {
simonis@22831 2935 ShouldNotReachHere();
simonis@22831 2936 return false;
simonis@22831 2937 }
simonis@22831 2938 }
simonis@22831 2939 }
simonis@22831 2940
simonis@22831 2941 guarantee(osthread->sr.is_suspended(), "Must be suspended");
simonis@22831 2942 return true;
simonis@22831 2943 }
simonis@22831 2944
simonis@22831 2945 static void do_resume(OSThread* osthread) {
simonis@22831 2946 //assert(osthread->sr.is_suspended(), "thread should be suspended");
simonis@22831 2947
simonis@22831 2948 if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) {
simonis@22831 2949 // failed to switch to WAKEUP_REQUEST
simonis@22831 2950 ShouldNotReachHere();
simonis@22831 2951 return;
simonis@22831 2952 }
simonis@22831 2953
simonis@22831 2954 while (!osthread->sr.is_running()) {
simonis@22831 2955 if (sr_notify(osthread) == 0) {
simonis@22831 2956 for (int n = 0; n < RANDOMLY_LARGE_INTEGER && !osthread->sr.is_running(); n++) {
simonis@22831 2957 for (int i = 0; i < 100 && !osthread->sr.is_running(); i++) {
fparain@25477 2958 os::naked_yield();
simonis@22831 2959 }
simonis@22831 2960 }
simonis@22831 2961 } else {
simonis@22831 2962 ShouldNotReachHere();
simonis@22831 2963 }
simonis@22831 2964 }
simonis@22831 2965
simonis@22831 2966 guarantee(osthread->sr.is_running(), "Must be running!");
simonis@22831 2967 }
simonis@22831 2968
simonis@22831 2969 ///////////////////////////////////////////////////////////////////////////////////
simonis@22831 2970 // signal handling (except suspend/resume)
simonis@22831 2971
simonis@22831 2972 // This routine may be used by user applications as a "hook" to catch signals.
simonis@22831 2973 // The user-defined signal handler must pass unrecognized signals to this
simonis@22831 2974 // routine, and if it returns true (non-zero), then the signal handler must
simonis@22831 2975 // return immediately. If the flag "abort_if_unrecognized" is true, then this
simonis@22831 2976 // routine will never retun false (zero), but instead will execute a VM panic
simonis@22831 2977 // routine kill the process.
simonis@22831 2978 //
simonis@22831 2979 // If this routine returns false, it is OK to call it again. This allows
simonis@22831 2980 // the user-defined signal handler to perform checks either before or after
simonis@22831 2981 // the VM performs its own checks. Naturally, the user code would be making
simonis@22831 2982 // a serious error if it tried to handle an exception (such as a null check
simonis@22831 2983 // or breakpoint) that the VM was generating for its own correct operation.
simonis@22831 2984 //
simonis@22831 2985 // This routine may recognize any of the following kinds of signals:
simonis@22831 2986 // SIGBUS, SIGSEGV, SIGILL, SIGFPE, SIGQUIT, SIGPIPE, SIGXFSZ, SIGUSR1.
simonis@22831 2987 // It should be consulted by handlers for any of those signals.
simonis@22831 2988 //
simonis@22831 2989 // The caller of this routine must pass in the three arguments supplied
simonis@22831 2990 // to the function referred to in the "sa_sigaction" (not the "sa_handler")
simonis@22831 2991 // field of the structure passed to sigaction(). This routine assumes that
simonis@22831 2992 // the sa_flags field passed to sigaction() includes SA_SIGINFO and SA_RESTART.
simonis@22831 2993 //
simonis@22831 2994 // Note that the VM will print warnings if it detects conflicting signal
simonis@22831 2995 // handlers, unless invoked with the option "-XX:+AllowUserSignalHandlers".
simonis@22831 2996 //
simonis@22831 2997 extern "C" JNIEXPORT int
simonis@22831 2998 JVM_handle_aix_signal(int signo, siginfo_t* siginfo, void* ucontext, int abort_if_unrecognized);
simonis@22831 2999
simonis@22831 3000 // Set thread signal mask (for some reason on AIX sigthreadmask() seems
simonis@22831 3001 // to be the thing to call; documentation is not terribly clear about whether
simonis@22831 3002 // pthread_sigmask also works, and if it does, whether it does the same.
simonis@22831 3003 bool set_thread_signal_mask(int how, const sigset_t* set, sigset_t* oset) {
simonis@22831 3004 const int rc = ::pthread_sigmask(how, set, oset);
simonis@22831 3005 // return value semantics differ slightly for error case:
simonis@22831 3006 // pthread_sigmask returns error number, sigthreadmask -1 and sets global errno
simonis@22831 3007 // (so, pthread_sigmask is more theadsafe for error handling)
simonis@22831 3008 // But success is always 0.
simonis@22831 3009 return rc == 0 ? true : false;
simonis@22831 3010 }
simonis@22831 3011
simonis@22831 3012 // Function to unblock all signals which are, according
simonis@22831 3013 // to POSIX, typical program error signals. If they happen while being blocked,
simonis@22831 3014 // they typically will bring down the process immediately.
simonis@22831 3015 bool unblock_program_error_signals() {
simonis@22831 3016 sigset_t set;
simonis@22831 3017 ::sigemptyset(&set);
simonis@22831 3018 ::sigaddset(&set, SIGILL);
simonis@22831 3019 ::sigaddset(&set, SIGBUS);
simonis@22831 3020 ::sigaddset(&set, SIGFPE);
simonis@22831 3021 ::sigaddset(&set, SIGSEGV);
simonis@22831 3022 return set_thread_signal_mask(SIG_UNBLOCK, &set, NULL);
simonis@22831 3023 }
simonis@22831 3024
simonis@22831 3025 // Renamed from 'signalHandler' to avoid collision with other shared libs.
coleenp@50768 3026 static void javaSignalHandler(int sig, siginfo_t* info, void* uc) {
simonis@22831 3027 assert(info != NULL && uc != NULL, "it must be old kernel");
simonis@22831 3028
simonis@22831 3029 // Never leave program error signals blocked;
simonis@22831 3030 // on all our platforms they would bring down the process immediately when
simonis@22831 3031 // getting raised while being blocked.
simonis@22831 3032 unblock_program_error_signals();
simonis@22831 3033
stuefe@34647 3034 int orig_errno = errno; // Preserve errno value over signal handler.
simonis@22831 3035 JVM_handle_aix_signal(sig, info, uc, true);
stuefe@34647 3036 errno = orig_errno;
simonis@22831 3037 }
simonis@22831 3038
simonis@22831 3039 // This boolean allows users to forward their own non-matching signals
simonis@22831 3040 // to JVM_handle_aix_signal, harmlessly.
simonis@22831 3041 bool os::Aix::signal_handlers_are_installed = false;
simonis@22831 3042
simonis@22831 3043 // For signal-chaining
goetz@34145 3044 struct sigaction sigact[NSIG];
goetz@34145 3045 sigset_t sigs;
simonis@22831 3046 bool os::Aix::libjsig_is_loaded = false;
simonis@22831 3047 typedef struct sigaction *(*get_signal_t)(int);
simonis@22831 3048 get_signal_t os::Aix::get_signal_action = NULL;
simonis@22831 3049
simonis@22831 3050 struct sigaction* os::Aix::get_chained_signal_action(int sig) {
simonis@22831 3051 struct sigaction *actp = NULL;
simonis@22831 3052
simonis@22831 3053 if (libjsig_is_loaded) {
simonis@22831 3054 // Retrieve the old signal handler from libjsig
simonis@22831 3055 actp = (*get_signal_action)(sig);
simonis@22831 3056 }
simonis@22831 3057 if (actp == NULL) {
simonis@22831 3058 // Retrieve the preinstalled signal handler from jvm
simonis@22831 3059 actp = get_preinstalled_handler(sig);
simonis@22831 3060 }
simonis@22831 3061
simonis@22831 3062 return actp;
simonis@22831 3063 }
simonis@22831 3064
simonis@22831 3065 static bool call_chained_handler(struct sigaction *actp, int sig,
simonis@22831 3066 siginfo_t *siginfo, void *context) {
goetz@22867 3067 // Call the old signal handler
goetz@22867 3068 if (actp->sa_handler == SIG_DFL) {
goetz@22867 3069 // It's more reasonable to let jvm treat it as an unexpected exception
goetz@22867 3070 // instead of taking the default action.
goetz@22867 3071 return false;
goetz@22867 3072 } else if (actp->sa_handler != SIG_IGN) {
goetz@22867 3073 if ((actp->sa_flags & SA_NODEFER) == 0) {
goetz@22867 3074 // automaticlly block the signal
goetz@22867 3075 sigaddset(&(actp->sa_mask), sig);
goetz@22867 3076 }
goetz@22867 3077
goetz@22867 3078 sa_handler_t hand = NULL;
goetz@22867 3079 sa_sigaction_t sa = NULL;
goetz@22867 3080 bool siginfo_flag_set = (actp->sa_flags & SA_SIGINFO) != 0;
goetz@22867 3081 // retrieve the chained handler
goetz@22867 3082 if (siginfo_flag_set) {
goetz@22867 3083 sa = actp->sa_sigaction;
goetz@22867 3084 } else {
goetz@22867 3085 hand = actp->sa_handler;
goetz@22867 3086 }
goetz@22867 3087
goetz@22867 3088 if ((actp->sa_flags & SA_RESETHAND) != 0) {
goetz@22867 3089 actp->sa_handler = SIG_DFL;
goetz@22867 3090 }
goetz@22867 3091
goetz@22867 3092 // try to honor the signal mask
goetz@22867 3093 sigset_t oset;
goetz@22867 3094 pthread_sigmask(SIG_SETMASK, &(actp->sa_mask), &oset);
goetz@22867 3095
goetz@22867 3096 // call into the chained handler
goetz@22867 3097 if (siginfo_flag_set) {
goetz@22867 3098 (*sa)(sig, siginfo, context);
goetz@22867 3099 } else {
goetz@22867 3100 (*hand)(sig);
goetz@22867 3101 }
goetz@22867 3102
goetz@22867 3103 // restore the signal mask
goetz@22867 3104 pthread_sigmask(SIG_SETMASK, &oset, 0);
goetz@22867 3105 }
goetz@22867 3106 // Tell jvm's signal handler the signal is taken care of.
simonis@22831 3107 return true;
simonis@22831 3108 }
simonis@22831 3109
simonis@22831 3110 bool os::Aix::chained_handler(int sig, siginfo_t* siginfo, void* context) {
simonis@22831 3111 bool chained = false;
simonis@22831 3112 // signal-chaining
simonis@22831 3113 if (UseSignalChaining) {
simonis@22831 3114 struct sigaction *actp = get_chained_signal_action(sig);
simonis@22831 3115 if (actp != NULL) {
simonis@22831 3116 chained = call_chained_handler(actp, sig, siginfo, context);
simonis@22831 3117 }
simonis@22831 3118 }
simonis@22831 3119 return chained;
simonis@22831 3120 }
simonis@22831 3121
simonis@22831 3122 struct sigaction* os::Aix::get_preinstalled_handler(int sig) {
goetz@34145 3123 if (sigismember(&sigs, sig)) {
simonis@22831 3124 return &sigact[sig];
simonis@22831 3125 }
simonis@22831 3126 return NULL;
simonis@22831 3127 }
simonis@22831 3128
simonis@22831 3129 void os::Aix::save_preinstalled_handler(int sig, struct sigaction& oldAct) {
goetz@34145 3130 assert(sig > 0 && sig < NSIG, "vm signal out of expected range");
simonis@22831 3131 sigact[sig] = oldAct;
goetz@34145 3132 sigaddset(&sigs, sig);
simonis@22831 3133 }
simonis@22831 3134
simonis@22831 3135 // for diagnostic
goetz@34145 3136 int sigflags[NSIG];
simonis@22831 3137
simonis@22831 3138 int os::Aix::get_our_sigflags(int sig) {
goetz@34145 3139 assert(sig > 0 && sig < NSIG, "vm signal out of expected range");
simonis@22831 3140 return sigflags[sig];
simonis@22831 3141 }
simonis@22831 3142
simonis@22831 3143 void os::Aix::set_our_sigflags(int sig, int flags) {
goetz@34145 3144 assert(sig > 0 && sig < NSIG, "vm signal out of expected range");
goetz@34145 3145 if (sig > 0 && sig < NSIG) {
goetz@34145 3146 sigflags[sig] = flags;
goetz@34145 3147 }
simonis@22831 3148 }
simonis@22831 3149
simonis@22831 3150 void os::Aix::set_signal_handler(int sig, bool set_installed) {
simonis@22831 3151 // Check for overwrite.
simonis@22831 3152 struct sigaction oldAct;
simonis@22831 3153 sigaction(sig, (struct sigaction*)NULL, &oldAct);
simonis@22831 3154
simonis@22831 3155 void* oldhand = oldAct.sa_sigaction
simonis@22831 3156 ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction)
simonis@22831 3157 : CAST_FROM_FN_PTR(void*, oldAct.sa_handler);
simonis@22831 3158 if (oldhand != CAST_FROM_FN_PTR(void*, SIG_DFL) &&
simonis@22831 3159 oldhand != CAST_FROM_FN_PTR(void*, SIG_IGN) &&
simonis@22831 3160 oldhand != CAST_FROM_FN_PTR(void*, (sa_sigaction_t)javaSignalHandler)) {
simonis@22831 3161 if (AllowUserSignalHandlers || !set_installed) {
simonis@22831 3162 // Do not overwrite; user takes responsibility to forward to us.
simonis@22831 3163 return;
simonis@22831 3164 } else if (UseSignalChaining) {
simonis@22831 3165 // save the old handler in jvm
simonis@22831 3166 save_preinstalled_handler(sig, oldAct);
simonis@22831 3167 // libjsig also interposes the sigaction() call below and saves the
simonis@22831 3168 // old sigaction on it own.
simonis@22831 3169 } else {
david@33105 3170 fatal("Encountered unexpected pre-existing sigaction handler "
david@33105 3171 "%#lx for signal %d.", (long)oldhand, sig);
simonis@22831 3172 }
simonis@22831 3173 }
simonis@22831 3174
simonis@22831 3175 struct sigaction sigAct;
simonis@22831 3176 sigfillset(&(sigAct.sa_mask));
simonis@22831 3177 if (!set_installed) {
simonis@22831 3178 sigAct.sa_handler = SIG_DFL;
simonis@22831 3179 sigAct.sa_flags = SA_RESTART;
simonis@22831 3180 } else {
simonis@22831 3181 sigAct.sa_sigaction = javaSignalHandler;
simonis@22831 3182 sigAct.sa_flags = SA_SIGINFO|SA_RESTART;
simonis@22831 3183 }
simonis@22831 3184 // Save flags, which are set by ours
goetz@34145 3185 assert(sig > 0 && sig < NSIG, "vm signal out of expected range");
simonis@22831 3186 sigflags[sig] = sigAct.sa_flags;
simonis@22831 3187
simonis@22831 3188 int ret = sigaction(sig, &sigAct, &oldAct);
simonis@22831 3189 assert(ret == 0, "check");
simonis@22831 3190
simonis@22831 3191 void* oldhand2 = oldAct.sa_sigaction
simonis@22831 3192 ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction)
simonis@22831 3193 : CAST_FROM_FN_PTR(void*, oldAct.sa_handler);
simonis@22831 3194 assert(oldhand2 == oldhand, "no concurrent signal handler installation");
simonis@22831 3195 }
simonis@22831 3196
simonis@22831 3197 // install signal handlers for signals that HotSpot needs to
simonis@22831 3198 // handle in order to support Java-level exception handling.
simonis@22831 3199 void os::Aix::install_signal_handlers() {
simonis@22831 3200 if (!signal_handlers_are_installed) {
simonis@22831 3201 signal_handlers_are_installed = true;
simonis@22831 3202
simonis@22831 3203 // signal-chaining
simonis@22831 3204 typedef void (*signal_setting_t)();
simonis@22831 3205 signal_setting_t begin_signal_setting = NULL;
simonis@22831 3206 signal_setting_t end_signal_setting = NULL;
simonis@22831 3207 begin_signal_setting = CAST_TO_FN_PTR(signal_setting_t,
simonis@22831 3208 dlsym(RTLD_DEFAULT, "JVM_begin_signal_setting"));
simonis@22831 3209 if (begin_signal_setting != NULL) {
simonis@22831 3210 end_signal_setting = CAST_TO_FN_PTR(signal_setting_t,
simonis@22831 3211 dlsym(RTLD_DEFAULT, "JVM_end_signal_setting"));
simonis@22831 3212 get_signal_action = CAST_TO_FN_PTR(get_signal_t,
simonis@22831 3213 dlsym(RTLD_DEFAULT, "JVM_get_signal_action"));
simonis@22831 3214 libjsig_is_loaded = true;
simonis@22831 3215 assert(UseSignalChaining, "should enable signal-chaining");
simonis@22831 3216 }
simonis@22831 3217 if (libjsig_is_loaded) {
goetz@34145 3218 // Tell libjsig jvm is setting signal handlers.
simonis@22831 3219 (*begin_signal_setting)();
simonis@22831 3220 }
simonis@22831 3221
goetz@34145 3222 ::sigemptyset(&sigs);
simonis@22831 3223 set_signal_handler(SIGSEGV, true);
simonis@22831 3224 set_signal_handler(SIGPIPE, true);
simonis@22831 3225 set_signal_handler(SIGBUS, true);
simonis@22831 3226 set_signal_handler(SIGILL, true);
simonis@22831 3227 set_signal_handler(SIGFPE, true);
simonis@22831 3228 set_signal_handler(SIGTRAP, true);
simonis@22831 3229 set_signal_handler(SIGXFSZ, true);
simonis@22831 3230
simonis@22831 3231 if (libjsig_is_loaded) {
goetz@28187 3232 // Tell libjsig jvm finishes setting signal handlers.
simonis@22831 3233 (*end_signal_setting)();
simonis@22831 3234 }
simonis@22831 3235
simonis@22831 3236 // We don't activate signal checker if libjsig is in place, we trust ourselves
simonis@22831 3237 // and if UserSignalHandler is installed all bets are off.
simonis@22831 3238 // Log that signal checking is off only if -verbose:jni is specified.
simonis@22831 3239 if (CheckJNICalls) {
simonis@22831 3240 if (libjsig_is_loaded) {
simonis@22831 3241 tty->print_cr("Info: libjsig is activated, all active signal checking is disabled");
simonis@22831 3242 check_signals = false;
simonis@22831 3243 }
simonis@22831 3244 if (AllowUserSignalHandlers) {
simonis@22831 3245 tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled");
simonis@22831 3246 check_signals = false;
simonis@22831 3247 }
goetz@28187 3248 // Need to initialize check_signal_done.
simonis@22831 3249 ::sigemptyset(&check_signal_done);
simonis@22831 3250 }
simonis@22831 3251 }
simonis@22831 3252 }
simonis@22831 3253
simonis@22831 3254 static const char* get_signal_handler_name(address handler,
simonis@22831 3255 char* buf, int buflen) {
simonis@22831 3256 int offset;
simonis@22831 3257 bool found = os::dll_address_to_library_name(handler, buf, buflen, &offset);
simonis@22831 3258 if (found) {
simonis@22831 3259 // skip directory names
simonis@22831 3260 const char *p1, *p2;
simonis@22831