Is it possible to stop a specific application thread?

David Holmes david.holmes at oracle.com
Mon Nov 11 18:06:37 PST 2013


On 12/11/2013 11:50 AM, Keith Chapman wrote:
> On Mon, Nov 11, 2013 at 8:25 PM, David Holmes <david.holmes at oracle.com
> <mailto:david.holmes at oracle.com>> wrote:
>     On 12/11/2013 11:16 AM, Keith Chapman wrote:
>         On Mon, Nov 11, 2013 at 7:26 PM, David Holmes
>         <david.holmes at oracle.com <mailto:david.holmes at oracle.com>
>         <mailto:david.holmes at oracle.com>>> wrote:
>              On 12/11/2013 6:29 AM, Keith Chapman wrote:
>                  I'm playing around with some research ideas on hotspot.
>
>                  One of my runtime services of the VM needs to stop a
>         specific
>                  application
>                  thread (I have a handle to the pthread of the application
>                  thread). How can
>                  the VM stop such a thread? Is there any mechanism in
>         place to do
>                  this?
>
>
>              There is no general purpose mechanism currently in place.
>
>
>         Thats a bummer, having such a mechanism would have been useful for
>         numerous VM services like biased locking revocation, concurrent GC.
>
>
>     For which safepoints are generally used so a per-thread safepoint
>     mechanism is what you are looking for.
>
>
>
>              You could use the deprecated and inherently dangerous
>         Thread.suspend
>              mechanism (either directly or via the JVMTI suspension
>         interface).
>
>              Or if you are more adventurous with your VM hacking you could
>              introduce a per-thread safepoint operation to cause it to stop.
>
>
>         I actually thought about that and explored the way safepoints are
>         implemented. The place that I had most trouble was getting threads
>         running compiled code to stop. The way it currently works is by
>         allocating a polling page (at startup) and drilling in that
>         address into
>         the compiled code. Hence i I am to do it per thread I would have
>         to make
>         a call to the runtime to get the address of the polling page for
>         that
>         particular thread. I presume this would be too expensive (Making
>         a VM
>         call at the end of each method and through some loop iterations).
>
>         Is there any insight you could offer on how this could be done?
>
>
>     Two basic options I can think of:
>
>     1. Use a single shared page and have other threads simply ignore the
>     safepoint request. This might incur some overhead as not-wanted
>     threads could hit this multiple times.
>
>     2. Use a per-thread page accessed via the current thread. There
>     would be a little overhead for the indirection but the compiler
>     knows how to access the current JavaThread object. No need for
>     runtime calls that I can see.
>
>
> This seems to be the most viable option. Cold you point me to an example
> in the codebase where something similar is done (Accessing the a field
> via the current thread)  in the compiler. I have already figured out how
> to do this for the other cases, its just the compiled code (Accessing a
> thread local safepoint page) that I haven't figured out yet.

I'm not a compiler person but the intrinsic for Thread.currentThread 
does just that: accesses the JavaThread field of the current thread that 
points to the java.lang.Thread object:

 From share/vm/c1/c1_LIRGenerator.cpp

// Example: Thread.currentThread()
void LIRGenerator::do_currentThread(Intrinsic* x) {
   assert(x->number_of_arguments() == 0, "wrong type");
   LIR_Opr reg = rlock_result(x);
   __ move_wide(new LIR_Address(getThreadPointer(), 
in_bytes(JavaThread::threadObj_offset()), T_OBJECT), reg);
}

 From ./share/vm/opto/library_call.cpp

//--------------------------generate_current_thread--------------------
Node* LibraryCallKit::generate_current_thread(Node* &tls_output) {
   ciKlass*    thread_klass = env()->Thread_klass();
   const Type* thread_type  = 
TypeOopPtr::make_from_klass(thread_klass)->cast_to_ptr_type(TypePtr::NotNull);
   Node* thread = _gvn.transform(new (C) ThreadLocalNode());
   Node* p = basic_plus_adr(top()/*!oop*/, thread, 
in_bytes(JavaThread::threadObj_offset()));
   Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT);
   tls_output = thread;
   return threadObj;
}

But please don't ask me how these work :)

PS. Be very careful changing what would normally be global safepoint ops 
into per-thread ones. There are a lot of safepoint assumptions strewn 
throughout the VM code.

David
-----

> Thanks,
> Keith.
>
>
>     Good luck.
>
>     David
>
>
>         Thanks,
>         Keith.
>
>              Or you could hack in a special "magic exception" type the
>         processing
>              of which simply blocks the thread until "resumed" somehow
>         (not sure
>              how ??). Or ...
>
>              Cheers,
>              David
>
>                  Thanks,
>                  Keith.
>
>
>
>
>         --
>
>         Keith Chapman
>         blog: http://www.keith-chapman.org
>
>
>
>
> --
>
> Keith Chapman
> blog: http://www.keith-chapman.org


More information about the hotspot-dev mailing list