src/os/solaris/vm/os_solaris.cpp

Print this page
rev 4773 : 8005849: JEP 167: Event-Based JVM Tracing
Reviewed-by: acorn, coleenp, sla
Contributed-by: Karen Kinnear <karen.kinnear@oracle.com>, Bengt Rutisson <bengt.rutisson@oracle.com>, Calvin Cheung <calvin.cheung@oracle.com>, Erik Gahlin <erik.gahlin@oracle.com>, Erik Helin <erik.helin@oracle.com>, Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com>, Keith McGuigan <keith.mcguigan@oracle.com>, Mattias Tobiasson <mattias.tobiasson@oracle.com>, Markus Gronlund <markus.gronlund@oracle.com>, Mikael Auno <mikael.auno@oracle.com>, Nils Eliasson <nils.eliasson@oracle.com>, Nils Loodin <nils.loodin@oracle.com>, Rickard Backman <rickard.backman@oracle.com>, Staffan Larsen <staffan.larsen@oracle.com>, Stefan Karlsson <stefan.karlsson@oracle.com>, Yekaterina Kantserova <yekaterina.kantserova@oracle.com>


 223 address os::Solaris::handler_end;    // end pc of thr_sighndlrinfo
 224 
 225 address os::Solaris::_main_stack_base = NULL;  // 4352906 workaround
 226 
 227 
 228 // "default" initializers for missing libc APIs
 229 extern "C" {
 230   static int lwp_mutex_init(mutex_t *mx, int scope, void *arg) { memset(mx, 0, sizeof(mutex_t)); return 0; }
 231   static int lwp_mutex_destroy(mutex_t *mx)                 { return 0; }
 232 
 233   static int lwp_cond_init(cond_t *cv, int scope, void *arg){ memset(cv, 0, sizeof(cond_t)); return 0; }
 234   static int lwp_cond_destroy(cond_t *cv)                   { return 0; }
 235 }
 236 
 237 // "default" initializers for pthread-based synchronization
 238 extern "C" {
 239   static int pthread_mutex_default_init(mutex_t *mx, int scope, void *arg) { memset(mx, 0, sizeof(mutex_t)); return 0; }
 240   static int pthread_cond_default_init(cond_t *cv, int scope, void *arg){ memset(cv, 0, sizeof(cond_t)); return 0; }
 241 }
 242 


 243 // Thread Local Storage
 244 // This is common to all Solaris platforms so it is defined here,
 245 // in this common file.
 246 // The declarations are in the os_cpu threadLS*.hpp files.
 247 //
 248 // Static member initialization for TLS
 249 Thread* ThreadLocalStorage::_get_thread_cache[ThreadLocalStorage::_pd_cache_size] = {NULL};
 250 
 251 #ifndef PRODUCT
 252 #define _PCT(n,d)       ((100.0*(double)(n))/(double)(d))
 253 
 254 int ThreadLocalStorage::_tcacheHit = 0;
 255 int ThreadLocalStorage::_tcacheMiss = 0;
 256 
 257 void ThreadLocalStorage::print_statistics() {
 258   int total = _tcacheMiss+_tcacheHit;
 259   tty->print_cr("Thread cache hits %d misses %d total %d percent %f\n",
 260                 _tcacheHit, _tcacheMiss, total, _PCT(_tcacheHit, total));
 261 }
 262 #undef _PCT


2563 
2564 // sun.misc.Signal
2565 
2566 extern "C" {
2567   static void UserHandler(int sig, void *siginfo, void *context) {
2568     // Ctrl-C is pressed during error reporting, likely because the error
2569     // handler fails to abort. Let VM die immediately.
2570     if (sig == SIGINT && is_error_reported()) {
2571        os::die();
2572     }
2573 
2574     os::signal_notify(sig);
2575     // We do not need to reinstate the signal handler each time...
2576   }
2577 }
2578 
2579 void* os::user_handler() {
2580   return CAST_FROM_FN_PTR(void*, UserHandler);
2581 }
2582 



















































2583 extern "C" {
2584   typedef void (*sa_handler_t)(int);
2585   typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
2586 }
2587 
2588 void* os::signal(int signal_number, void* handler) {
2589   struct sigaction sigAct, oldSigAct;
2590   sigfillset(&(sigAct.sa_mask));
2591   sigAct.sa_flags = SA_RESTART & ~SA_RESETHAND;
2592   sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler);
2593 
2594   if (sigaction(signal_number, &sigAct, &oldSigAct))
2595     // -1 means registration failed
2596     return (void *)-1;
2597 
2598   return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler);
2599 }
2600 
2601 void os::signal_raise(int signal_number) {
2602   raise(signal_number);


4147   int p;
4148   if ( !UseThreadPriorities ) {
4149     *priority_ptr = NormalPriority;
4150     return OS_OK;
4151   }
4152   int status = thr_getprio(thread->osthread()->thread_id(), &p);
4153   if (status != 0) {
4154     return OS_ERR;
4155   }
4156   *priority_ptr = p;
4157   return OS_OK;
4158 }
4159 
4160 
4161 // Hint to the underlying OS that a task switch would not be good.
4162 // Void return because it's a hint and can fail.
4163 void os::hint_no_preempt() {
4164   schedctl_start(schedctl_init());
4165 }
4166 






























































4167 void os::interrupt(Thread* thread) {
4168   assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer");
4169 
4170   OSThread* osthread = thread->osthread();
4171 
4172   int isInterrupted = osthread->interrupted();
4173   if (!isInterrupted) {
4174       osthread->set_interrupted(true);
4175       OrderAccess::fence();
4176       // os::sleep() is implemented with either poll (NULL,0,timeout) or
4177       // by parking on _SleepEvent.  If the former, thr_kill will unwedge
4178       // the sleeper by SIGINTR, otherwise the unpark() will wake the sleeper.
4179       ParkEvent * const slp = thread->_SleepEvent ;
4180       if (slp != NULL) slp->unpark() ;
4181   }
4182 
4183   // For JSR166:  unpark after setting status but before thr_kill -dl
4184   if (thread->is_Java_thread()) {
4185     ((JavaThread*)thread)->parker()->unpark();
4186   }


4230 
4231 int os::message_box(const char* title, const char* message) {
4232   int i;
4233   fdStream err(defaultStream::error_fd());
4234   for (i = 0; i < 78; i++) err.print_raw("=");
4235   err.cr();
4236   err.print_raw_cr(title);
4237   for (i = 0; i < 78; i++) err.print_raw("-");
4238   err.cr();
4239   err.print_raw_cr(message);
4240   for (i = 0; i < 78; i++) err.print_raw("=");
4241   err.cr();
4242 
4243   char buf[16];
4244   // Prevent process from exiting upon "read error" without consuming all CPU
4245   while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); }
4246 
4247   return buf[0] == 'y' || buf[0] == 'Y';
4248 }
4249 














































































































4250 // A lightweight implementation that does not suspend the target thread and
4251 // thus returns only a hint. Used for profiling only!
4252 ExtendedPC os::get_thread_pc(Thread* thread) {
4253   // Make sure that it is called by the watcher and the Threads lock is owned.
4254   assert(Thread::current()->is_Watcher_thread(), "Must be watcher and own Threads_lock");
4255   // For now, is only used to profile the VM Thread
4256   assert(thread->is_VM_thread(), "Can only be called for VMThread");
4257   ExtendedPC epc;
4258 
4259   GetThreadPC_Callback  cb(ProfileVM_lock);
4260   OSThread *osthread = thread->osthread();
4261   const int time_to_wait = 400; // 400ms wait for initial response
4262   int status = cb.interrupt(thread, time_to_wait);
4263 
4264   if (cb.is_done() ) {
4265     epc = cb.addr();
4266   } else {
4267     DEBUG_ONLY(tty->print_cr("Failed to get pc for thread: %d got %d status",
4268                               osthread->thread_id(), status););
4269     // epc is already NULL
4270   }
4271   return epc;
4272 }
4273 
4274 
4275 // This does not do anything on Solaris. This is basically a hook for being
4276 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
4277 void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) {
4278   f(value, method, args, thread);
4279 }
4280 
4281 // This routine may be used by user applications as a "hook" to catch signals.
4282 // The user-defined signal handler must pass unrecognized signals to this
4283 // routine, and if it returns true (non-zero), then the signal handler must
4284 // return immediately.  If the flag "abort_if_unrecognized" is true, then this
4285 // routine will never retun false (zero), but instead will execute a VM panic
4286 // routine kill the process.
4287 //
4288 // If this routine returns false, it is OK to call it again.  This allows
4289 // the user-defined signal handler to perform checks either before or after
4290 // the VM performs its own checks.  Naturally, the user code would be making
4291 // a serious error if it tried to handle an exception (such as a null check




 223 address os::Solaris::handler_end;    // end pc of thr_sighndlrinfo
 224 
 225 address os::Solaris::_main_stack_base = NULL;  // 4352906 workaround
 226 
 227 
 228 // "default" initializers for missing libc APIs
 229 extern "C" {
 230   static int lwp_mutex_init(mutex_t *mx, int scope, void *arg) { memset(mx, 0, sizeof(mutex_t)); return 0; }
 231   static int lwp_mutex_destroy(mutex_t *mx)                 { return 0; }
 232 
 233   static int lwp_cond_init(cond_t *cv, int scope, void *arg){ memset(cv, 0, sizeof(cond_t)); return 0; }
 234   static int lwp_cond_destroy(cond_t *cv)                   { return 0; }
 235 }
 236 
 237 // "default" initializers for pthread-based synchronization
 238 extern "C" {
 239   static int pthread_mutex_default_init(mutex_t *mx, int scope, void *arg) { memset(mx, 0, sizeof(mutex_t)); return 0; }
 240   static int pthread_cond_default_init(cond_t *cv, int scope, void *arg){ memset(cv, 0, sizeof(cond_t)); return 0; }
 241 }
 242 
 243 static void unpackTime(timespec* absTime, bool isAbsolute, jlong time);
 244 
 245 // Thread Local Storage
 246 // This is common to all Solaris platforms so it is defined here,
 247 // in this common file.
 248 // The declarations are in the os_cpu threadLS*.hpp files.
 249 //
 250 // Static member initialization for TLS
 251 Thread* ThreadLocalStorage::_get_thread_cache[ThreadLocalStorage::_pd_cache_size] = {NULL};
 252 
 253 #ifndef PRODUCT
 254 #define _PCT(n,d)       ((100.0*(double)(n))/(double)(d))
 255 
 256 int ThreadLocalStorage::_tcacheHit = 0;
 257 int ThreadLocalStorage::_tcacheMiss = 0;
 258 
 259 void ThreadLocalStorage::print_statistics() {
 260   int total = _tcacheMiss+_tcacheHit;
 261   tty->print_cr("Thread cache hits %d misses %d total %d percent %f\n",
 262                 _tcacheHit, _tcacheMiss, total, _PCT(_tcacheHit, total));
 263 }
 264 #undef _PCT


2565 
2566 // sun.misc.Signal
2567 
2568 extern "C" {
2569   static void UserHandler(int sig, void *siginfo, void *context) {
2570     // Ctrl-C is pressed during error reporting, likely because the error
2571     // handler fails to abort. Let VM die immediately.
2572     if (sig == SIGINT && is_error_reported()) {
2573        os::die();
2574     }
2575 
2576     os::signal_notify(sig);
2577     // We do not need to reinstate the signal handler each time...
2578   }
2579 }
2580 
2581 void* os::user_handler() {
2582   return CAST_FROM_FN_PTR(void*, UserHandler);
2583 }
2584 
2585 class Semaphore : public StackObj {
2586   public:
2587     Semaphore();
2588     ~Semaphore();
2589     void signal();
2590     void wait();
2591     bool trywait();
2592     bool timedwait(unsigned int sec, int nsec);
2593   private:
2594     sema_t _semaphore;
2595 };
2596 
2597 
2598 Semaphore::Semaphore() {
2599   sema_init(&_semaphore, 0, NULL, NULL);
2600 }
2601 
2602 Semaphore::~Semaphore() {
2603   sema_destroy(&_semaphore);
2604 }
2605 
2606 void Semaphore::signal() {
2607   sema_post(&_semaphore);
2608 }
2609 
2610 void Semaphore::wait() {
2611   sema_wait(&_semaphore);
2612 }
2613 
2614 bool Semaphore::trywait() {
2615   return sema_trywait(&_semaphore) == 0;
2616 }
2617 
2618 bool Semaphore::timedwait(unsigned int sec, int nsec) {
2619   struct timespec ts;
2620   unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
2621 
2622   while (1) {
2623     int result = sema_timedwait(&_semaphore, &ts);
2624     if (result == 0) {
2625       return true;
2626     } else if (errno == EINTR) {
2627       continue;
2628     } else if (errno == ETIME) {
2629       return false;
2630     } else {
2631       return false;
2632     }
2633   }
2634 }
2635 
2636 extern "C" {
2637   typedef void (*sa_handler_t)(int);
2638   typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
2639 }
2640 
2641 void* os::signal(int signal_number, void* handler) {
2642   struct sigaction sigAct, oldSigAct;
2643   sigfillset(&(sigAct.sa_mask));
2644   sigAct.sa_flags = SA_RESTART & ~SA_RESETHAND;
2645   sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler);
2646 
2647   if (sigaction(signal_number, &sigAct, &oldSigAct))
2648     // -1 means registration failed
2649     return (void *)-1;
2650 
2651   return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler);
2652 }
2653 
2654 void os::signal_raise(int signal_number) {
2655   raise(signal_number);


4200   int p;
4201   if ( !UseThreadPriorities ) {
4202     *priority_ptr = NormalPriority;
4203     return OS_OK;
4204   }
4205   int status = thr_getprio(thread->osthread()->thread_id(), &p);
4206   if (status != 0) {
4207     return OS_ERR;
4208   }
4209   *priority_ptr = p;
4210   return OS_OK;
4211 }
4212 
4213 
4214 // Hint to the underlying OS that a task switch would not be good.
4215 // Void return because it's a hint and can fail.
4216 void os::hint_no_preempt() {
4217   schedctl_start(schedctl_init());
4218 }
4219 
4220 static void resume_clear_context(OSThread *osthread) {
4221   osthread->set_ucontext(NULL);
4222 }
4223 
4224 static void suspend_save_context(OSThread *osthread, ucontext_t* context) {
4225   osthread->set_ucontext(context);
4226 }
4227 
4228 static Semaphore sr_semaphore;
4229 
4230 void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) {
4231   // Save and restore errno to avoid confusing native code with EINTR
4232   // after sigsuspend.
4233   int old_errno = errno;
4234 
4235   OSThread* osthread = thread->osthread();
4236   assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
4237 
4238   os::SuspendResume::State current = osthread->sr.state();
4239   if (current == os::SuspendResume::SR_SUSPEND_REQUEST) {
4240     suspend_save_context(osthread, uc);
4241 
4242     // attempt to switch the state, we assume we had a SUSPEND_REQUEST
4243     os::SuspendResume::State state = osthread->sr.suspended();
4244     if (state == os::SuspendResume::SR_SUSPENDED) {
4245       sigset_t suspend_set;  // signals for sigsuspend()
4246 
4247       // get current set of blocked signals and unblock resume signal
4248       thr_sigsetmask(SIG_BLOCK, NULL, &suspend_set);
4249       sigdelset(&suspend_set, os::Solaris::SIGasync());
4250 
4251       sr_semaphore.signal();
4252       // wait here until we are resumed
4253       while (1) {
4254         sigsuspend(&suspend_set);
4255 
4256         os::SuspendResume::State result = osthread->sr.running();
4257         if (result == os::SuspendResume::SR_RUNNING) {
4258           sr_semaphore.signal();
4259           break;
4260         }
4261       }
4262 
4263     } else if (state == os::SuspendResume::SR_RUNNING) {
4264       // request was cancelled, continue
4265     } else {
4266       ShouldNotReachHere();
4267     }
4268 
4269     resume_clear_context(osthread);
4270   } else if (current == os::SuspendResume::SR_RUNNING) {
4271     // request was cancelled, continue
4272   } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) {
4273     // ignore
4274   } else {
4275     // ignore
4276   }
4277 
4278   errno = old_errno;
4279 }
4280 
4281 
4282 void os::interrupt(Thread* thread) {
4283   assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer");
4284 
4285   OSThread* osthread = thread->osthread();
4286 
4287   int isInterrupted = osthread->interrupted();
4288   if (!isInterrupted) {
4289       osthread->set_interrupted(true);
4290       OrderAccess::fence();
4291       // os::sleep() is implemented with either poll (NULL,0,timeout) or
4292       // by parking on _SleepEvent.  If the former, thr_kill will unwedge
4293       // the sleeper by SIGINTR, otherwise the unpark() will wake the sleeper.
4294       ParkEvent * const slp = thread->_SleepEvent ;
4295       if (slp != NULL) slp->unpark() ;
4296   }
4297 
4298   // For JSR166:  unpark after setting status but before thr_kill -dl
4299   if (thread->is_Java_thread()) {
4300     ((JavaThread*)thread)->parker()->unpark();
4301   }


4345 
4346 int os::message_box(const char* title, const char* message) {
4347   int i;
4348   fdStream err(defaultStream::error_fd());
4349   for (i = 0; i < 78; i++) err.print_raw("=");
4350   err.cr();
4351   err.print_raw_cr(title);
4352   for (i = 0; i < 78; i++) err.print_raw("-");
4353   err.cr();
4354   err.print_raw_cr(message);
4355   for (i = 0; i < 78; i++) err.print_raw("=");
4356   err.cr();
4357 
4358   char buf[16];
4359   // Prevent process from exiting upon "read error" without consuming all CPU
4360   while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); }
4361 
4362   return buf[0] == 'y' || buf[0] == 'Y';
4363 }
4364 
4365 static int sr_notify(OSThread* osthread) {
4366   int status = thr_kill(osthread->thread_id(), os::Solaris::SIGasync());
4367   assert_status(status == 0, status, "thr_kill");
4368   return status;
4369 }
4370 
4371 // "Randomly" selected value for how long we want to spin
4372 // before bailing out on suspending a thread, also how often
4373 // we send a signal to a thread we want to resume
4374 static const int RANDOMLY_LARGE_INTEGER = 1000000;
4375 static const int RANDOMLY_LARGE_INTEGER2 = 100;
4376 
4377 static bool do_suspend(OSThread* osthread) {
4378   assert(osthread->sr.is_running(), "thread should be running");
4379   assert(!sr_semaphore.trywait(), "semaphore has invalid state");
4380 
4381   // mark as suspended and send signal
4382   if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) {
4383     // failed to switch, state wasn't running?
4384     ShouldNotReachHere();
4385     return false;
4386   }
4387 
4388   if (sr_notify(osthread) != 0) {
4389     ShouldNotReachHere();
4390   }
4391 
4392   // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
4393   while (true) {
4394     if (sr_semaphore.timedwait(0, 2000 * NANOSECS_PER_MILLISEC)) {
4395       break;
4396     } else {
4397       // timeout
4398       os::SuspendResume::State cancelled = osthread->sr.cancel_suspend();
4399       if (cancelled == os::SuspendResume::SR_RUNNING) {
4400         return false;
4401       } else if (cancelled == os::SuspendResume::SR_SUSPENDED) {
4402         // make sure that we consume the signal on the semaphore as well
4403         sr_semaphore.wait();
4404         break;
4405       } else {
4406         ShouldNotReachHere();
4407         return false;
4408       }
4409     }
4410   }
4411 
4412   guarantee(osthread->sr.is_suspended(), "Must be suspended");
4413   return true;
4414 }
4415 
4416 static void do_resume(OSThread* osthread) {
4417   assert(osthread->sr.is_suspended(), "thread should be suspended");
4418   assert(!sr_semaphore.trywait(), "invalid semaphore state");
4419 
4420   if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) {
4421     // failed to switch to WAKEUP_REQUEST
4422     ShouldNotReachHere();
4423     return;
4424   }
4425 
4426   while (true) {
4427     if (sr_notify(osthread) == 0) {
4428       if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) {
4429         if (osthread->sr.is_running()) {
4430           return;
4431         }
4432       }
4433     } else {
4434       ShouldNotReachHere();
4435     }
4436   }
4437 
4438   guarantee(osthread->sr.is_running(), "Must be running!");
4439 }
4440 
4441 void os::SuspendedThreadTask::internal_do_task() {
4442   if (do_suspend(_thread->osthread())) {
4443     SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext());
4444     do_task(context);
4445     do_resume(_thread->osthread());
4446   }
4447 }
4448 
4449 class PcFetcher : public os::SuspendedThreadTask {
4450 public:
4451   PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {}
4452   ExtendedPC result();
4453 protected:
4454   void do_task(const os::SuspendedThreadTaskContext& context);
4455 private:
4456   ExtendedPC _epc;
4457 };
4458 
4459 ExtendedPC PcFetcher::result() {
4460   guarantee(is_done(), "task is not done yet.");
4461   return _epc;
4462 }
4463 
4464 void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) {
4465   Thread* thread = context.thread();
4466   OSThread* osthread = thread->osthread();
4467   if (osthread->ucontext() != NULL) {
4468     _epc = os::Solaris::ucontext_get_pc((ucontext_t *) context.ucontext());
4469   } else {
4470     // NULL context is unexpected, double-check this is the VMThread
4471     guarantee(thread->is_VM_thread(), "can only be called for VMThread");
4472   }
4473 }
4474 
4475 // A lightweight implementation that does not suspend the target thread and
4476 // thus returns only a hint. Used for profiling only!
4477 ExtendedPC os::get_thread_pc(Thread* thread) {
4478   // Make sure that it is called by the watcher and the Threads lock is owned.
4479   assert(Thread::current()->is_Watcher_thread(), "Must be watcher and own Threads_lock");
4480   // For now, is only used to profile the VM Thread
4481   assert(thread->is_VM_thread(), "Can only be called for VMThread");
4482   PcFetcher fetcher(thread);
4483   fetcher.run();
4484   return fetcher.result();












4485 }
4486 
4487 
4488 // This does not do anything on Solaris. This is basically a hook for being
4489 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
4490 void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) {
4491   f(value, method, args, thread);
4492 }
4493 
4494 // This routine may be used by user applications as a "hook" to catch signals.
4495 // The user-defined signal handler must pass unrecognized signals to this
4496 // routine, and if it returns true (non-zero), then the signal handler must
4497 // return immediately.  If the flag "abort_if_unrecognized" is true, then this
4498 // routine will never retun false (zero), but instead will execute a VM panic
4499 // routine kill the process.
4500 //
4501 // If this routine returns false, it is OK to call it again.  This allows
4502 // the user-defined signal handler to perform checks either before or after
4503 // the VM performs its own checks.  Naturally, the user code would be making
4504 // a serious error if it tried to handle an exception (such as a null check