--- old/src/hotspot/share/runtime/thread.hpp 2018-12-10 01:36:32.633165640 -0500 +++ new/src/hotspot/share/runtime/thread.hpp 2018-12-10 01:36:31.013072969 -0500 @@ -109,6 +109,31 @@ // This means !t->is_Java_thread() iff t is a NonJavaThread, or t is // a partially constructed/destroyed Thread. +/* + Thread execution sequence and actions: + + All threads: + - thread_native_entry // per-OS native entry point + - stack initialization + - other OS-level initialization (signal masks etc) + - handshake with creating thread (if not started suspended) + - this->call_run() // common shared entry point + - shared common initialization + - this->pre_run() // virtual per-thread-type initialization + - this->run() // virtual per-thread-type "main" logic + - shared common tear-down + - this->post_run() // virtual per-thread-type tear-down + - // 'this' no longer referenceable + - OS-level tear-down (minimal) + - final logging + + For JavaThread: + - this->run() // virtual but not normally overridden + - this->thread_main_inner() // extra call level to ensure correct stack calculations + - this->entry_point() // set differently for each kind of JavaThread + +*/ + class Thread: public ThreadShadow { friend class VMStructs; friend class JVMCIVMStructs; @@ -119,7 +144,6 @@ static THREAD_LOCAL_DECL Thread* _thr_current; #endif - private: // Thread local data area available to the GC. The internal // structure and contents of this data area is GC-specific. // Only GC and GC barrier code should access this data area. @@ -141,6 +165,9 @@ // const char* _exception_file; // file information for exception (debugging only) // int _exception_line; // line information for exception (debugging only) protected: + + DEBUG_ONLY(static Thread* _starting_thread;) + // Support for forcing alignment of thread objects for biased locking void* _real_malloc_address; @@ -402,6 +429,21 @@ protected: // To be implemented by children. virtual void run() = 0; + virtual void pre_run() = 0; + virtual void post_run() = 0; // Note: Thread must not be deleted prior to calling this! + +#ifdef ASSERT + enum RunState { + PRE_CALL_RUN, + CALL_RUN, + PRE_RUN, + RUN, + POST_RUN + // POST_CALL_RUN - can't define this one as 'this' may be deleted when we want to set it + }; + RunState _run_state; // for lifecycle checks +#endif + public: // invokes ::run(), with common preparations and cleanups. @@ -780,6 +822,13 @@ class List; static List _the_list; + void add_to_the_list(); + void remove_from_the_list(); + + protected: + virtual void pre_run(); + virtual void post_run(); + public: NonJavaThread(); ~NonJavaThread(); @@ -787,10 +836,19 @@ class Iterator; }; -// Provides iteration over the list of NonJavaThreads. Because list -// management occurs in the NonJavaThread constructor and destructor, -// entries in the list may not be fully constructed instances of a -// derived class. Threads created after an iterator is constructed +// Provides iteration over the list of NonJavaThreads. +// Normal list addition occurs in pre_run(), and removal occurs +// in post_run(), so that only live fully-initialized threads can +// be found in the list. There is a special case during VM startup +// when the BarrierSet has not yet been created, where we add to the +// list during the constructor. That set of initial threads (the main +// thread, plus GC threads typically) is iterated over when the +// BarrierSet is set and each thread is manually updated. The fact those +// threads may not yet have executed is not an issue for that code. +// However it is possible that those threads may still not have executed +// by the time subsequent iterators are created and used - but they are +// known to be fully initialized by their creating thread. +// Threads created after an iterator is constructed // will not be visited by the iterator. The scope of an iterator is a // critical section; there must be no safepoint checks in that scope. class NonJavaThread::Iterator : public StackObj { @@ -828,7 +886,6 @@ ~NamedThread(); // May only be called once per thread. void set_name(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); - void initialize_named_thread(); virtual bool is_Named_thread() const { return true; } virtual char* name() const { return _name == NULL ? (char*)"Unknown Thread" : _name; } JavaThread *processed_thread() { return _processed_thread; } @@ -859,7 +916,7 @@ // A single WatcherThread is used for simulating timer interrupts. class WatcherThread: public NonJavaThread { friend class VMStructs; - public: + protected: virtual void run(); private: @@ -1871,9 +1928,12 @@ inline CompilerThread* as_CompilerThread(); - public: + protected: + virtual void pre_run(); virtual void run(); void thread_main_inner(); + virtual void post_run(); + private: GrowableArray* _array_for_gc;