comparison src/os/solaris/vm/os_solaris.cpp @ 10405:f2110083203d

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>
author sla
date Mon, 10 Jun 2013 11:30:51 +0200
parents 9ce110b1d14a
children 836a62f43af9 a837fa3d3f86
comparison
equal deleted inserted replaced
10404:d0add7016434 10405:f2110083203d
237 // "default" initializers for pthread-based synchronization 237 // "default" initializers for pthread-based synchronization
238 extern "C" { 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; } 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; } 240 static int pthread_cond_default_init(cond_t *cv, int scope, void *arg){ memset(cv, 0, sizeof(cond_t)); return 0; }
241 } 241 }
242
243 static void unpackTime(timespec* absTime, bool isAbsolute, jlong time);
242 244
243 // Thread Local Storage 245 // Thread Local Storage
244 // This is common to all Solaris platforms so it is defined here, 246 // This is common to all Solaris platforms so it is defined here,
245 // in this common file. 247 // in this common file.
246 // The declarations are in the os_cpu threadLS*.hpp files. 248 // The declarations are in the os_cpu threadLS*.hpp files.
2578 2580
2579 void* os::user_handler() { 2581 void* os::user_handler() {
2580 return CAST_FROM_FN_PTR(void*, UserHandler); 2582 return CAST_FROM_FN_PTR(void*, UserHandler);
2581 } 2583 }
2582 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
2583 extern "C" { 2636 extern "C" {
2584 typedef void (*sa_handler_t)(int); 2637 typedef void (*sa_handler_t)(int);
2585 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); 2638 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
2586 } 2639 }
2587 2640
4162 // Void return because it's a hint and can fail. 4215 // Void return because it's a hint and can fail.
4163 void os::hint_no_preempt() { 4216 void os::hint_no_preempt() {
4164 schedctl_start(schedctl_init()); 4217 schedctl_start(schedctl_init());
4165 } 4218 }
4166 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
4167 void os::interrupt(Thread* thread) { 4282 void os::interrupt(Thread* thread) {
4168 assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); 4283 assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer");
4169 4284
4170 OSThread* osthread = thread->osthread(); 4285 OSThread* osthread = thread->osthread();
4171 4286
4245 while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); } 4360 while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); }
4246 4361
4247 return buf[0] == 'y' || buf[0] == 'Y'; 4362 return buf[0] == 'y' || buf[0] == 'Y';
4248 } 4363 }
4249 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
4250 // A lightweight implementation that does not suspend the target thread and 4475 // A lightweight implementation that does not suspend the target thread and
4251 // thus returns only a hint. Used for profiling only! 4476 // thus returns only a hint. Used for profiling only!
4252 ExtendedPC os::get_thread_pc(Thread* thread) { 4477 ExtendedPC os::get_thread_pc(Thread* thread) {
4253 // Make sure that it is called by the watcher and the Threads lock is owned. 4478 // 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"); 4479 assert(Thread::current()->is_Watcher_thread(), "Must be watcher and own Threads_lock");
4255 // For now, is only used to profile the VM Thread 4480 // For now, is only used to profile the VM Thread
4256 assert(thread->is_VM_thread(), "Can only be called for VMThread"); 4481 assert(thread->is_VM_thread(), "Can only be called for VMThread");
4257 ExtendedPC epc; 4482 PcFetcher fetcher(thread);
4258 4483 fetcher.run();
4259 GetThreadPC_Callback cb(ProfileVM_lock); 4484 return fetcher.result();
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 } 4485 }
4273 4486
4274 4487
4275 // This does not do anything on Solaris. This is basically a hook for being 4488 // 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. 4489 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32.