src/os/solaris/vm/jsig.c

Wed, 27 Mar 2013 19:21:18 +0100

author
tschatzl
date
Wed, 27 Mar 2013 19:21:18 +0100
changeset 4854
754c24457b20
parent 2314
f95d63e2154a
child 6876
710a3c8b516e
permissions
-rw-r--r--

7112912: Message "Error occurred during initialization of VM" on boxes with lots of RAM
Summary: Ergonomics now also takes available virtual memory into account when deciding for a heap size. The helper method to determine the maximum allocatable memory block now uses the appropriate OS specific calls to retrieve available virtual memory for the java process. In 32 bit environments this method now also searches for the maximum actually reservable amount of memory. Merge previously separate implementations for Linux/BSD/Solaris into a single method.
Reviewed-by: jmasa, tamao

duke@435 1 /*
stefank@2314 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 /* CopyrightVersion 1.2 */
duke@435 26
duke@435 27 /* This is a special library that should be loaded before libc &
duke@435 28 * libthread to interpose the signal handler installation functions:
duke@435 29 * sigaction(), signal(), sigset().
duke@435 30 * Used for signal-chaining. See RFE 4381843.
duke@435 31 */
duke@435 32
duke@435 33 #include <stdlib.h>
duke@435 34 #include <stdio.h>
duke@435 35 #include <string.h>
duke@435 36 #include <signal.h>
duke@435 37 #include <dlfcn.h>
duke@435 38 #include <thread.h>
duke@435 39 #include <synch.h>
duke@435 40 #include "jvm_solaris.h"
duke@435 41
duke@435 42 #define bool int
duke@435 43 #define true 1
duke@435 44 #define false 0
duke@435 45
duke@435 46 static struct sigaction *sact = (struct sigaction *)NULL; /* saved signal handlers */
duke@435 47 static sigset_t jvmsigs;
duke@435 48
duke@435 49 /* used to synchronize the installation of signal handlers */
duke@435 50 static mutex_t mutex = DEFAULTMUTEX;
duke@435 51 static cond_t cond = DEFAULTCV;
duke@435 52 static thread_t tid = 0;
duke@435 53
duke@435 54 typedef void (*sa_handler_t)(int);
duke@435 55 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
duke@435 56 typedef sa_handler_t (*signal_t)(int, sa_handler_t);
duke@435 57 typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *);
duke@435 58
duke@435 59 static signal_t os_signal = 0; /* os's version of signal()/sigset() */
duke@435 60 static sigaction_t os_sigaction = 0; /* os's version of sigaction() */
duke@435 61
duke@435 62 static bool jvm_signal_installing = false;
duke@435 63 static bool jvm_signal_installed = false;
duke@435 64
duke@435 65
duke@435 66 /* assume called within signal_lock */
duke@435 67 static void allocate_sact() {
duke@435 68 size_t maxsignum;
duke@435 69 maxsignum = SIGRTMAX;
duke@435 70 if (sact == NULL) {
duke@435 71 sact = (struct sigaction *)malloc((maxsignum+1) * (size_t)sizeof(struct sigaction));
duke@435 72 memset(sact, 0, (maxsignum+1) * (size_t)sizeof(struct sigaction));
duke@435 73 }
duke@435 74
duke@435 75 if (sact == NULL) {
duke@435 76 printf("%s\n", "libjsig.so unable to allocate memory");
duke@435 77 exit(0);
duke@435 78 }
duke@435 79
duke@435 80 sigemptyset(&jvmsigs);
duke@435 81 }
duke@435 82
duke@435 83 static void signal_lock() {
duke@435 84 mutex_lock(&mutex);
duke@435 85 /* When the jvm is installing its set of signal handlers, threads
duke@435 86 * other than the jvm thread should wait */
duke@435 87 if (jvm_signal_installing) {
duke@435 88 if (tid != thr_self()) {
duke@435 89 cond_wait(&cond, &mutex);
duke@435 90 }
duke@435 91 }
duke@435 92 }
duke@435 93
duke@435 94 static void signal_unlock() {
duke@435 95 mutex_unlock(&mutex);
duke@435 96 }
duke@435 97
duke@435 98 static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
duke@435 99 bool is_sigset) {
duke@435 100 if (os_signal == NULL) {
duke@435 101 if (!is_sigset) {
duke@435 102 os_signal = (signal_t)dlsym(RTLD_NEXT, "signal");
duke@435 103 } else {
duke@435 104 os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset");
duke@435 105 }
duke@435 106 if (os_signal == NULL) {
duke@435 107 printf("%s\n", dlerror());
duke@435 108 exit(0);
duke@435 109 }
duke@435 110 }
duke@435 111 return (*os_signal)(sig, disp);
duke@435 112 }
duke@435 113
duke@435 114 static void save_signal_handler(int sig, sa_handler_t disp, bool is_sigset) {
duke@435 115 sigset_t set;
duke@435 116 if (sact == NULL) {
duke@435 117 allocate_sact();
duke@435 118 }
duke@435 119 sact[sig].sa_handler = disp;
duke@435 120 sigemptyset(&set);
duke@435 121 sact[sig].sa_mask = set;
duke@435 122 if (!is_sigset) {
duke@435 123 sact[sig].sa_flags = SA_NODEFER;
duke@435 124 if (sig != SIGILL && sig != SIGTRAP && sig != SIGPWR) {
duke@435 125 sact[sig].sa_flags |= SA_RESETHAND;
duke@435 126 }
duke@435 127 } else {
duke@435 128 sact[sig].sa_flags = 0;
duke@435 129 }
duke@435 130 }
duke@435 131
duke@435 132 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
duke@435 133 sa_handler_t oldhandler;
duke@435 134 bool sigblocked;
duke@435 135
duke@435 136 signal_lock();
duke@435 137 if (sact == NULL) {
duke@435 138 allocate_sact();
duke@435 139 }
duke@435 140
duke@435 141 if (jvm_signal_installed && sigismember(&jvmsigs, sig)) {
duke@435 142 /* jvm has installed its signal handler for this signal. */
duke@435 143 /* Save the handler. Don't really install it. */
duke@435 144 if (is_sigset) {
duke@435 145 /* We won't honor the SIG_HOLD request to change the signal mask */
duke@435 146 sigblocked = sigismember(&(sact[sig].sa_mask), sig);
duke@435 147 }
duke@435 148 oldhandler = sact[sig].sa_handler;
duke@435 149 save_signal_handler(sig, disp, is_sigset);
duke@435 150
duke@435 151 if (is_sigset && sigblocked) {
duke@435 152 oldhandler = SIG_HOLD;
duke@435 153 }
duke@435 154
duke@435 155 signal_unlock();
duke@435 156 return oldhandler;
duke@435 157 } else if (jvm_signal_installing) {
duke@435 158 /* jvm is installing its signal handlers. Install the new
duke@435 159 * handlers and save the old ones. jvm uses sigaction().
duke@435 160 * Leave the piece here just in case. */
duke@435 161 oldhandler = call_os_signal(sig, disp, is_sigset);
duke@435 162 save_signal_handler(sig, oldhandler, is_sigset);
duke@435 163
duke@435 164 /* Record the signals used by jvm */
duke@435 165 sigaddset(&jvmsigs, sig);
duke@435 166
duke@435 167 signal_unlock();
duke@435 168 return oldhandler;
duke@435 169 } else {
duke@435 170 /* jvm has no relation with this signal (yet). Install the
duke@435 171 * the handler. */
duke@435 172 oldhandler = call_os_signal(sig, disp, is_sigset);
duke@435 173
duke@435 174 signal_unlock();
duke@435 175 return oldhandler;
duke@435 176 }
duke@435 177 }
duke@435 178
duke@435 179 sa_handler_t signal(int sig, sa_handler_t disp) {
duke@435 180 return set_signal(sig, disp, false);
duke@435 181 }
duke@435 182
duke@435 183 sa_handler_t sigset(int sig, sa_handler_t disp) {
duke@435 184 return set_signal(sig, disp, true);
duke@435 185 }
duke@435 186
duke@435 187 static int call_os_sigaction(int sig, const struct sigaction *act,
duke@435 188 struct sigaction *oact) {
duke@435 189 if (os_sigaction == NULL) {
duke@435 190 os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction");
duke@435 191 if (os_sigaction == NULL) {
duke@435 192 printf("%s\n", dlerror());
duke@435 193 exit(0);
duke@435 194 }
duke@435 195 }
duke@435 196 return (*os_sigaction)(sig, act, oact);
duke@435 197 }
duke@435 198
duke@435 199 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
duke@435 200 int res;
duke@435 201 struct sigaction oldAct;
duke@435 202
duke@435 203 signal_lock();
duke@435 204
duke@435 205 if (sact == NULL ) {
duke@435 206 allocate_sact();
duke@435 207 }
duke@435 208 if (jvm_signal_installed && sigismember(&jvmsigs, sig)) {
duke@435 209 /* jvm has installed its signal handler for this signal. */
duke@435 210 /* Save the handler. Don't really install it. */
duke@435 211 if (oact != NULL) {
duke@435 212 *oact = sact[sig];
duke@435 213 }
duke@435 214 if (act != NULL) {
duke@435 215 sact[sig] = *act;
duke@435 216 }
duke@435 217
duke@435 218 signal_unlock();
duke@435 219 return 0;
duke@435 220 } else if (jvm_signal_installing) {
duke@435 221 /* jvm is installing its signal handlers. Install the new
duke@435 222 * handlers and save the old ones. */
duke@435 223 res = call_os_sigaction(sig, act, &oldAct);
duke@435 224 sact[sig] = oldAct;
duke@435 225 if (oact != NULL) {
duke@435 226 *oact = oldAct;
duke@435 227 }
duke@435 228
duke@435 229 /* Record the signals used by jvm */
duke@435 230 sigaddset(&jvmsigs, sig);
duke@435 231
duke@435 232 signal_unlock();
duke@435 233 return res;
duke@435 234 } else {
duke@435 235 /* jvm has no relation with this signal (yet). Install the
duke@435 236 * the handler. */
duke@435 237 res = call_os_sigaction(sig, act, oact);
duke@435 238
duke@435 239 signal_unlock();
duke@435 240 return res;
duke@435 241 }
duke@435 242 }
duke@435 243
duke@435 244 /* The four functions for the jvm to call into */
duke@435 245 void JVM_begin_signal_setting() {
duke@435 246 signal_lock();
duke@435 247 jvm_signal_installing = true;
duke@435 248 tid = thr_self();
duke@435 249 signal_unlock();
duke@435 250 }
duke@435 251
duke@435 252 void JVM_end_signal_setting() {
duke@435 253 signal_lock();
duke@435 254 jvm_signal_installed = true;
duke@435 255 jvm_signal_installing = false;
duke@435 256 cond_broadcast(&cond);
duke@435 257 signal_unlock();
duke@435 258 }
duke@435 259
duke@435 260 struct sigaction *JVM_get_signal_action(int sig) {
duke@435 261 if (sact == NULL) {
duke@435 262 allocate_sact();
duke@435 263 }
duke@435 264 /* Does race condition make sense here? */
duke@435 265 if (sigismember(&jvmsigs, sig)) {
duke@435 266 return &sact[sig];
duke@435 267 }
duke@435 268 return NULL;
duke@435 269 }
duke@435 270
duke@435 271 int JVM_get_libjsig_version() {
duke@435 272 return JSIG_VERSION_1_4_1;
duke@435 273 }

mercurial