Creating a JavaThread and its java.lang.Thread oop

Tom Rodriguez Thomas.Rodriguez at Sun.COM
Tue Nov 6 09:56:17 PST 2007


I'd recommend creating your thread pool at the absolute end of create_vm. 
Otherwise you are do your work during bootstrap which is a very tricky period in 
the VM and you're just asking for trouble.

One big clue is way down at the bottom.

 > (/home/peterh/workspace/openjdk/hotspot/src/share/vm/runtime/handles.cpp:40),
 > pid=18280, tid=3084282768
 >     #  Error: assert(thread == Thread::current(),"sanity check")
 >

This means that the code appears to be confused about which thread it's running 
in.  If you look at allocate_threadObj it expects to be called from within the 
newly created thread, not from within the creating thread, which means that this 
== THREAD, but the way you are calling it this != THREAD.  Handles are always 
specific to the currently running thread so if you pass in an explicit argument 
it must be equal to the current thread.  If you replace the use of this in the 
Handle constructors with THREAD then it will work properly when called from a 
different thread or the same thread.

By the way, this:

         if(TracePoolGen) FlagSetting fs(TraceThreadEvents, true);

doesn't do what you think.  FlagSetting is temporary so it's reset when the 
destructor runs.  If you want to permanently set it, 
FLAG_SET_DEFAULT(TraceThreadEvents, true) is the recommended idiom.

tom

Peter Helfer wrote:
> Hi all
> 
> I am still trying to get my thread pool, so far without real luck... ok, 
> so here is how I'm trying to achieve it:
> 
> - I'm preparing my own subsystem from runtime/init.cpp, which creates 
> some runtime-code etc..
> - When starting up (runtime/thread.cpp: Threads::create_vm(..) ), I'm 
> starting the thread pool
>   after everything is done, shortly before vm_init_completed is set, so 
> I can use Universe::...
> - I've been seeing a lot of different assertion errors, so I'm now 
> completely exhausted :-(
> 
> [create_vm(..)]:
>  initialize_class(vmSymbolHandles::java_lang_Compiler(), CHECK_0);
>  reset_vm_info_property(CHECK_0);
>  threadpool_init2(); // HERE COMES THE THREAD POOL
>  quicken_jni_functions();
>  set_init_completed();
>  HS_DTRACE_PROBE(hotspot, vm__init__end);
>  Management::record_vm_init_completed();
> 
> Now in this function I'm calling the constructor to it which calls the 
> initialize() function:
> 
> void Threadpool::initialize(){ // is called indirectly by 
> threadpool_init2();
>         assert(Threadpool::get_SpinWaitEntry() != 0, "the spin wait 
> entry is missing!");
>         Threadpool::might_be_available = 0; // static peek variable
>         Threadpool::threadID = 1; //static var
> 
>         // MutexLocker ml(ThreadPool); -
>         /* THIS CAUSED SOME LOCK INVERSION..
>          * it is skipped, but still safe, as all clients to this pool 
> first ask might_be_available > 0, which
>          * isnt the case. But it would be nicer..
>          */
> 
>         if(TracePoolGen) FlagSetting fs(TraceThreadEvents, true);
>         for(int i = 0; i < _size; i++){
>                 _pool[i] = 
> createThread((ThreadFunction)Speculation::get_SpinWaitEntry());
>                 Thread::start(_pool[i]); // and start it immediately
>         }
>         Threadpool::might_be_available = _size;
> }
> 
> This now calls the real creator:
> 
> JavaThread* Threadpool::createThread(ThreadFunction entrypoint){
>         EXCEPTION_MARK; // creates a ExceptionMark and THREAD
>         JavaThread* result_thread = NULL;
>         {
>                 result_thread = new JavaThread(entrypoint); //size = 0
>                 if (result_thread->osthread() != NULL) {
>                         oop group = Universe::main_thread_group();
>                         bool attach_failed = false;
>                         {
>                                 HandleMark hm(THREAD);
>                                 Handle thread_group(THREAD, group);
>                                 
> result_thread->allocate_threadObj(thread_group, "fromThreadPool", false, 
> THREAD);
>                                 if (HAS_PENDING_EXCEPTION) {
>                                         CLEAR_PENDING_EXCEPTION;
>                                         // cleanup outside the handle mark.
>                                         attach_failed = true;
>                                 }
>                         }
>                         if(attach_failed){
>                                 delete result_thread;
>                                 result_thread = NULL;
>                         }
>                 } else {
>                      delete result_thread;
>                      result_thread = NULL;
>                 }
>         }
>         return result_thread;
> }
> 
> 
> Now I've seen different errors with different configurations...
>  - inverted locks
>  - SIGSEV (that was before splitting the init into 2 parts...)
>  - looping forever with TracePoolGen/TraceThreadEvents set...
>     creating thread 0x8084800
>     creating thread 0x8086400
>     creating thread 0x8088000
>     creating thread 0x8089c00
>     creating thread 0x808b800
>     creating thread 0x808d400
>     creating thread 0x808f000
>     creating thread 0x8090c00
>     creating thread 0x8092800
>     creating thread 0x8094800
>     Thread::set priority 0x0806d400 [4d6c] main (prio: 5)
>     creating thread 0x80d4800
>     Thread::set priority 0x080d4800 [4d83] Reference Handler (prio: 10)
>     Thread::start 0x080d4800 [4d83] Reference Handler (prio: 10)
>     creating thread 0x80d6000
>     .. and here nothing happens anymore
>  - and the current one:
>     Internal Error 

> 
> Could somebody maybe point me in the right direction, or even hand out a 
> correct piece of code ? It seems that I am missing important parts, but 
> I have no clue what to look for.. and before I smash my monitor, I 
> rather give in and try to continue at a different end of my project..
> 
> Thanks & Regards,
> 
> Peter
> 
> 
> 
> 



More information about the hotspot-runtime-dev mailing list