src/os_cpu/solaris_x86/vm/os_solaris_x86.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>
   1 /*
   2  * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


 166     }
 167   }
 168   return retuc;
 169 }
 170 
 171 // Assumes ucontext is valid
 172 ExtendedPC os::Solaris::ucontext_get_ExtendedPC(ucontext_t *uc) {
 173   return ExtendedPC((address)uc->uc_mcontext.gregs[REG_PC]);
 174 }
 175 
 176 // Assumes ucontext is valid
 177 intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) {
 178   return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
 179 }
 180 
 181 // Assumes ucontext is valid
 182 intptr_t* os::Solaris::ucontext_get_fp(ucontext_t *uc) {
 183   return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
 184 }
 185 




 186 // For Forte Analyzer AsyncGetCallTrace profiling support - thread
 187 // is currently interrupted by SIGPROF.
 188 //
 189 // The difference between this and os::fetch_frame_from_context() is that
 190 // here we try to skip nested signal frames.
 191 ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread,
 192   ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
 193 
 194   assert(thread != NULL, "just checking");
 195   assert(ret_sp != NULL, "just checking");
 196   assert(ret_fp != NULL, "just checking");
 197 
 198   ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc);
 199   return os::fetch_frame_from_context(luc, ret_sp, ret_fp);
 200 }
 201 
 202 ExtendedPC os::fetch_frame_from_context(void* ucVoid,
 203                     intptr_t** ret_sp, intptr_t** ret_fp) {
 204 
 205   ExtendedPC  epc;


 235 address os::current_stack_pointer() {
 236   return (address)_get_current_sp();
 237 }
 238 
 239 extern "C" intptr_t *_get_current_fp();  // in .il file
 240 
 241 frame os::current_frame() {
 242   intptr_t* fp = _get_current_fp();  // it's inlined so want current fp
 243   frame myframe((intptr_t*)os::current_stack_pointer(),
 244                 (intptr_t*)fp,
 245                 CAST_FROM_FN_PTR(address, os::current_frame));
 246   if (os::is_first_C_frame(&myframe)) {
 247     // stack is not walkable
 248     frame ret; // This will be a null useless frame
 249     return ret;
 250   } else {
 251     return os::get_sender_for_C_frame(&myframe);
 252   }
 253 }
 254 
 255 // This is a simple callback that just fetches a PC for an interrupted thread.
 256 // The thread need not be suspended and the fetched PC is just a hint.
 257 // This one is currently used for profiling the VMThread ONLY!
 258 
 259 // Must be synchronous
 260 void GetThreadPC_Callback::execute(OSThread::InterruptArguments *args) {
 261   Thread*     thread = args->thread();
 262   ucontext_t* uc     = args->ucontext();
 263   intptr_t* sp;
 264 
 265   assert(ProfileVM && thread->is_VM_thread(), "just checking");
 266 
 267   ExtendedPC new_addr((address)uc->uc_mcontext.gregs[REG_PC]);
 268   _addr = new_addr;
 269 }
 270 
 271 static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) {
 272   char lwpstatusfile[PROCFILE_LENGTH];
 273   int lwpfd, err;
 274 
 275   if (err = os::Solaris::thr_getstate(tid, flags, lwp, ss, rs))
 276     return (err);
 277   if (*flags == TRS_LWPID) {
 278     sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(),
 279             *lwp);
 280     if ((lwpfd = open(lwpstatusfile, O_RDONLY)) < 0) {
 281       perror("thr_mutator_status: open lwpstatus");
 282       return (EINVAL);
 283     }
 284     if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) !=
 285         sizeof (lwpstatus_t)) {
 286       perror("thr_mutator_status: read lwpstatus");
 287       (void) close(lwpfd);
 288       return (EINVAL);
 289     }
 290     (void) close(lwpfd);


 402     }
 403   }
 404 
 405   JavaThread* thread = NULL;
 406   VMThread* vmthread = NULL;
 407 
 408   if (os::Solaris::signal_handlers_are_installed) {
 409     if (t != NULL ){
 410       if(t->is_Java_thread()) {
 411         thread = (JavaThread*)t;
 412       }
 413       else if(t->is_VM_thread()){
 414         vmthread = (VMThread *)t;
 415       }
 416     }
 417   }
 418 
 419   guarantee(sig != os::Solaris::SIGinterrupt(), "Can not chain VM interrupt signal, try -XX:+UseAltSigs");
 420 
 421   if (sig == os::Solaris::SIGasync()) {
 422     if(thread){
 423       OSThread::InterruptArguments args(thread, uc);
 424       thread->osthread()->do_interrupt_callbacks_at_interrupt(&args);
 425       return true;
 426     }
 427     else if(vmthread){
 428       OSThread::InterruptArguments args(vmthread, uc);
 429       vmthread->osthread()->do_interrupt_callbacks_at_interrupt(&args);
 430       return true;
 431     } else if (os::Solaris::chained_handler(sig, info, ucVoid)) {
 432       return true;
 433     } else {
 434       // If os::Solaris::SIGasync not chained, and this is a non-vm and
 435       // non-java thread
 436       return true;
 437     }
 438   }
 439 
 440   if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
 441     // can't decode this kind of signal
 442     info = NULL;
 443   } else {
 444     assert(sig == info->si_signo, "bad siginfo");
 445   }
 446 
 447   // decide if this trap can be handled by a stub
 448   address stub = NULL;
 449 


   1 /*
   2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


 166     }
 167   }
 168   return retuc;
 169 }
 170 
 171 // Assumes ucontext is valid
 172 ExtendedPC os::Solaris::ucontext_get_ExtendedPC(ucontext_t *uc) {
 173   return ExtendedPC((address)uc->uc_mcontext.gregs[REG_PC]);
 174 }
 175 
 176 // Assumes ucontext is valid
 177 intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) {
 178   return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
 179 }
 180 
 181 // Assumes ucontext is valid
 182 intptr_t* os::Solaris::ucontext_get_fp(ucontext_t *uc) {
 183   return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
 184 }
 185 
 186 address os::Solaris::ucontext_get_pc(ucontext_t *uc) {
 187   return (address) uc->uc_mcontext.gregs[REG_PC];
 188 }
 189 
 190 // For Forte Analyzer AsyncGetCallTrace profiling support - thread
 191 // is currently interrupted by SIGPROF.
 192 //
 193 // The difference between this and os::fetch_frame_from_context() is that
 194 // here we try to skip nested signal frames.
 195 ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread,
 196   ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
 197 
 198   assert(thread != NULL, "just checking");
 199   assert(ret_sp != NULL, "just checking");
 200   assert(ret_fp != NULL, "just checking");
 201 
 202   ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc);
 203   return os::fetch_frame_from_context(luc, ret_sp, ret_fp);
 204 }
 205 
 206 ExtendedPC os::fetch_frame_from_context(void* ucVoid,
 207                     intptr_t** ret_sp, intptr_t** ret_fp) {
 208 
 209   ExtendedPC  epc;


 239 address os::current_stack_pointer() {
 240   return (address)_get_current_sp();
 241 }
 242 
 243 extern "C" intptr_t *_get_current_fp();  // in .il file
 244 
 245 frame os::current_frame() {
 246   intptr_t* fp = _get_current_fp();  // it's inlined so want current fp
 247   frame myframe((intptr_t*)os::current_stack_pointer(),
 248                 (intptr_t*)fp,
 249                 CAST_FROM_FN_PTR(address, os::current_frame));
 250   if (os::is_first_C_frame(&myframe)) {
 251     // stack is not walkable
 252     frame ret; // This will be a null useless frame
 253     return ret;
 254   } else {
 255     return os::get_sender_for_C_frame(&myframe);
 256   }
 257 }
 258 
















 259 static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) {
 260   char lwpstatusfile[PROCFILE_LENGTH];
 261   int lwpfd, err;
 262 
 263   if (err = os::Solaris::thr_getstate(tid, flags, lwp, ss, rs))
 264     return (err);
 265   if (*flags == TRS_LWPID) {
 266     sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(),
 267             *lwp);
 268     if ((lwpfd = open(lwpstatusfile, O_RDONLY)) < 0) {
 269       perror("thr_mutator_status: open lwpstatus");
 270       return (EINVAL);
 271     }
 272     if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) !=
 273         sizeof (lwpstatus_t)) {
 274       perror("thr_mutator_status: read lwpstatus");
 275       (void) close(lwpfd);
 276       return (EINVAL);
 277     }
 278     (void) close(lwpfd);


 390     }
 391   }
 392 
 393   JavaThread* thread = NULL;
 394   VMThread* vmthread = NULL;
 395 
 396   if (os::Solaris::signal_handlers_are_installed) {
 397     if (t != NULL ){
 398       if(t->is_Java_thread()) {
 399         thread = (JavaThread*)t;
 400       }
 401       else if(t->is_VM_thread()){
 402         vmthread = (VMThread *)t;
 403       }
 404     }
 405   }
 406 
 407   guarantee(sig != os::Solaris::SIGinterrupt(), "Can not chain VM interrupt signal, try -XX:+UseAltSigs");
 408 
 409   if (sig == os::Solaris::SIGasync()) {
 410     if(thread || vmthread){
 411       OSThread::SR_handler(t, uc);






 412       return true;
 413     } else if (os::Solaris::chained_handler(sig, info, ucVoid)) {
 414       return true;
 415     } else {
 416       // If os::Solaris::SIGasync not chained, and this is a non-vm and
 417       // non-java thread
 418       return true;
 419     }
 420   }
 421 
 422   if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
 423     // can't decode this kind of signal
 424     info = NULL;
 425   } else {
 426     assert(sig == info->si_signo, "bad siginfo");
 427   }
 428 
 429   // decide if this trap can be handled by a stub
 430   address stub = NULL;
 431