78 # include <sys/types.h>
79 # include <sys/mman.h>
80 # include <sys/stat.h>
81 # include <sys/select.h>
82 # include <pthread.h>
83 # include <signal.h>
84 # include <errno.h>
85 # include <dlfcn.h>
86 # include <stdio.h>
87 # include <unistd.h>
88 # include <sys/resource.h>
89 # include <pthread.h>
90 # include <sys/stat.h>
91 # include <sys/time.h>
92 # include <sys/times.h>
93 # include <sys/utsname.h>
94 # include <sys/socket.h>
95 # include <sys/wait.h>
96 # include <pwd.h>
97 # include <poll.h>
98 # include <semaphore.h>
99 # include <fcntl.h>
100 # include <string.h>
101 # include <syscall.h>
102 # include <sys/sysinfo.h>
103 # include <gnu/libc-version.h>
104 # include <sys/ipc.h>
105 # include <sys/shm.h>
106 # include <link.h>
107 # include <stdint.h>
108 # include <inttypes.h>
109 # include <sys/ioctl.h>
110
111 #ifndef _GNU_SOURCE
112 #define _GNU_SOURCE
113 #include <sched.h>
114 #undef _GNU_SOURCE
115 #else
116 #include <sched.h>
117 #endif
118
2462 // 4511530 - sem_post is serialized and handled by the manager thread. When
2463 // the program is interrupted by Ctrl-C, SIGINT is sent to every thread. We
2464 // don't want to flood the manager thread with sem_post requests.
2465 if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1) {
2466 return;
2467 }
2468
2469 // Ctrl-C is pressed during error reporting, likely because the error
2470 // handler fails to abort. Let VM die immediately.
2471 if (sig == SIGINT && VMError::is_error_reported()) {
2472 os::die();
2473 }
2474
2475 os::signal_notify(sig);
2476 }
2477
2478 void* os::user_handler() {
2479 return CAST_FROM_FN_PTR(void*, UserHandler);
2480 }
2481
2482 struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
2483 struct timespec ts;
2484 // Semaphore's are always associated with CLOCK_REALTIME
2485 os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
2486 // see unpackTime for discussion on overflow checking
2487 if (sec >= MAX_SECS) {
2488 ts.tv_sec += MAX_SECS;
2489 ts.tv_nsec = 0;
2490 } else {
2491 ts.tv_sec += sec;
2492 ts.tv_nsec += nsec;
2493 if (ts.tv_nsec >= NANOSECS_PER_SEC) {
2494 ts.tv_nsec -= NANOSECS_PER_SEC;
2495 ++ts.tv_sec; // note: this must be <= max_secs
2496 }
2497 }
2498
2499 return ts;
2500 }
2501
2502 extern "C" {
2518
2519 return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler);
2520 }
2521
2522 void os::signal_raise(int signal_number) {
2523 ::raise(signal_number);
2524 }
2525
2526 // The following code is moved from os.cpp for making this
2527 // code platform specific, which it is by its very nature.
2528
2529 // Will be modified when max signal is changed to be dynamic
2530 int os::sigexitnum_pd() {
2531 return NSIG;
2532 }
2533
2534 // a counter for each possible signal value
2535 static volatile jint pending_signals[NSIG+1] = { 0 };
2536
2537 // Linux(POSIX) specific hand shaking semaphore.
2538 static sem_t sig_sem;
2539 static PosixSemaphore sr_semaphore;
2540
2541 void os::signal_init_pd() {
2542 // Initialize signal structures
2543 ::memset((void*)pending_signals, 0, sizeof(pending_signals));
2544
2545 // Initialize signal semaphore
2546 ::sem_init(&sig_sem, 0, 0);
2547 }
2548
2549 void os::signal_notify(int sig) {
2550 Atomic::inc(&pending_signals[sig]);
2551 ::sem_post(&sig_sem);
2552 }
2553
2554 static int check_pending_signals(bool wait) {
2555 Atomic::store(0, &sigint_count);
2556 for (;;) {
2557 for (int i = 0; i < NSIG + 1; i++) {
2558 jint n = pending_signals[i];
2559 if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) {
2560 return i;
2561 }
2562 }
2563 if (!wait) {
2564 return -1;
2565 }
2566 JavaThread *thread = JavaThread::current();
2567 ThreadBlockInVM tbivm(thread);
2568
2569 bool threadIsSuspended;
2570 do {
2571 thread->set_suspend_equivalent();
2572 // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
2573 ::sem_wait(&sig_sem);
2574
2575 // were we externally suspended while we were waiting?
2576 threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
2577 if (threadIsSuspended) {
2578 // The semaphore has been incremented, but while we were waiting
2579 // another thread suspended us. We don't want to continue running
2580 // while suspended because that would surprise the thread that
2581 // suspended us.
2582 ::sem_post(&sig_sem);
2583
2584 thread->java_suspend_self();
2585 }
2586 } while (threadIsSuspended);
2587 }
2588 }
2589
2590 int os::signal_lookup() {
2591 return check_pending_signals(false);
2592 }
2593
2594 int os::signal_wait() {
2595 return check_pending_signals(true);
2596 }
2597
2598 ////////////////////////////////////////////////////////////////////////////////
2599 // Virtual Memory
2600
2601 int os::vm_page_size() {
2602 // Seems redundant as all get out
2603 assert(os::Linux::page_size() != -1, "must call os::init");
2604 return os::Linux::page_size();
2605 }
2606
2607 // Solaris allocates memory by pages.
2608 int os::vm_allocation_granularity() {
2609 assert(os::Linux::page_size() != -1, "must call os::init");
2610 return os::Linux::page_size();
2611 }
2612
2613 // Rationale behind this function:
4300
4301 // returns true on success and false on error - really an error is fatal
4302 // but this seems the normal response to library errors
4303 static bool do_suspend(OSThread* osthread) {
4304 assert(osthread->sr.is_running(), "thread should be running");
4305 assert(!sr_semaphore.trywait(), "semaphore has invalid state");
4306
4307 // mark as suspended and send signal
4308 if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) {
4309 // failed to switch, state wasn't running?
4310 ShouldNotReachHere();
4311 return false;
4312 }
4313
4314 if (sr_notify(osthread) != 0) {
4315 ShouldNotReachHere();
4316 }
4317
4318 // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
4319 while (true) {
4320 if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) {
4321 break;
4322 } else {
4323 // timeout
4324 os::SuspendResume::State cancelled = osthread->sr.cancel_suspend();
4325 if (cancelled == os::SuspendResume::SR_RUNNING) {
4326 return false;
4327 } else if (cancelled == os::SuspendResume::SR_SUSPENDED) {
4328 // make sure that we consume the signal on the semaphore as well
4329 sr_semaphore.wait();
4330 break;
4331 } else {
4332 ShouldNotReachHere();
4333 return false;
4334 }
4335 }
4336 }
4337
4338 guarantee(osthread->sr.is_suspended(), "Must be suspended");
4339 return true;
4340 }
4341
4342 static void do_resume(OSThread* osthread) {
4343 assert(osthread->sr.is_suspended(), "thread should be suspended");
4344 assert(!sr_semaphore.trywait(), "invalid semaphore state");
4345
4346 if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) {
4347 // failed to switch to WAKEUP_REQUEST
4348 ShouldNotReachHere();
4349 return;
4350 }
4351
4352 while (true) {
4353 if (sr_notify(osthread) == 0) {
4354 if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) {
4355 if (osthread->sr.is_running()) {
4356 return;
4357 }
4358 }
4359 } else {
4360 ShouldNotReachHere();
4361 }
4362 }
4363
4364 guarantee(osthread->sr.is_running(), "Must be running!");
4365 }
4366
4367 ///////////////////////////////////////////////////////////////////////////////////
4368 // signal handling (except suspend/resume)
4369
4370 // This routine may be used by user applications as a "hook" to catch signals.
4371 // The user-defined signal handler must pass unrecognized signals to this
4372 // routine, and if it returns true (non-zero), then the signal handler must
4373 // return immediately. If the flag "abort_if_unrecognized" is true, then this
4374 // routine will never retun false (zero), but instead will execute a VM panic
|
78 # include <sys/types.h>
79 # include <sys/mman.h>
80 # include <sys/stat.h>
81 # include <sys/select.h>
82 # include <pthread.h>
83 # include <signal.h>
84 # include <errno.h>
85 # include <dlfcn.h>
86 # include <stdio.h>
87 # include <unistd.h>
88 # include <sys/resource.h>
89 # include <pthread.h>
90 # include <sys/stat.h>
91 # include <sys/time.h>
92 # include <sys/times.h>
93 # include <sys/utsname.h>
94 # include <sys/socket.h>
95 # include <sys/wait.h>
96 # include <pwd.h>
97 # include <poll.h>
98 # include <fcntl.h>
99 # include <string.h>
100 # include <syscall.h>
101 # include <sys/sysinfo.h>
102 # include <gnu/libc-version.h>
103 # include <sys/ipc.h>
104 # include <sys/shm.h>
105 # include <link.h>
106 # include <stdint.h>
107 # include <inttypes.h>
108 # include <sys/ioctl.h>
109
110 #ifndef _GNU_SOURCE
111 #define _GNU_SOURCE
112 #include <sched.h>
113 #undef _GNU_SOURCE
114 #else
115 #include <sched.h>
116 #endif
117
2461 // 4511530 - sem_post is serialized and handled by the manager thread. When
2462 // the program is interrupted by Ctrl-C, SIGINT is sent to every thread. We
2463 // don't want to flood the manager thread with sem_post requests.
2464 if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1) {
2465 return;
2466 }
2467
2468 // Ctrl-C is pressed during error reporting, likely because the error
2469 // handler fails to abort. Let VM die immediately.
2470 if (sig == SIGINT && VMError::is_error_reported()) {
2471 os::die();
2472 }
2473
2474 os::signal_notify(sig);
2475 }
2476
2477 void* os::user_handler() {
2478 return CAST_FROM_FN_PTR(void*, UserHandler);
2479 }
2480
2481 static struct timespec create_timespec(unsigned int sec, int nsec) {
2482 struct timespec ts;
2483 // Semaphore's are always associated with CLOCK_REALTIME
2484 os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
2485 // see unpackTime for discussion on overflow checking
2486 if (sec >= MAX_SECS) {
2487 ts.tv_sec += MAX_SECS;
2488 ts.tv_nsec = 0;
2489 } else {
2490 ts.tv_sec += sec;
2491 ts.tv_nsec += nsec;
2492 if (ts.tv_nsec >= NANOSECS_PER_SEC) {
2493 ts.tv_nsec -= NANOSECS_PER_SEC;
2494 ++ts.tv_sec; // note: this must be <= max_secs
2495 }
2496 }
2497
2498 return ts;
2499 }
2500
2501 extern "C" {
2517
2518 return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler);
2519 }
2520
2521 void os::signal_raise(int signal_number) {
2522 ::raise(signal_number);
2523 }
2524
2525 // The following code is moved from os.cpp for making this
2526 // code platform specific, which it is by its very nature.
2527
2528 // Will be modified when max signal is changed to be dynamic
2529 int os::sigexitnum_pd() {
2530 return NSIG;
2531 }
2532
2533 // a counter for each possible signal value
2534 static volatile jint pending_signals[NSIG+1] = { 0 };
2535
2536 // Linux(POSIX) specific hand shaking semaphore.
2537 static Semaphore* sig_sem = NULL;
2538 static PosixSemaphore sr_semaphore;
2539
2540 void os::signal_init_pd() {
2541 // Initialize signal structures
2542 ::memset((void*)pending_signals, 0, sizeof(pending_signals));
2543
2544 // Initialize signal semaphore
2545 sig_sem = new Semaphore();
2546 }
2547
2548 void os::signal_notify(int sig) {
2549 if (sig_sem != NULL) {
2550 Atomic::inc(&pending_signals[sig]);
2551 sig_sem->signal();
2552 } else {
2553 // Signal thread is not created with ReduceSignalUsage and signal_init_pd
2554 // initialization isn't called.
2555 assert(ReduceSignalUsage, "signal semaphore should be created");
2556 }
2557 }
2558
2559 static int check_pending_signals(bool wait) {
2560 Atomic::store(0, &sigint_count);
2561 for (;;) {
2562 for (int i = 0; i < NSIG + 1; i++) {
2563 jint n = pending_signals[i];
2564 if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) {
2565 return i;
2566 }
2567 }
2568 if (!wait) {
2569 return -1;
2570 }
2571 JavaThread *thread = JavaThread::current();
2572 ThreadBlockInVM tbivm(thread);
2573
2574 bool threadIsSuspended;
2575 do {
2576 thread->set_suspend_equivalent();
2577 // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
2578 sig_sem->wait();
2579
2580 // were we externally suspended while we were waiting?
2581 threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
2582 if (threadIsSuspended) {
2583 // The semaphore has been incremented, but while we were waiting
2584 // another thread suspended us. We don't want to continue running
2585 // while suspended because that would surprise the thread that
2586 // suspended us.
2587 sig_sem->signal();
2588
2589 thread->java_suspend_self();
2590 }
2591 } while (threadIsSuspended);
2592 }
2593 }
2594
2595 int os::signal_wait() {
2596 return check_pending_signals(true);
2597 }
2598
2599 ////////////////////////////////////////////////////////////////////////////////
2600 // Virtual Memory
2601
2602 int os::vm_page_size() {
2603 // Seems redundant as all get out
2604 assert(os::Linux::page_size() != -1, "must call os::init");
2605 return os::Linux::page_size();
2606 }
2607
2608 // Solaris allocates memory by pages.
2609 int os::vm_allocation_granularity() {
2610 assert(os::Linux::page_size() != -1, "must call os::init");
2611 return os::Linux::page_size();
2612 }
2613
2614 // Rationale behind this function:
4301
4302 // returns true on success and false on error - really an error is fatal
4303 // but this seems the normal response to library errors
4304 static bool do_suspend(OSThread* osthread) {
4305 assert(osthread->sr.is_running(), "thread should be running");
4306 assert(!sr_semaphore.trywait(), "semaphore has invalid state");
4307
4308 // mark as suspended and send signal
4309 if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) {
4310 // failed to switch, state wasn't running?
4311 ShouldNotReachHere();
4312 return false;
4313 }
4314
4315 if (sr_notify(osthread) != 0) {
4316 ShouldNotReachHere();
4317 }
4318
4319 // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
4320 while (true) {
4321 if (sr_semaphore.timedwait(create_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
4322 break;
4323 } else {
4324 // timeout
4325 os::SuspendResume::State cancelled = osthread->sr.cancel_suspend();
4326 if (cancelled == os::SuspendResume::SR_RUNNING) {
4327 return false;
4328 } else if (cancelled == os::SuspendResume::SR_SUSPENDED) {
4329 // make sure that we consume the signal on the semaphore as well
4330 sr_semaphore.wait();
4331 break;
4332 } else {
4333 ShouldNotReachHere();
4334 return false;
4335 }
4336 }
4337 }
4338
4339 guarantee(osthread->sr.is_suspended(), "Must be suspended");
4340 return true;
4341 }
4342
4343 static void do_resume(OSThread* osthread) {
4344 assert(osthread->sr.is_suspended(), "thread should be suspended");
4345 assert(!sr_semaphore.trywait(), "invalid semaphore state");
4346
4347 if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) {
4348 // failed to switch to WAKEUP_REQUEST
4349 ShouldNotReachHere();
4350 return;
4351 }
4352
4353 while (true) {
4354 if (sr_notify(osthread) == 0) {
4355 if (sr_semaphore.timedwait(create_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
4356 if (osthread->sr.is_running()) {
4357 return;
4358 }
4359 }
4360 } else {
4361 ShouldNotReachHere();
4362 }
4363 }
4364
4365 guarantee(osthread->sr.is_running(), "Must be running!");
4366 }
4367
4368 ///////////////////////////////////////////////////////////////////////////////////
4369 // signal handling (except suspend/resume)
4370
4371 // This routine may be used by user applications as a "hook" to catch signals.
4372 // The user-defined signal handler must pass unrecognized signals to this
4373 // routine, and if it returns true (non-zero), then the signal handler must
4374 // return immediately. If the flag "abort_if_unrecognized" is true, then this
4375 // routine will never retun false (zero), but instead will execute a VM panic
|