< prev index next >

src/hotspot/os/solaris/os_solaris.cpp

Print this page




2045 
2046 // sun.misc.Signal
2047 
2048 extern "C" {
2049   static void UserHandler(int sig, void *siginfo, void *context) {
2050     // Ctrl-C is pressed during error reporting, likely because the error
2051     // handler fails to abort. Let VM die immediately.
2052     if (sig == SIGINT && VMError::is_error_reported()) {
2053       os::die();
2054     }
2055 
2056     os::signal_notify(sig);
2057     // We do not need to reinstate the signal handler each time...
2058   }
2059 }
2060 
2061 void* os::user_handler() {
2062   return CAST_FROM_FN_PTR(void*, UserHandler);
2063 }
2064 
2065 struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
2066   struct timespec ts;
2067   unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
2068 
2069   return ts;
2070 }
2071 
2072 extern "C" {
2073   typedef void (*sa_handler_t)(int);
2074   typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
2075 }
2076 
2077 void* os::signal(int signal_number, void* handler) {
2078   struct sigaction sigAct, oldSigAct;
2079   sigfillset(&(sigAct.sa_mask));
2080   sigAct.sa_flags = SA_RESTART & ~SA_RESETHAND;
2081   sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler);
2082 
2083   if (sigaction(signal_number, &sigAct, &oldSigAct)) {
2084     // -1 means registration failed
2085     return (void *)-1;
2086   }
2087 
2088   return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler);
2089 }
2090 
2091 void os::signal_raise(int signal_number) {
2092   raise(signal_number);
2093 }
2094 
2095 // The following code is moved from os.cpp for making this
2096 // code platform specific, which it is by its very nature.
2097 
2098 // a counter for each possible signal value
2099 static int Sigexit = 0;
2100 static jint *pending_signals = NULL;
2101 static int *preinstalled_sigs = NULL;
2102 static struct sigaction *chainedsigactions = NULL;
2103 static sema_t sig_sem;
2104 typedef int (*version_getting_t)();
2105 version_getting_t os::Solaris::get_libjsig_version = NULL;
2106 
2107 int os::sigexitnum_pd() {
2108   assert(Sigexit > 0, "signal memory not yet initialized");
2109   return Sigexit;
2110 }
2111 
2112 void os::Solaris::init_signal_mem() {
2113   // Initialize signal structures
2114   Maxsignum = SIGRTMAX;
2115   Sigexit = Maxsignum+1;
2116   assert(Maxsignum >0, "Unable to obtain max signal number");
2117 

2118   // pending_signals has one int per signal
2119   // The additional signal is for SIGEXIT - exit signal to signal_thread
2120   pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1), mtInternal);
2121   memset(pending_signals, 0, (sizeof(jint) * (Sigexit+1)));
2122 
2123   if (UseSignalChaining) {
2124     chainedsigactions = (struct sigaction *)malloc(sizeof(struct sigaction)
2125                                                    * (Maxsignum + 1), mtInternal);
2126     memset(chainedsigactions, 0, (sizeof(struct sigaction) * (Maxsignum + 1)));
2127     preinstalled_sigs = (int *)os::malloc(sizeof(int) * (Maxsignum + 1), mtInternal);
2128     memset(preinstalled_sigs, 0, (sizeof(int) * (Maxsignum + 1)));
2129   }
2130   ourSigFlags = (int*)malloc(sizeof(int) * (Maxsignum + 1), mtInternal);
2131   memset(ourSigFlags, 0, sizeof(int) * (Maxsignum + 1));
2132 }
2133 
2134 void os::signal_init_pd() {
2135   int ret;
2136 
2137   ret = ::sema_init(&sig_sem, 0, NULL, NULL);
2138   assert(ret == 0, "sema_init() failed");
2139 }
2140 
2141 void os::signal_notify(int signal_number) {
2142   int ret;
2143 
2144   Atomic::inc(&pending_signals[signal_number]);
2145   ret = ::sema_post(&sig_sem);
2146   assert(ret == 0, "sema_post() failed");



2147 }
2148 
2149 static int check_pending_signals(bool wait_for_signal) {
2150   int ret;
2151   while (true) {
2152     for (int i = 0; i < Sigexit + 1; i++) {
2153       jint n = pending_signals[i];
2154       if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) {
2155         return i;
2156       }
2157     }
2158     if (!wait_for_signal) {
2159       return -1;
2160     }
2161     JavaThread *thread = JavaThread::current();
2162     ThreadBlockInVM tbivm(thread);
2163 
2164     bool threadIsSuspended;
2165     do {
2166       thread->set_suspend_equivalent();
2167       // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
2168       while ((ret = ::sema_wait(&sig_sem)) == EINTR)
2169         ;
2170       assert(ret == 0, "sema_wait() failed");
2171 
2172       // were we externally suspended while we were waiting?
2173       threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
2174       if (threadIsSuspended) {
2175         // The semaphore has been incremented, but while we were waiting
2176         // another thread suspended us. We don't want to continue running
2177         // while suspended because that would surprise the thread that
2178         // suspended us.
2179         ret = ::sema_post(&sig_sem);
2180         assert(ret == 0, "sema_post() failed");
2181 
2182         thread->java_suspend_self();
2183       }
2184     } while (threadIsSuspended);
2185   }
2186 }
2187 
2188 int os::signal_lookup() {
2189   return check_pending_signals(false);
2190 }
2191 
2192 int os::signal_wait() {
2193   return check_pending_signals(true);
2194 }
2195 
2196 ////////////////////////////////////////////////////////////////////////////////
2197 // Virtual Memory
2198 
2199 static int page_size = -1;
2200 
2201 int os::vm_page_size() {
2202   assert(page_size != -1, "must call os::init");
2203   return page_size;
2204 }
2205 
2206 // Solaris allocates memory by pages.
2207 int os::vm_allocation_granularity() {
2208   assert(page_size != -1, "must call os::init");
2209   return page_size;
2210 }
2211 


3582 static const int RANDOMLY_LARGE_INTEGER = 1000000;
3583 static const int RANDOMLY_LARGE_INTEGER2 = 100;
3584 
3585 static bool do_suspend(OSThread* osthread) {
3586   assert(osthread->sr.is_running(), "thread should be running");
3587   assert(!sr_semaphore.trywait(), "semaphore has invalid state");
3588 
3589   // mark as suspended and send signal
3590   if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) {
3591     // failed to switch, state wasn't running?
3592     ShouldNotReachHere();
3593     return false;
3594   }
3595 
3596   if (sr_notify(osthread) != 0) {
3597     ShouldNotReachHere();
3598   }
3599 
3600   // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
3601   while (true) {
3602     if (sr_semaphore.timedwait(0, 2000 * NANOSECS_PER_MILLISEC)) {
3603       break;
3604     } else {
3605       // timeout
3606       os::SuspendResume::State cancelled = osthread->sr.cancel_suspend();
3607       if (cancelled == os::SuspendResume::SR_RUNNING) {
3608         return false;
3609       } else if (cancelled == os::SuspendResume::SR_SUSPENDED) {
3610         // make sure that we consume the signal on the semaphore as well
3611         sr_semaphore.wait();
3612         break;
3613       } else {
3614         ShouldNotReachHere();
3615         return false;
3616       }
3617     }
3618   }
3619 
3620   guarantee(osthread->sr.is_suspended(), "Must be suspended");
3621   return true;
3622 }
3623 
3624 static void do_resume(OSThread* osthread) {
3625   assert(osthread->sr.is_suspended(), "thread should be suspended");
3626   assert(!sr_semaphore.trywait(), "invalid semaphore state");
3627 
3628   if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) {
3629     // failed to switch to WAKEUP_REQUEST
3630     ShouldNotReachHere();
3631     return;
3632   }
3633 
3634   while (true) {
3635     if (sr_notify(osthread) == 0) {
3636       if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) {
3637         if (osthread->sr.is_running()) {
3638           return;
3639         }
3640       }
3641     } else {
3642       ShouldNotReachHere();
3643     }
3644   }
3645 
3646   guarantee(osthread->sr.is_running(), "Must be running!");
3647 }
3648 
3649 void os::SuspendedThreadTask::internal_do_task() {
3650   if (do_suspend(_thread->osthread())) {
3651     SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext());
3652     do_task(context);
3653     do_resume(_thread->osthread());
3654   }
3655 }
3656 




2045 
2046 // sun.misc.Signal
2047 
2048 extern "C" {
2049   static void UserHandler(int sig, void *siginfo, void *context) {
2050     // Ctrl-C is pressed during error reporting, likely because the error
2051     // handler fails to abort. Let VM die immediately.
2052     if (sig == SIGINT && VMError::is_error_reported()) {
2053       os::die();
2054     }
2055 
2056     os::signal_notify(sig);
2057     // We do not need to reinstate the signal handler each time...
2058   }
2059 }
2060 
2061 void* os::user_handler() {
2062   return CAST_FROM_FN_PTR(void*, UserHandler);
2063 }
2064 
2065 static struct timespec create_timespec(unsigned int sec, int nsec) {
2066   struct timespec ts;
2067   unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
2068 
2069   return ts;
2070 }
2071 
2072 extern "C" {
2073   typedef void (*sa_handler_t)(int);
2074   typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
2075 }
2076 
2077 void* os::signal(int signal_number, void* handler) {
2078   struct sigaction sigAct, oldSigAct;
2079   sigfillset(&(sigAct.sa_mask));
2080   sigAct.sa_flags = SA_RESTART & ~SA_RESETHAND;
2081   sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler);
2082 
2083   if (sigaction(signal_number, &sigAct, &oldSigAct)) {
2084     // -1 means registration failed
2085     return (void *)-1;
2086   }
2087 
2088   return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler);
2089 }
2090 
2091 void os::signal_raise(int signal_number) {
2092   raise(signal_number);
2093 }
2094 
2095 // The following code is moved from os.cpp for making this
2096 // code platform specific, which it is by its very nature.
2097 
2098 // a counter for each possible signal value
2099 static int Sigexit = 0;
2100 static jint *pending_signals = NULL;
2101 static int *preinstalled_sigs = NULL;
2102 static struct sigaction *chainedsigactions = NULL;
2103 static Semaphore* sig_sem = NULL;
2104 typedef int (*version_getting_t)();
2105 version_getting_t os::Solaris::get_libjsig_version = NULL;
2106 
2107 int os::sigexitnum_pd() {
2108   assert(Sigexit > 0, "signal memory not yet initialized");
2109   return Sigexit;
2110 }
2111 
2112 void os::Solaris::init_signal_mem() {
2113   // Initialize signal structures
2114   Maxsignum = SIGRTMAX;
2115   Sigexit = Maxsignum+1;
2116   assert(Maxsignum >0, "Unable to obtain max signal number");
2117 
2118   // Initialize signal structures
2119   // pending_signals has one int per signal
2120   // The additional signal is for SIGEXIT - exit signal to signal_thread
2121   pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1), mtInternal);
2122   memset(pending_signals, 0, (sizeof(jint) * (Sigexit+1)));
2123 
2124   if (UseSignalChaining) {
2125     chainedsigactions = (struct sigaction *)malloc(sizeof(struct sigaction)
2126                                                    * (Maxsignum + 1), mtInternal);
2127     memset(chainedsigactions, 0, (sizeof(struct sigaction) * (Maxsignum + 1)));
2128     preinstalled_sigs = (int *)os::malloc(sizeof(int) * (Maxsignum + 1), mtInternal);
2129     memset(preinstalled_sigs, 0, (sizeof(int) * (Maxsignum + 1)));
2130   }
2131   ourSigFlags = (int*)malloc(sizeof(int) * (Maxsignum + 1), mtInternal);
2132   memset(ourSigFlags, 0, sizeof(int) * (Maxsignum + 1));
2133 }
2134 
2135 void os::signal_init_pd() {
2136   // Initialize signal semaphore
2137   sig_sem = new Semaphore();


2138 }
2139 
2140 void os::signal_notify(int sig) {
2141   if (sig_sem != NULL) {
2142     Atomic::inc(&pending_signals[sig]);
2143     sig_sem->signal();
2144   } else {
2145     // Signal thread is not created with ReduceSignalUsage and signal_init_pd
2146     // initialization isn't called.
2147     assert(ReduceSignalUsage, "signal semaphore should be created");
2148   }
2149 }
2150 
2151 static int check_pending_signals(bool wait_for_signal) {
2152   int ret;
2153   while (true) {
2154     for (int i = 0; i < Sigexit + 1; i++) {
2155       jint n = pending_signals[i];
2156       if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) {
2157         return i;
2158       }
2159     }
2160     if (!wait_for_signal) {
2161       return -1;
2162     }
2163     JavaThread *thread = JavaThread::current();
2164     ThreadBlockInVM tbivm(thread);
2165 
2166     bool threadIsSuspended;
2167     do {
2168       thread->set_suspend_equivalent();
2169       sig_sem->wait();



2170 
2171       // were we externally suspended while we were waiting?
2172       threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
2173       if (threadIsSuspended) {
2174         // The semaphore has been incremented, but while we were waiting
2175         // another thread suspended us. We don't want to continue running
2176         // while suspended because that would surprise the thread that
2177         // suspended us.
2178         sig_sem->signal();

2179 
2180         thread->java_suspend_self();
2181       }
2182     } while (threadIsSuspended);
2183   }
2184 }
2185 




2186 int os::signal_wait() {
2187   return check_pending_signals(true);
2188 }
2189 
2190 ////////////////////////////////////////////////////////////////////////////////
2191 // Virtual Memory
2192 
2193 static int page_size = -1;
2194 
2195 int os::vm_page_size() {
2196   assert(page_size != -1, "must call os::init");
2197   return page_size;
2198 }
2199 
2200 // Solaris allocates memory by pages.
2201 int os::vm_allocation_granularity() {
2202   assert(page_size != -1, "must call os::init");
2203   return page_size;
2204 }
2205 


3576 static const int RANDOMLY_LARGE_INTEGER = 1000000;
3577 static const int RANDOMLY_LARGE_INTEGER2 = 100;
3578 
3579 static bool do_suspend(OSThread* osthread) {
3580   assert(osthread->sr.is_running(), "thread should be running");
3581   assert(!sr_semaphore.trywait(), "semaphore has invalid state");
3582 
3583   // mark as suspended and send signal
3584   if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) {
3585     // failed to switch, state wasn't running?
3586     ShouldNotReachHere();
3587     return false;
3588   }
3589 
3590   if (sr_notify(osthread) != 0) {
3591     ShouldNotReachHere();
3592   }
3593 
3594   // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
3595   while (true) {
3596     if (sr_semaphore.timedwait(create_timespec(0, 2000 * NANOSECS_PER_MILLISEC))) {
3597       break;
3598     } else {
3599       // timeout
3600       os::SuspendResume::State cancelled = osthread->sr.cancel_suspend();
3601       if (cancelled == os::SuspendResume::SR_RUNNING) {
3602         return false;
3603       } else if (cancelled == os::SuspendResume::SR_SUSPENDED) {
3604         // make sure that we consume the signal on the semaphore as well
3605         sr_semaphore.wait();
3606         break;
3607       } else {
3608         ShouldNotReachHere();
3609         return false;
3610       }
3611     }
3612   }
3613 
3614   guarantee(osthread->sr.is_suspended(), "Must be suspended");
3615   return true;
3616 }
3617 
3618 static void do_resume(OSThread* osthread) {
3619   assert(osthread->sr.is_suspended(), "thread should be suspended");
3620   assert(!sr_semaphore.trywait(), "invalid semaphore state");
3621 
3622   if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) {
3623     // failed to switch to WAKEUP_REQUEST
3624     ShouldNotReachHere();
3625     return;
3626   }
3627 
3628   while (true) {
3629     if (sr_notify(osthread) == 0) {
3630       if (sr_semaphore.timedwait(create_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
3631         if (osthread->sr.is_running()) {
3632           return;
3633         }
3634       }
3635     } else {
3636       ShouldNotReachHere();
3637     }
3638   }
3639 
3640   guarantee(osthread->sr.is_running(), "Must be running!");
3641 }
3642 
3643 void os::SuspendedThreadTask::internal_do_task() {
3644   if (do_suspend(_thread->osthread())) {
3645     SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext());
3646     do_task(context);
3647     do_resume(_thread->osthread());
3648   }
3649 }
3650 


< prev index next >