Mercurial > hg > truffle
comparison src/os/posix/vm/os_posix.cpp @ 14909:4ca6dc0799b6
Backout jdk9 merge
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Tue, 01 Apr 2014 13:57:07 +0200 |
parents | bb9356ec5967 |
children | 52b4284cb496 |
comparison
equal
deleted
inserted
replaced
14908:8db6e76cb658 | 14909:4ca6dc0799b6 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | 9 * This code is distributed in the hope that it will be useful, but WITHOUT |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 * version 2 for more details (a copy is included in the LICENSE file that | 12 * version 2 for more details (a copy is included in the LICENSE file that |
13 * accompanied this code). | 13 * accompanied this code). |
14 * | 14 * |
15 * You should have received a copy of the GNU General Public License version | 15 * You should have received a copy of the GNU General Public License version |
16 * 2 along with this work; if not, write to the Free Software Foundation, | 16 * 2 along with this work; if not, write to the Free Software Foundation, |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 * | 18 * |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 * or visit www.oracle.com if you need additional information or have any | 20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. | 21 * questions. |
22 * | 22 * |
23 */ | 23 */ |
24 | 24 |
25 #include "utilities/globalDefinitions.hpp" | |
26 #include "prims/jvm.h" | 25 #include "prims/jvm.h" |
27 #include "runtime/frame.inline.hpp" | 26 #include "runtime/frame.inline.hpp" |
28 #include "runtime/interfaceSupport.hpp" | |
29 #include "runtime/os.hpp" | 27 #include "runtime/os.hpp" |
30 #include "utilities/vmError.hpp" | 28 #include "utilities/vmError.hpp" |
31 | 29 |
32 #include <signal.h> | |
33 #include <unistd.h> | 30 #include <unistd.h> |
34 #include <sys/resource.h> | 31 #include <sys/resource.h> |
35 #include <sys/utsname.h> | 32 #include <sys/utsname.h> |
36 #include <pthread.h> | 33 #include <pthread.h> |
37 #include <signal.h> | 34 #include <signal.h> |
38 | 35 |
39 // Todo: provide a os::get_max_process_id() or similar. Number of processes | |
40 // may have been configured, can be read more accurately from proc fs etc. | |
41 #ifndef MAX_PID | |
42 #define MAX_PID INT_MAX | |
43 #endif | |
44 #define IS_VALID_PID(p) (p > 0 && p < MAX_PID) | |
45 | 36 |
46 // Check core dump limit and report possible place where core can be found | 37 // Check core dump limit and report possible place where core can be found |
47 void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) { | 38 void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) { |
48 int n; | 39 int n; |
49 struct rlimit rlim; | 40 struct rlimit rlim; |
165 st->print(", CORE "); | 156 st->print(", CORE "); |
166 getrlimit(RLIMIT_CORE, &rlim); | 157 getrlimit(RLIMIT_CORE, &rlim); |
167 if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); | 158 if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); |
168 else st->print("%uk", rlim.rlim_cur >> 10); | 159 else st->print("%uk", rlim.rlim_cur >> 10); |
169 | 160 |
170 // Isn't there on solaris | 161 //Isn't there on solaris |
171 #if !defined(TARGET_OS_FAMILY_solaris) && !defined(TARGET_OS_FAMILY_aix) | 162 #ifndef TARGET_OS_FAMILY_solaris |
172 st->print(", NPROC "); | 163 st->print(", NPROC "); |
173 getrlimit(RLIMIT_NPROC, &rlim); | 164 getrlimit(RLIMIT_NPROC, &rlim); |
174 if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); | 165 if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); |
175 else st->print("%d", rlim.rlim_cur); | 166 else st->print("%d", rlim.rlim_cur); |
176 #endif | 167 #endif |
267 return getcwd(buf, buflen); | 258 return getcwd(buf, buflen); |
268 } | 259 } |
269 | 260 |
270 FILE* os::open(int fd, const char* mode) { | 261 FILE* os::open(int fd, const char* mode) { |
271 return ::fdopen(fd, mode); | 262 return ::fdopen(fd, mode); |
263 } | |
264 | |
265 void* os::get_default_process_handle() { | |
266 return (void*)::dlopen(NULL, RTLD_LAZY); | |
272 } | 267 } |
273 | 268 |
274 // Builds a platform dependent Agent_OnLoad_<lib_name> function name | 269 // Builds a platform dependent Agent_OnLoad_<lib_name> function name |
275 // which is used to find statically linked in agents. | 270 // which is used to find statically linked in agents. |
276 // Parameters: | 271 // Parameters: |
314 strncat(agent_entry_name, lib_name, name_len); | 309 strncat(agent_entry_name, lib_name, name_len); |
315 } | 310 } |
316 return agent_entry_name; | 311 return agent_entry_name; |
317 } | 312 } |
318 | 313 |
319 int os::sleep(Thread* thread, jlong millis, bool interruptible) { | |
320 assert(thread == Thread::current(), "thread consistency check"); | |
321 | |
322 ParkEvent * const slp = thread->_SleepEvent ; | |
323 slp->reset() ; | |
324 OrderAccess::fence() ; | |
325 | |
326 if (interruptible) { | |
327 jlong prevtime = javaTimeNanos(); | |
328 | |
329 for (;;) { | |
330 if (os::is_interrupted(thread, true)) { | |
331 return OS_INTRPT; | |
332 } | |
333 | |
334 jlong newtime = javaTimeNanos(); | |
335 | |
336 if (newtime - prevtime < 0) { | |
337 // time moving backwards, should only happen if no monotonic clock | |
338 // not a guarantee() because JVM should not abort on kernel/glibc bugs | |
339 assert(!os::supports_monotonic_clock(), "unexpected time moving backwards detected in os::sleep(interruptible)"); | |
340 } else { | |
341 millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; | |
342 } | |
343 | |
344 if (millis <= 0) { | |
345 return OS_OK; | |
346 } | |
347 | |
348 prevtime = newtime; | |
349 | |
350 { | |
351 assert(thread->is_Java_thread(), "sanity check"); | |
352 JavaThread *jt = (JavaThread *) thread; | |
353 ThreadBlockInVM tbivm(jt); | |
354 OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); | |
355 | |
356 jt->set_suspend_equivalent(); | |
357 // cleared by handle_special_suspend_equivalent_condition() or | |
358 // java_suspend_self() via check_and_wait_while_suspended() | |
359 | |
360 slp->park(millis); | |
361 | |
362 // were we externally suspended while we were waiting? | |
363 jt->check_and_wait_while_suspended(); | |
364 } | |
365 } | |
366 } else { | |
367 OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); | |
368 jlong prevtime = javaTimeNanos(); | |
369 | |
370 for (;;) { | |
371 // It'd be nice to avoid the back-to-back javaTimeNanos() calls on | |
372 // the 1st iteration ... | |
373 jlong newtime = javaTimeNanos(); | |
374 | |
375 if (newtime - prevtime < 0) { | |
376 // time moving backwards, should only happen if no monotonic clock | |
377 // not a guarantee() because JVM should not abort on kernel/glibc bugs | |
378 assert(!os::supports_monotonic_clock(), "unexpected time moving backwards detected on os::sleep(!interruptible)"); | |
379 } else { | |
380 millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; | |
381 } | |
382 | |
383 if (millis <= 0) break ; | |
384 | |
385 prevtime = newtime; | |
386 slp->park(millis); | |
387 } | |
388 return OS_OK ; | |
389 } | |
390 } | |
391 | |
392 //////////////////////////////////////////////////////////////////////////////// | |
393 // interrupt support | |
394 | |
395 void os::interrupt(Thread* thread) { | |
396 assert(Thread::current() == thread || Threads_lock->owned_by_self(), | |
397 "possibility of dangling Thread pointer"); | |
398 | |
399 OSThread* osthread = thread->osthread(); | |
400 | |
401 if (!osthread->interrupted()) { | |
402 osthread->set_interrupted(true); | |
403 // More than one thread can get here with the same value of osthread, | |
404 // resulting in multiple notifications. We do, however, want the store | |
405 // to interrupted() to be visible to other threads before we execute unpark(). | |
406 OrderAccess::fence(); | |
407 ParkEvent * const slp = thread->_SleepEvent ; | |
408 if (slp != NULL) slp->unpark() ; | |
409 } | |
410 | |
411 // For JSR166. Unpark even if interrupt status already was set | |
412 if (thread->is_Java_thread()) | |
413 ((JavaThread*)thread)->parker()->unpark(); | |
414 | |
415 ParkEvent * ev = thread->_ParkEvent ; | |
416 if (ev != NULL) ev->unpark() ; | |
417 | |
418 } | |
419 | |
420 bool os::is_interrupted(Thread* thread, bool clear_interrupted) { | |
421 assert(Thread::current() == thread || Threads_lock->owned_by_self(), | |
422 "possibility of dangling Thread pointer"); | |
423 | |
424 OSThread* osthread = thread->osthread(); | |
425 | |
426 bool interrupted = osthread->interrupted(); | |
427 | |
428 // NOTE that since there is no "lock" around the interrupt and | |
429 // is_interrupted operations, there is the possibility that the | |
430 // interrupted flag (in osThread) will be "false" but that the | |
431 // low-level events will be in the signaled state. This is | |
432 // intentional. The effect of this is that Object.wait() and | |
433 // LockSupport.park() will appear to have a spurious wakeup, which | |
434 // is allowed and not harmful, and the possibility is so rare that | |
435 // it is not worth the added complexity to add yet another lock. | |
436 // For the sleep event an explicit reset is performed on entry | |
437 // to os::sleep, so there is no early return. It has also been | |
438 // recommended not to put the interrupted flag into the "event" | |
439 // structure because it hides the issue. | |
440 if (interrupted && clear_interrupted) { | |
441 osthread->set_interrupted(false); | |
442 // consider thread->_SleepEvent->reset() ... optional optimization | |
443 } | |
444 | |
445 return interrupted; | |
446 } | |
447 | |
448 // Returned string is a constant. For unknown signals "UNKNOWN" is returned. | |
449 const char* os::Posix::get_signal_name(int sig, char* out, size_t outlen) { | |
450 | |
451 static const struct { | |
452 int sig; const char* name; | |
453 } | |
454 info[] = | |
455 { | |
456 { SIGABRT, "SIGABRT" }, | |
457 #ifdef SIGAIO | |
458 { SIGAIO, "SIGAIO" }, | |
459 #endif | |
460 { SIGALRM, "SIGALRM" }, | |
461 #ifdef SIGALRM1 | |
462 { SIGALRM1, "SIGALRM1" }, | |
463 #endif | |
464 { SIGBUS, "SIGBUS" }, | |
465 #ifdef SIGCANCEL | |
466 { SIGCANCEL, "SIGCANCEL" }, | |
467 #endif | |
468 { SIGCHLD, "SIGCHLD" }, | |
469 #ifdef SIGCLD | |
470 { SIGCLD, "SIGCLD" }, | |
471 #endif | |
472 { SIGCONT, "SIGCONT" }, | |
473 #ifdef SIGCPUFAIL | |
474 { SIGCPUFAIL, "SIGCPUFAIL" }, | |
475 #endif | |
476 #ifdef SIGDANGER | |
477 { SIGDANGER, "SIGDANGER" }, | |
478 #endif | |
479 #ifdef SIGDIL | |
480 { SIGDIL, "SIGDIL" }, | |
481 #endif | |
482 #ifdef SIGEMT | |
483 { SIGEMT, "SIGEMT" }, | |
484 #endif | |
485 { SIGFPE, "SIGFPE" }, | |
486 #ifdef SIGFREEZE | |
487 { SIGFREEZE, "SIGFREEZE" }, | |
488 #endif | |
489 #ifdef SIGGFAULT | |
490 { SIGGFAULT, "SIGGFAULT" }, | |
491 #endif | |
492 #ifdef SIGGRANT | |
493 { SIGGRANT, "SIGGRANT" }, | |
494 #endif | |
495 { SIGHUP, "SIGHUP" }, | |
496 { SIGILL, "SIGILL" }, | |
497 { SIGINT, "SIGINT" }, | |
498 #ifdef SIGIO | |
499 { SIGIO, "SIGIO" }, | |
500 #endif | |
501 #ifdef SIGIOINT | |
502 { SIGIOINT, "SIGIOINT" }, | |
503 #endif | |
504 #ifdef SIGIOT | |
505 // SIGIOT is there for BSD compatibility, but on most Unices just a | |
506 // synonym for SIGABRT. The result should be "SIGABRT", not | |
507 // "SIGIOT". | |
508 #if (SIGIOT != SIGABRT ) | |
509 { SIGIOT, "SIGIOT" }, | |
510 #endif | |
511 #endif | |
512 #ifdef SIGKAP | |
513 { SIGKAP, "SIGKAP" }, | |
514 #endif | |
515 { SIGKILL, "SIGKILL" }, | |
516 #ifdef SIGLOST | |
517 { SIGLOST, "SIGLOST" }, | |
518 #endif | |
519 #ifdef SIGLWP | |
520 { SIGLWP, "SIGLWP" }, | |
521 #endif | |
522 #ifdef SIGLWPTIMER | |
523 { SIGLWPTIMER, "SIGLWPTIMER" }, | |
524 #endif | |
525 #ifdef SIGMIGRATE | |
526 { SIGMIGRATE, "SIGMIGRATE" }, | |
527 #endif | |
528 #ifdef SIGMSG | |
529 { SIGMSG, "SIGMSG" }, | |
530 #endif | |
531 { SIGPIPE, "SIGPIPE" }, | |
532 #ifdef SIGPOLL | |
533 { SIGPOLL, "SIGPOLL" }, | |
534 #endif | |
535 #ifdef SIGPRE | |
536 { SIGPRE, "SIGPRE" }, | |
537 #endif | |
538 { SIGPROF, "SIGPROF" }, | |
539 #ifdef SIGPTY | |
540 { SIGPTY, "SIGPTY" }, | |
541 #endif | |
542 #ifdef SIGPWR | |
543 { SIGPWR, "SIGPWR" }, | |
544 #endif | |
545 { SIGQUIT, "SIGQUIT" }, | |
546 #ifdef SIGRECONFIG | |
547 { SIGRECONFIG, "SIGRECONFIG" }, | |
548 #endif | |
549 #ifdef SIGRECOVERY | |
550 { SIGRECOVERY, "SIGRECOVERY" }, | |
551 #endif | |
552 #ifdef SIGRESERVE | |
553 { SIGRESERVE, "SIGRESERVE" }, | |
554 #endif | |
555 #ifdef SIGRETRACT | |
556 { SIGRETRACT, "SIGRETRACT" }, | |
557 #endif | |
558 #ifdef SIGSAK | |
559 { SIGSAK, "SIGSAK" }, | |
560 #endif | |
561 { SIGSEGV, "SIGSEGV" }, | |
562 #ifdef SIGSOUND | |
563 { SIGSOUND, "SIGSOUND" }, | |
564 #endif | |
565 { SIGSTOP, "SIGSTOP" }, | |
566 { SIGSYS, "SIGSYS" }, | |
567 #ifdef SIGSYSERROR | |
568 { SIGSYSERROR, "SIGSYSERROR" }, | |
569 #endif | |
570 #ifdef SIGTALRM | |
571 { SIGTALRM, "SIGTALRM" }, | |
572 #endif | |
573 { SIGTERM, "SIGTERM" }, | |
574 #ifdef SIGTHAW | |
575 { SIGTHAW, "SIGTHAW" }, | |
576 #endif | |
577 { SIGTRAP, "SIGTRAP" }, | |
578 #ifdef SIGTSTP | |
579 { SIGTSTP, "SIGTSTP" }, | |
580 #endif | |
581 { SIGTTIN, "SIGTTIN" }, | |
582 { SIGTTOU, "SIGTTOU" }, | |
583 #ifdef SIGURG | |
584 { SIGURG, "SIGURG" }, | |
585 #endif | |
586 { SIGUSR1, "SIGUSR1" }, | |
587 { SIGUSR2, "SIGUSR2" }, | |
588 #ifdef SIGVIRT | |
589 { SIGVIRT, "SIGVIRT" }, | |
590 #endif | |
591 { SIGVTALRM, "SIGVTALRM" }, | |
592 #ifdef SIGWAITING | |
593 { SIGWAITING, "SIGWAITING" }, | |
594 #endif | |
595 #ifdef SIGWINCH | |
596 { SIGWINCH, "SIGWINCH" }, | |
597 #endif | |
598 #ifdef SIGWINDOW | |
599 { SIGWINDOW, "SIGWINDOW" }, | |
600 #endif | |
601 { SIGXCPU, "SIGXCPU" }, | |
602 { SIGXFSZ, "SIGXFSZ" }, | |
603 #ifdef SIGXRES | |
604 { SIGXRES, "SIGXRES" }, | |
605 #endif | |
606 { -1, NULL } | |
607 }; | |
608 | |
609 const char* ret = NULL; | |
610 | |
611 #ifdef SIGRTMIN | |
612 if (sig >= SIGRTMIN && sig <= SIGRTMAX) { | |
613 if (sig == SIGRTMIN) { | |
614 ret = "SIGRTMIN"; | |
615 } else if (sig == SIGRTMAX) { | |
616 ret = "SIGRTMAX"; | |
617 } else { | |
618 jio_snprintf(out, outlen, "SIGRTMIN+%d", sig - SIGRTMIN); | |
619 return out; | |
620 } | |
621 } | |
622 #endif | |
623 | |
624 if (sig > 0) { | |
625 for (int idx = 0; info[idx].sig != -1; idx ++) { | |
626 if (info[idx].sig == sig) { | |
627 ret = info[idx].name; | |
628 break; | |
629 } | |
630 } | |
631 } | |
632 | |
633 if (!ret) { | |
634 if (!is_valid_signal(sig)) { | |
635 ret = "INVALID"; | |
636 } else { | |
637 ret = "UNKNOWN"; | |
638 } | |
639 } | |
640 | |
641 jio_snprintf(out, outlen, ret); | |
642 return out; | |
643 } | |
644 | |
645 // Returns true if signal number is valid. | |
646 bool os::Posix::is_valid_signal(int sig) { | |
647 // MacOS not really POSIX compliant: sigaddset does not return | |
648 // an error for invalid signal numbers. However, MacOS does not | |
649 // support real time signals and simply seems to have just 33 | |
650 // signals with no holes in the signal range. | |
651 #ifdef __APPLE__ | |
652 return sig >= 1 && sig < NSIG; | |
653 #else | |
654 // Use sigaddset to check for signal validity. | |
655 sigset_t set; | |
656 if (sigaddset(&set, sig) == -1 && errno == EINVAL) { | |
657 return false; | |
658 } | |
659 return true; | |
660 #endif | |
661 } | |
662 | |
663 #define NUM_IMPORTANT_SIGS 32 | |
664 // Returns one-line short description of a signal set in a user provided buffer. | |
665 const char* os::Posix::describe_signal_set_short(const sigset_t* set, char* buffer, size_t buf_size) { | |
666 assert(buf_size == (NUM_IMPORTANT_SIGS + 1), "wrong buffer size"); | |
667 // Note: for shortness, just print out the first 32. That should | |
668 // cover most of the useful ones, apart from realtime signals. | |
669 for (int sig = 1; sig <= NUM_IMPORTANT_SIGS; sig++) { | |
670 const int rc = sigismember(set, sig); | |
671 if (rc == -1 && errno == EINVAL) { | |
672 buffer[sig-1] = '?'; | |
673 } else { | |
674 buffer[sig-1] = rc == 0 ? '0' : '1'; | |
675 } | |
676 } | |
677 buffer[NUM_IMPORTANT_SIGS] = 0; | |
678 return buffer; | |
679 } | |
680 | |
681 // Prints one-line description of a signal set. | |
682 void os::Posix::print_signal_set_short(outputStream* st, const sigset_t* set) { | |
683 char buf[NUM_IMPORTANT_SIGS + 1]; | |
684 os::Posix::describe_signal_set_short(set, buf, sizeof(buf)); | |
685 st->print(buf); | |
686 } | |
687 | |
688 // Writes one-line description of a combination of sigaction.sa_flags into a user | |
689 // provided buffer. Returns that buffer. | |
690 const char* os::Posix::describe_sa_flags(int flags, char* buffer, size_t size) { | |
691 char* p = buffer; | |
692 size_t remaining = size; | |
693 bool first = true; | |
694 int idx = 0; | |
695 | |
696 assert(buffer, "invalid argument"); | |
697 | |
698 if (size == 0) { | |
699 return buffer; | |
700 } | |
701 | |
702 strncpy(buffer, "none", size); | |
703 | |
704 const struct { | |
705 int i; | |
706 const char* s; | |
707 } flaginfo [] = { | |
708 { SA_NOCLDSTOP, "SA_NOCLDSTOP" }, | |
709 { SA_ONSTACK, "SA_ONSTACK" }, | |
710 { SA_RESETHAND, "SA_RESETHAND" }, | |
711 { SA_RESTART, "SA_RESTART" }, | |
712 { SA_SIGINFO, "SA_SIGINFO" }, | |
713 { SA_NOCLDWAIT, "SA_NOCLDWAIT" }, | |
714 { SA_NODEFER, "SA_NODEFER" }, | |
715 #ifdef AIX | |
716 { SA_ONSTACK, "SA_ONSTACK" }, | |
717 { SA_OLDSTYLE, "SA_OLDSTYLE" }, | |
718 #endif | |
719 { 0, NULL } | |
720 }; | |
721 | |
722 for (idx = 0; flaginfo[idx].s && remaining > 1; idx++) { | |
723 if (flags & flaginfo[idx].i) { | |
724 if (first) { | |
725 jio_snprintf(p, remaining, "%s", flaginfo[idx].s); | |
726 first = false; | |
727 } else { | |
728 jio_snprintf(p, remaining, "|%s", flaginfo[idx].s); | |
729 } | |
730 const size_t len = strlen(p); | |
731 p += len; | |
732 remaining -= len; | |
733 } | |
734 } | |
735 | |
736 buffer[size - 1] = '\0'; | |
737 | |
738 return buffer; | |
739 } | |
740 | |
741 // Prints one-line description of a combination of sigaction.sa_flags. | |
742 void os::Posix::print_sa_flags(outputStream* st, int flags) { | |
743 char buffer[0x100]; | |
744 os::Posix::describe_sa_flags(flags, buffer, sizeof(buffer)); | |
745 st->print(buffer); | |
746 } | |
747 | |
748 // Helper function for os::Posix::print_siginfo_...(): | |
749 // return a textual description for signal code. | |
750 struct enum_sigcode_desc_t { | |
751 const char* s_name; | |
752 const char* s_desc; | |
753 }; | |
754 | |
755 static bool get_signal_code_description(const siginfo_t* si, enum_sigcode_desc_t* out) { | |
756 | |
757 const struct { | |
758 int sig; int code; const char* s_code; const char* s_desc; | |
759 } t1 [] = { | |
760 { SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode." }, | |
761 { SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand." }, | |
762 { SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode." }, | |
763 { SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap." }, | |
764 { SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode." }, | |
765 { SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register." }, | |
766 { SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error." }, | |
767 { SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error." }, | |
768 #if defined(IA64) && defined(LINUX) | |
769 { SIGILL, ILL_BADIADDR, "ILL_BADIADDR", "Unimplemented instruction address" }, | |
770 { SIGILL, ILL_BREAK, "ILL_BREAK", "Application Break instruction" }, | |
771 #endif | |
772 { SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero." }, | |
773 { SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow." }, | |
774 { SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating-point divide by zero." }, | |
775 { SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating-point overflow." }, | |
776 { SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating-point underflow." }, | |
777 { SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating-point inexact result." }, | |
778 { SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating-point operation." }, | |
779 { SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range." }, | |
780 { SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object." }, | |
781 { SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for mapped object." }, | |
782 #ifdef AIX | |
783 // no explanation found what keyerr would be | |
784 { SIGSEGV, SEGV_KEYERR, "SEGV_KEYERR", "key error" }, | |
785 #endif | |
786 #if defined(IA64) && !defined(AIX) | |
787 { SIGSEGV, SEGV_PSTKOVF, "SEGV_PSTKOVF", "Paragraph stack overflow" }, | |
788 #endif | |
789 { SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment." }, | |
790 { SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Nonexistent physical address." }, | |
791 { SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object-specific hardware error." }, | |
792 { SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint." }, | |
793 { SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap." }, | |
794 { SIGCHLD, CLD_EXITED, "CLD_EXITED", "Child has exited." }, | |
795 { SIGCHLD, CLD_KILLED, "CLD_KILLED", "Child has terminated abnormally and did not create a core file." }, | |
796 { SIGCHLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally and created a core file." }, | |
797 { SIGCHLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped." }, | |
798 { SIGCHLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped." }, | |
799 { SIGCHLD, CLD_CONTINUED,"CLD_CONTINUED","Stopped child has continued." }, | |
800 #ifdef SIGPOLL | |
801 { SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available." }, | |
802 { SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available." }, | |
803 { SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error." }, | |
804 { SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available." }, | |
805 { SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected. [Option End]" }, | |
806 #endif | |
807 { -1, -1, NULL, NULL } | |
808 }; | |
809 | |
810 // Codes valid in any signal context. | |
811 const struct { | |
812 int code; const char* s_code; const char* s_desc; | |
813 } t2 [] = { | |
814 { SI_USER, "SI_USER", "Signal sent by kill()." }, | |
815 { SI_QUEUE, "SI_QUEUE", "Signal sent by the sigqueue()." }, | |
816 { SI_TIMER, "SI_TIMER", "Signal generated by expiration of a timer set by timer_settime()." }, | |
817 { SI_ASYNCIO, "SI_ASYNCIO", "Signal generated by completion of an asynchronous I/O request." }, | |
818 { SI_MESGQ, "SI_MESGQ", "Signal generated by arrival of a message on an empty message queue." }, | |
819 // Linux specific | |
820 #ifdef SI_TKILL | |
821 { SI_TKILL, "SI_TKILL", "Signal sent by tkill (pthread_kill)" }, | |
822 #endif | |
823 #ifdef SI_DETHREAD | |
824 { SI_DETHREAD, "SI_DETHREAD", "Signal sent by execve() killing subsidiary threads" }, | |
825 #endif | |
826 #ifdef SI_KERNEL | |
827 { SI_KERNEL, "SI_KERNEL", "Signal sent by kernel." }, | |
828 #endif | |
829 #ifdef SI_SIGIO | |
830 { SI_SIGIO, "SI_SIGIO", "Signal sent by queued SIGIO" }, | |
831 #endif | |
832 | |
833 #ifdef AIX | |
834 { SI_UNDEFINED, "SI_UNDEFINED","siginfo contains partial information" }, | |
835 { SI_EMPTY, "SI_EMPTY", "siginfo contains no useful information" }, | |
836 #endif | |
837 | |
838 #ifdef __sun | |
839 { SI_NOINFO, "SI_NOINFO", "No signal information" }, | |
840 { SI_RCTL, "SI_RCTL", "kernel generated signal via rctl action" }, | |
841 { SI_LWP, "SI_LWP", "Signal sent via lwp_kill" }, | |
842 #endif | |
843 | |
844 { -1, NULL, NULL } | |
845 }; | |
846 | |
847 const char* s_code = NULL; | |
848 const char* s_desc = NULL; | |
849 | |
850 for (int i = 0; t1[i].sig != -1; i ++) { | |
851 if (t1[i].sig == si->si_signo && t1[i].code == si->si_code) { | |
852 s_code = t1[i].s_code; | |
853 s_desc = t1[i].s_desc; | |
854 break; | |
855 } | |
856 } | |
857 | |
858 if (s_code == NULL) { | |
859 for (int i = 0; t2[i].s_code != NULL; i ++) { | |
860 if (t2[i].code == si->si_code) { | |
861 s_code = t2[i].s_code; | |
862 s_desc = t2[i].s_desc; | |
863 } | |
864 } | |
865 } | |
866 | |
867 if (s_code == NULL) { | |
868 out->s_name = "unknown"; | |
869 out->s_desc = "unknown"; | |
870 return false; | |
871 } | |
872 | |
873 out->s_name = s_code; | |
874 out->s_desc = s_desc; | |
875 | |
876 return true; | |
877 } | |
878 | |
879 // A POSIX conform, platform-independend siginfo print routine. | |
880 // Short print out on one line. | |
881 void os::Posix::print_siginfo_brief(outputStream* os, const siginfo_t* si) { | |
882 char buf[20]; | |
883 os->print("siginfo: "); | |
884 | |
885 if (!si) { | |
886 os->print("<null>"); | |
887 return; | |
888 } | |
889 | |
890 // See print_siginfo_full() for details. | |
891 const int sig = si->si_signo; | |
892 | |
893 os->print("si_signo: %d (%s)", sig, os::Posix::get_signal_name(sig, buf, sizeof(buf))); | |
894 | |
895 enum_sigcode_desc_t ed; | |
896 if (get_signal_code_description(si, &ed)) { | |
897 os->print(", si_code: %d (%s)", si->si_code, ed.s_name); | |
898 } else { | |
899 os->print(", si_code: %d (unknown)", si->si_code); | |
900 } | |
901 | |
902 if (si->si_errno) { | |
903 os->print(", si_errno: %d", si->si_errno); | |
904 } | |
905 | |
906 const int me = (int) ::getpid(); | |
907 const int pid = (int) si->si_pid; | |
908 | |
909 if (si->si_code == SI_USER || si->si_code == SI_QUEUE) { | |
910 if (IS_VALID_PID(pid) && pid != me) { | |
911 os->print(", sent from pid: %d (uid: %d)", pid, (int) si->si_uid); | |
912 } | |
913 } else if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || | |
914 sig == SIGTRAP || sig == SIGFPE) { | |
915 os->print(", si_addr: " PTR_FORMAT, si->si_addr); | |
916 #ifdef SIGPOLL | |
917 } else if (sig == SIGPOLL) { | |
918 os->print(", si_band: " PTR64_FORMAT, (uint64_t)si->si_band); | |
919 #endif | |
920 } else if (sig == SIGCHLD) { | |
921 os->print_cr(", si_pid: %d, si_uid: %d, si_status: %d", (int) si->si_pid, si->si_uid, si->si_status); | |
922 } | |
923 } | |
924 | |
925 os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { | 314 os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { |
926 assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); | 315 assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); |
927 } | 316 } |
928 | 317 |
929 /* | 318 /* |