< prev index next >

src/hotspot/os/linux/os_linux.cpp

Print this page




  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


< prev index next >