Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/os/posix/vm/os_posix.cpp
32285 views
/*1* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "utilities/globalDefinitions.hpp"25#include "prims/jvm.h"26#include "runtime/frame.inline.hpp"27#include "runtime/os.hpp"28#include "utilities/vmError.hpp"2930#include <signal.h>31#include <unistd.h>32#include <sys/resource.h>33#include <sys/utsname.h>34#include <pthread.h>35#include <signal.h>3637PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC3839// Todo: provide a os::get_max_process_id() or similar. Number of processes40// may have been configured, can be read more accurately from proc fs etc.41#ifndef MAX_PID42#define MAX_PID INT_MAX43#endif44#define IS_VALID_PID(p) (p > 0 && p < MAX_PID)4546// Check core dump limit and report possible place where core can be found47void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) {48int n;49struct rlimit rlim;50bool success;5152n = get_core_path(buffer, bufferSize);5354if (getrlimit(RLIMIT_CORE, &rlim) != 0) {55jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (may not exist)", current_process_id());56success = true;57} else {58switch(rlim.rlim_cur) {59case RLIM_INFINITY:60jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d", current_process_id());61success = true;62break;63case 0:64jio_snprintf(buffer, bufferSize, "Core dumps have been disabled. To enable core dumping, try \"ulimit -c unlimited\" before starting Java again");65success = false;66break;67default:68jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (max size %lu kB). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", current_process_id(), (unsigned long)(rlim.rlim_cur >> 10));69success = true;70break;71}72}73VMError::report_coredump_status(buffer, success);74}7576int os::get_native_stack(address* stack, int frames, int toSkip) {77#ifdef _NMT_NOINLINE_78toSkip++;79#endif8081int frame_idx = 0;82int num_of_frames; // number of frames captured83frame fr = os::current_frame();84while (fr.pc() && frame_idx < frames) {85if (toSkip > 0) {86toSkip --;87} else {88stack[frame_idx ++] = fr.pc();89}90if (fr.fp() == NULL || os::is_first_C_frame(&fr)91||fr.sender_pc() == NULL || fr.cb() != NULL) break;9293if (fr.sender_pc() && !os::is_first_C_frame(&fr)) {94fr = os::get_sender_for_C_frame(&fr);95} else {96break;97}98}99num_of_frames = frame_idx;100for (; frame_idx < frames; frame_idx ++) {101stack[frame_idx] = NULL;102}103104return num_of_frames;105}106107108bool os::unsetenv(const char* name) {109assert(name != NULL, "Null pointer");110return (::unsetenv(name) == 0);111}112113int os::get_last_error() {114return errno;115}116117bool os::is_debugger_attached() {118// not implemented119return false;120}121122void os::wait_for_keypress_at_exit(void) {123// don't do anything on posix platforms124return;125}126127// Multiple threads can race in this code, and can remap over each other with MAP_FIXED,128// so on posix, unmap the section at the start and at the end of the chunk that we mapped129// rather than unmapping and remapping the whole chunk to get requested alignment.130char* os::reserve_memory_aligned(size_t size, size_t alignment MACOS_AARCH64_ONLY(, bool exec)) {131assert((alignment & (os::vm_allocation_granularity() - 1)) == 0,132"Alignment must be a multiple of allocation granularity (page size)");133assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned");134135size_t extra_size = size + alignment;136assert(extra_size >= size, "overflow, size is too large to allow alignment");137138char* extra_base = os::reserve_memory(extra_size, NULL, alignment MACOS_AARCH64_ONLY(, exec));139140if (extra_base == NULL) {141return NULL;142}143144// Do manual alignment145char* aligned_base = (char*) align_size_up((uintptr_t) extra_base, alignment);146147// [ | | ]148// ^ extra_base149// ^ extra_base + begin_offset == aligned_base150// extra_base + begin_offset + size ^151// extra_base + extra_size ^152// |<>| == begin_offset153// end_offset == |<>|154size_t begin_offset = aligned_base - extra_base;155size_t end_offset = (extra_base + extra_size) - (aligned_base + size);156157if (begin_offset > 0) {158os::release_memory(extra_base, begin_offset);159}160161if (end_offset > 0) {162os::release_memory(extra_base + begin_offset + size, end_offset);163}164165return aligned_base;166}167168int os::vsnprintf(char* buf, size_t len, const char* fmt, va_list args) {169int result = ::vsnprintf(buf, len, fmt, args);170// If an encoding error occurred (result < 0) then it's not clear171// whether the buffer is NUL terminated, so ensure it is.172if ((result < 0) && (len > 0)) {173buf[len - 1] = '\0';174}175return result;176}177178void os::Posix::print_load_average(outputStream* st) {179st->print("load average:");180double loadavg[3];181os::loadavg(loadavg, 3);182st->print("%0.02f %0.02f %0.02f", loadavg[0], loadavg[1], loadavg[2]);183st->cr();184}185186void os::Posix::print_rlimit_info(outputStream* st) {187st->print("rlimit:");188struct rlimit rlim;189190st->print(" STACK ");191getrlimit(RLIMIT_STACK, &rlim);192if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");193else st->print("%uk", rlim.rlim_cur >> 10);194195st->print(", CORE ");196getrlimit(RLIMIT_CORE, &rlim);197if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");198else st->print("%uk", rlim.rlim_cur >> 10);199200// Isn't there on solaris201#if !defined(TARGET_OS_FAMILY_solaris) && !defined(TARGET_OS_FAMILY_aix)202st->print(", NPROC ");203getrlimit(RLIMIT_NPROC, &rlim);204if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");205else st->print("%d", rlim.rlim_cur);206#endif207208st->print(", NOFILE ");209getrlimit(RLIMIT_NOFILE, &rlim);210if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");211else st->print("%d", rlim.rlim_cur);212213st->print(", AS ");214getrlimit(RLIMIT_AS, &rlim);215if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity");216else st->print("%uk", rlim.rlim_cur >> 10);217st->cr();218}219220void os::Posix::print_uname_info(outputStream* st) {221// kernel222st->print("uname:");223struct utsname name;224uname(&name);225st->print("%s ", name.sysname);226st->print("%s ", name.release);227st->print("%s ", name.version);228st->print("%s", name.machine);229st->cr();230}231232bool os::has_allocatable_memory_limit(julong* limit) {233struct rlimit rlim;234int getrlimit_res = getrlimit(RLIMIT_AS, &rlim);235// if there was an error when calling getrlimit, assume that there is no limitation236// on virtual memory.237bool result;238if ((getrlimit_res != 0) || (rlim.rlim_cur == RLIM_INFINITY)) {239result = false;240} else {241*limit = (julong)rlim.rlim_cur;242result = true;243}244#ifdef _LP64245return result;246#else247// arbitrary virtual space limit for 32 bit Unices found by testing. If248// getrlimit above returned a limit, bound it with this limit. Otherwise249// directly use it.250const julong max_virtual_limit = (julong)3800*M;251if (result) {252*limit = MIN2(*limit, max_virtual_limit);253} else {254*limit = max_virtual_limit;255}256257// bound by actually allocatable memory. The algorithm uses two bounds, an258// upper and a lower limit. The upper limit is the current highest amount of259// memory that could not be allocated, the lower limit is the current highest260// amount of memory that could be allocated.261// The algorithm iteratively refines the result by halving the difference262// between these limits, updating either the upper limit (if that value could263// not be allocated) or the lower limit (if the that value could be allocated)264// until the difference between these limits is "small".265266// the minimum amount of memory we care about allocating.267const julong min_allocation_size = M;268269julong upper_limit = *limit;270271// first check a few trivial cases272if (is_allocatable(upper_limit) || (upper_limit <= min_allocation_size)) {273*limit = upper_limit;274} else if (!is_allocatable(min_allocation_size)) {275// we found that not even min_allocation_size is allocatable. Return it276// anyway. There is no point to search for a better value any more.277*limit = min_allocation_size;278} else {279// perform the binary search.280julong lower_limit = min_allocation_size;281while ((upper_limit - lower_limit) > min_allocation_size) {282julong temp_limit = ((upper_limit - lower_limit) / 2) + lower_limit;283temp_limit = align_size_down_(temp_limit, min_allocation_size);284if (is_allocatable(temp_limit)) {285lower_limit = temp_limit;286} else {287upper_limit = temp_limit;288}289}290*limit = lower_limit;291}292return true;293#endif294}295296const char* os::get_current_directory(char *buf, size_t buflen) {297return getcwd(buf, buflen);298}299300FILE* os::open(int fd, const char* mode) {301return ::fdopen(fd, mode);302}303304DIR* os::opendir(const char* dirname) {305assert(dirname != NULL, "just checking");306return ::opendir(dirname);307}308309struct dirent* os::readdir(DIR* dirp) {310assert(dirp != NULL, "just checking");311return ::readdir(dirp);312}313314int os::closedir(DIR *dirp) {315assert(dirp != NULL, "just checking");316return ::closedir(dirp);317}318319// Builds a platform dependent Agent_OnLoad_<lib_name> function name320// which is used to find statically linked in agents.321// Parameters:322// sym_name: Symbol in library we are looking for323// lib_name: Name of library to look in, NULL for shared libs.324// is_absolute_path == true if lib_name is absolute path to agent325// such as "/a/b/libL.so"326// == false if only the base name of the library is passed in327// such as "L"328char* os::build_agent_function_name(const char *sym_name, const char *lib_name,329bool is_absolute_path) {330char *agent_entry_name;331size_t len;332size_t name_len;333size_t prefix_len = strlen(JNI_LIB_PREFIX);334size_t suffix_len = strlen(JNI_LIB_SUFFIX);335const char *start;336337if (lib_name != NULL) {338len = name_len = strlen(lib_name);339if (is_absolute_path) {340// Need to strip path, prefix and suffix341if ((start = strrchr(lib_name, *os::file_separator())) != NULL) {342lib_name = ++start;343}344if (len <= (prefix_len + suffix_len)) {345return NULL;346}347lib_name += prefix_len;348name_len = strlen(lib_name) - suffix_len;349}350}351len = (lib_name != NULL ? name_len : 0) + strlen(sym_name) + 2;352agent_entry_name = NEW_C_HEAP_ARRAY_RETURN_NULL(char, len, mtThread);353if (agent_entry_name == NULL) {354return NULL;355}356strcpy(agent_entry_name, sym_name);357if (lib_name != NULL) {358strcat(agent_entry_name, "_");359strncat(agent_entry_name, lib_name, name_len);360}361return agent_entry_name;362}363364// Returned string is a constant. For unknown signals "UNKNOWN" is returned.365const char* os::Posix::get_signal_name(int sig, char* out, size_t outlen) {366367static const struct {368int sig; const char* name;369}370info[] =371{372{ SIGABRT, "SIGABRT" },373#ifdef SIGAIO374{ SIGAIO, "SIGAIO" },375#endif376{ SIGALRM, "SIGALRM" },377#ifdef SIGALRM1378{ SIGALRM1, "SIGALRM1" },379#endif380{ SIGBUS, "SIGBUS" },381#ifdef SIGCANCEL382{ SIGCANCEL, "SIGCANCEL" },383#endif384{ SIGCHLD, "SIGCHLD" },385#ifdef SIGCLD386{ SIGCLD, "SIGCLD" },387#endif388{ SIGCONT, "SIGCONT" },389#ifdef SIGCPUFAIL390{ SIGCPUFAIL, "SIGCPUFAIL" },391#endif392#ifdef SIGDANGER393{ SIGDANGER, "SIGDANGER" },394#endif395#ifdef SIGDIL396{ SIGDIL, "SIGDIL" },397#endif398#ifdef SIGEMT399{ SIGEMT, "SIGEMT" },400#endif401{ SIGFPE, "SIGFPE" },402#ifdef SIGFREEZE403{ SIGFREEZE, "SIGFREEZE" },404#endif405#ifdef SIGGFAULT406{ SIGGFAULT, "SIGGFAULT" },407#endif408#ifdef SIGGRANT409{ SIGGRANT, "SIGGRANT" },410#endif411{ SIGHUP, "SIGHUP" },412{ SIGILL, "SIGILL" },413{ SIGINT, "SIGINT" },414#ifdef SIGIO415{ SIGIO, "SIGIO" },416#endif417#ifdef SIGIOINT418{ SIGIOINT, "SIGIOINT" },419#endif420#ifdef SIGIOT421// SIGIOT is there for BSD compatibility, but on most Unices just a422// synonym for SIGABRT. The result should be "SIGABRT", not423// "SIGIOT".424#if (SIGIOT != SIGABRT )425{ SIGIOT, "SIGIOT" },426#endif427#endif428#ifdef SIGKAP429{ SIGKAP, "SIGKAP" },430#endif431{ SIGKILL, "SIGKILL" },432#ifdef SIGLOST433{ SIGLOST, "SIGLOST" },434#endif435#ifdef SIGLWP436{ SIGLWP, "SIGLWP" },437#endif438#ifdef SIGLWPTIMER439{ SIGLWPTIMER, "SIGLWPTIMER" },440#endif441#ifdef SIGMIGRATE442{ SIGMIGRATE, "SIGMIGRATE" },443#endif444#ifdef SIGMSG445{ SIGMSG, "SIGMSG" },446#endif447{ SIGPIPE, "SIGPIPE" },448#ifdef SIGPOLL449{ SIGPOLL, "SIGPOLL" },450#endif451#ifdef SIGPRE452{ SIGPRE, "SIGPRE" },453#endif454{ SIGPROF, "SIGPROF" },455#ifdef SIGPTY456{ SIGPTY, "SIGPTY" },457#endif458#ifdef SIGPWR459{ SIGPWR, "SIGPWR" },460#endif461{ SIGQUIT, "SIGQUIT" },462#ifdef SIGRECONFIG463{ SIGRECONFIG, "SIGRECONFIG" },464#endif465#ifdef SIGRECOVERY466{ SIGRECOVERY, "SIGRECOVERY" },467#endif468#ifdef SIGRESERVE469{ SIGRESERVE, "SIGRESERVE" },470#endif471#ifdef SIGRETRACT472{ SIGRETRACT, "SIGRETRACT" },473#endif474#ifdef SIGSAK475{ SIGSAK, "SIGSAK" },476#endif477{ SIGSEGV, "SIGSEGV" },478#ifdef SIGSOUND479{ SIGSOUND, "SIGSOUND" },480#endif481{ SIGSTOP, "SIGSTOP" },482{ SIGSYS, "SIGSYS" },483#ifdef SIGSYSERROR484{ SIGSYSERROR, "SIGSYSERROR" },485#endif486#ifdef SIGTALRM487{ SIGTALRM, "SIGTALRM" },488#endif489{ SIGTERM, "SIGTERM" },490#ifdef SIGTHAW491{ SIGTHAW, "SIGTHAW" },492#endif493{ SIGTRAP, "SIGTRAP" },494#ifdef SIGTSTP495{ SIGTSTP, "SIGTSTP" },496#endif497{ SIGTTIN, "SIGTTIN" },498{ SIGTTOU, "SIGTTOU" },499#ifdef SIGURG500{ SIGURG, "SIGURG" },501#endif502{ SIGUSR1, "SIGUSR1" },503{ SIGUSR2, "SIGUSR2" },504#ifdef SIGVIRT505{ SIGVIRT, "SIGVIRT" },506#endif507{ SIGVTALRM, "SIGVTALRM" },508#ifdef SIGWAITING509{ SIGWAITING, "SIGWAITING" },510#endif511#ifdef SIGWINCH512{ SIGWINCH, "SIGWINCH" },513#endif514#ifdef SIGWINDOW515{ SIGWINDOW, "SIGWINDOW" },516#endif517{ SIGXCPU, "SIGXCPU" },518{ SIGXFSZ, "SIGXFSZ" },519#ifdef SIGXRES520{ SIGXRES, "SIGXRES" },521#endif522{ -1, NULL }523};524525const char* ret = NULL;526527#ifdef SIGRTMIN528if (sig >= SIGRTMIN && sig <= SIGRTMAX) {529if (sig == SIGRTMIN) {530ret = "SIGRTMIN";531} else if (sig == SIGRTMAX) {532ret = "SIGRTMAX";533} else {534jio_snprintf(out, outlen, "SIGRTMIN+%d", sig - SIGRTMIN);535return out;536}537}538#endif539540if (sig > 0) {541for (int idx = 0; info[idx].sig != -1; idx ++) {542if (info[idx].sig == sig) {543ret = info[idx].name;544break;545}546}547}548549if (!ret) {550if (!is_valid_signal(sig)) {551ret = "INVALID";552} else {553ret = "UNKNOWN";554}555}556557jio_snprintf(out, outlen, ret);558return out;559}560561// Returns true if signal number is valid.562bool os::Posix::is_valid_signal(int sig) {563// MacOS not really POSIX compliant: sigaddset does not return564// an error for invalid signal numbers. However, MacOS does not565// support real time signals and simply seems to have just 33566// signals with no holes in the signal range.567#ifdef __APPLE__568return sig >= 1 && sig < NSIG;569#else570// Use sigaddset to check for signal validity.571sigset_t set;572if (sigaddset(&set, sig) == -1 && errno == EINVAL) {573return false;574}575return true;576#endif577}578579#define NUM_IMPORTANT_SIGS 32580// Returns one-line short description of a signal set in a user provided buffer.581const char* os::Posix::describe_signal_set_short(const sigset_t* set, char* buffer, size_t buf_size) {582assert(buf_size == (NUM_IMPORTANT_SIGS + 1), "wrong buffer size");583// Note: for shortness, just print out the first 32. That should584// cover most of the useful ones, apart from realtime signals.585for (int sig = 1; sig <= NUM_IMPORTANT_SIGS; sig++) {586const int rc = sigismember((sigset_t*)set, sig);587if (rc == -1 && errno == EINVAL) {588buffer[sig-1] = '?';589} else {590buffer[sig-1] = rc == 0 ? '0' : '1';591}592}593buffer[NUM_IMPORTANT_SIGS] = 0;594return buffer;595}596597// Prints one-line description of a signal set.598void os::Posix::print_signal_set_short(outputStream* st, const sigset_t* set) {599char buf[NUM_IMPORTANT_SIGS + 1];600os::Posix::describe_signal_set_short(set, buf, sizeof(buf));601st->print("%s", buf);602}603604// Writes one-line description of a combination of sigaction.sa_flags into a user605// provided buffer. Returns that buffer.606const char* os::Posix::describe_sa_flags(int flags, char* buffer, size_t size) {607char* p = buffer;608size_t remaining = size;609bool first = true;610int idx = 0;611612assert(buffer, "invalid argument");613614if (size == 0) {615return buffer;616}617618strncpy(buffer, "none", size);619620const struct {621// NB: i is an unsigned int here because SA_RESETHAND is on some622// systems 0x80000000, which is implicitly unsigned. Assignining623// it to an int field would be an overflow in unsigned-to-signed624// conversion.625unsigned int i;626const char* s;627} flaginfo [] = {628{ SA_NOCLDSTOP, "SA_NOCLDSTOP" },629{ SA_ONSTACK, "SA_ONSTACK" },630{ SA_RESETHAND, "SA_RESETHAND" },631{ SA_RESTART, "SA_RESTART" },632{ SA_SIGINFO, "SA_SIGINFO" },633{ SA_NOCLDWAIT, "SA_NOCLDWAIT" },634{ SA_NODEFER, "SA_NODEFER" },635#ifdef AIX636{ SA_ONSTACK, "SA_ONSTACK" },637{ SA_OLDSTYLE, "SA_OLDSTYLE" },638#endif639{ 0, NULL }640};641642for (idx = 0; flaginfo[idx].s && remaining > 1; idx++) {643if (flags & flaginfo[idx].i) {644if (first) {645jio_snprintf(p, remaining, "%s", flaginfo[idx].s);646first = false;647} else {648jio_snprintf(p, remaining, "|%s", flaginfo[idx].s);649}650const size_t len = strlen(p);651p += len;652remaining -= len;653}654}655656buffer[size - 1] = '\0';657658return buffer;659}660661// Prints one-line description of a combination of sigaction.sa_flags.662void os::Posix::print_sa_flags(outputStream* st, int flags) {663char buffer[0x100];664os::Posix::describe_sa_flags(flags, buffer, sizeof(buffer));665st->print("%s", buffer);666}667668// Helper function for os::Posix::print_siginfo_...():669// return a textual description for signal code.670struct enum_sigcode_desc_t {671const char* s_name;672const char* s_desc;673};674675static bool get_signal_code_description(const siginfo_t* si, enum_sigcode_desc_t* out) {676677const struct {678int sig; int code; const char* s_code; const char* s_desc;679} t1 [] = {680{ SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode." },681{ SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand." },682{ SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode." },683{ SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap." },684{ SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode." },685{ SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register." },686{ SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error." },687{ SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error." },688#if defined(IA64) && defined(LINUX)689{ SIGILL, ILL_BADIADDR, "ILL_BADIADDR", "Unimplemented instruction address" },690{ SIGILL, ILL_BREAK, "ILL_BREAK", "Application Break instruction" },691#endif692{ SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero." },693{ SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow." },694{ SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating-point divide by zero." },695{ SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating-point overflow." },696{ SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating-point underflow." },697{ SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating-point inexact result." },698{ SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating-point operation." },699{ SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range." },700{ SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object." },701{ SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for mapped object." },702#ifdef AIX703// no explanation found what keyerr would be704{ SIGSEGV, SEGV_KEYERR, "SEGV_KEYERR", "key error" },705#endif706#if defined(IA64) && !defined(AIX)707{ SIGSEGV, SEGV_PSTKOVF, "SEGV_PSTKOVF", "Paragraph stack overflow" },708#endif709#if defined(__sparc) && defined(SOLARIS)710// define Solaris Sparc M7 ADI SEGV signals711#if !defined(SEGV_ACCADI)712#define SEGV_ACCADI 3713#endif714{ SIGSEGV, SEGV_ACCADI, "SEGV_ACCADI", "ADI not enabled for mapped object." },715#if !defined(SEGV_ACCDERR)716#define SEGV_ACCDERR 4717#endif718{ SIGSEGV, SEGV_ACCDERR, "SEGV_ACCDERR", "ADI disrupting exception." },719#if !defined(SEGV_ACCPERR)720#define SEGV_ACCPERR 5721#endif722{ SIGSEGV, SEGV_ACCPERR, "SEGV_ACCPERR", "ADI precise exception." },723#endif // defined(__sparc) && defined(SOLARIS)724{ SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment." },725{ SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Nonexistent physical address." },726{ SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object-specific hardware error." },727{ SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint." },728{ SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap." },729{ SIGCHLD, CLD_EXITED, "CLD_EXITED", "Child has exited." },730{ SIGCHLD, CLD_KILLED, "CLD_KILLED", "Child has terminated abnormally and did not create a core file." },731{ SIGCHLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally and created a core file." },732{ SIGCHLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped." },733{ SIGCHLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped." },734{ SIGCHLD, CLD_CONTINUED,"CLD_CONTINUED","Stopped child has continued." },735#ifdef SIGPOLL736{ SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available." },737{ SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available." },738{ SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error." },739{ SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available." },740{ SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected. [Option End]" },741#endif742{ -1, -1, NULL, NULL }743};744745// Codes valid in any signal context.746const struct {747int code; const char* s_code; const char* s_desc;748} t2 [] = {749{ SI_USER, "SI_USER", "Signal sent by kill()." },750{ SI_QUEUE, "SI_QUEUE", "Signal sent by the sigqueue()." },751{ SI_TIMER, "SI_TIMER", "Signal generated by expiration of a timer set by timer_settime()." },752{ SI_ASYNCIO, "SI_ASYNCIO", "Signal generated by completion of an asynchronous I/O request." },753{ SI_MESGQ, "SI_MESGQ", "Signal generated by arrival of a message on an empty message queue." },754// Linux specific755#ifdef SI_TKILL756{ SI_TKILL, "SI_TKILL", "Signal sent by tkill (pthread_kill)" },757#endif758#ifdef SI_DETHREAD759{ SI_DETHREAD, "SI_DETHREAD", "Signal sent by execve() killing subsidiary threads" },760#endif761#ifdef SI_KERNEL762{ SI_KERNEL, "SI_KERNEL", "Signal sent by kernel." },763#endif764#ifdef SI_SIGIO765{ SI_SIGIO, "SI_SIGIO", "Signal sent by queued SIGIO" },766#endif767768#ifdef AIX769{ SI_UNDEFINED, "SI_UNDEFINED","siginfo contains partial information" },770{ SI_EMPTY, "SI_EMPTY", "siginfo contains no useful information" },771#endif772773#ifdef __sun774{ SI_NOINFO, "SI_NOINFO", "No signal information" },775{ SI_RCTL, "SI_RCTL", "kernel generated signal via rctl action" },776{ SI_LWP, "SI_LWP", "Signal sent via lwp_kill" },777#endif778779{ -1, NULL, NULL }780};781782const char* s_code = NULL;783const char* s_desc = NULL;784785for (int i = 0; t1[i].sig != -1; i ++) {786if (t1[i].sig == si->si_signo && t1[i].code == si->si_code) {787s_code = t1[i].s_code;788s_desc = t1[i].s_desc;789break;790}791}792793if (s_code == NULL) {794for (int i = 0; t2[i].s_code != NULL; i ++) {795if (t2[i].code == si->si_code) {796s_code = t2[i].s_code;797s_desc = t2[i].s_desc;798}799}800}801802if (s_code == NULL) {803out->s_name = "unknown";804out->s_desc = "unknown";805return false;806}807808out->s_name = s_code;809out->s_desc = s_desc;810811return true;812}813814// A POSIX conform, platform-independend siginfo print routine.815// Short print out on one line.816void os::Posix::print_siginfo_brief(outputStream* os, const siginfo_t* si) {817char buf[20];818os->print("siginfo: ");819820if (!si) {821os->print("<null>");822return;823}824825// See print_siginfo_full() for details.826const int sig = si->si_signo;827828os->print("si_signo: %d (%s)", sig, os::Posix::get_signal_name(sig, buf, sizeof(buf)));829830enum_sigcode_desc_t ed;831if (get_signal_code_description(si, &ed)) {832os->print(", si_code: %d (%s)", si->si_code, ed.s_name);833} else {834os->print(", si_code: %d (unknown)", si->si_code);835}836837if (si->si_errno) {838os->print(", si_errno: %d", si->si_errno);839}840841const int me = (int) ::getpid();842const int pid = (int) si->si_pid;843844if (si->si_code == SI_USER || si->si_code == SI_QUEUE) {845if (IS_VALID_PID(pid) && pid != me) {846os->print(", sent from pid: %d (uid: %d)", pid, (int) si->si_uid);847}848} else if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||849sig == SIGTRAP || sig == SIGFPE) {850os->print(", si_addr: " PTR_FORMAT, si->si_addr);851#ifdef SIGPOLL852} else if (sig == SIGPOLL) {853os->print(", si_band: " PTR64_FORMAT, (uint64_t)si->si_band);854#endif855} else if (sig == SIGCHLD) {856os->print_cr(", si_pid: %d, si_uid: %d, si_status: %d", (int) si->si_pid, si->si_uid, si->si_status);857}858}859860Thread* os::ThreadCrashProtection::_protected_thread = NULL;861os::ThreadCrashProtection* os::ThreadCrashProtection::_crash_protection = NULL;862volatile intptr_t os::ThreadCrashProtection::_crash_mux = 0;863864os::ThreadCrashProtection::ThreadCrashProtection() {865}866867/*868* See the caveats for this class in os_posix.hpp869* Protects the callback call so that SIGSEGV / SIGBUS jumps back into this870* method and returns false. If none of the signals are raised, returns true.871* The callback is supposed to provide the method that should be protected.872*/873bool os::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) {874sigset_t saved_sig_mask;875876Thread::muxAcquire(&_crash_mux, "CrashProtection");877878_protected_thread = ThreadLocalStorage::thread();879assert(_protected_thread != NULL, "Cannot crash protect a NULL thread");880881// we cannot rely on sigsetjmp/siglongjmp to save/restore the signal mask882// since on at least some systems (OS X) siglongjmp will restore the mask883// for the process, not the thread884pthread_sigmask(0, NULL, &saved_sig_mask);885if (sigsetjmp(_jmpbuf, 0) == 0) {886// make sure we can see in the signal handler that we have crash protection887// installed888_crash_protection = this;889cb.call();890// and clear the crash protection891_crash_protection = NULL;892_protected_thread = NULL;893Thread::muxRelease(&_crash_mux);894return true;895}896// this happens when we siglongjmp() back897pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);898_crash_protection = NULL;899_protected_thread = NULL;900Thread::muxRelease(&_crash_mux);901return false;902}903904void os::ThreadCrashProtection::restore() {905assert(_crash_protection != NULL, "must have crash protection");906siglongjmp(_jmpbuf, 1);907}908909void os::ThreadCrashProtection::check_crash_protection(int sig,910Thread* thread) {911912if (thread != NULL &&913thread == _protected_thread &&914_crash_protection != NULL) {915916if (sig == SIGSEGV || sig == SIGBUS) {917_crash_protection->restore();918}919}920}921922923