Question about thread initialization
David Holmes
david.holmes at oracle.com
Fri Oct 12 23:42:13 UTC 2018
Hi Thomas,
On 13/10/2018 3:56 AM, Thomas Stüfe wrote:
> Hi David,
>
> thank you for your brain cycles.
>
> On Fri, Oct 12, 2018 at 12:39 PM David Holmes <david.holmes at oracle.com> wrote:
>>
>> Hi Thomas,
>>
>> On 12/10/2018 6:18 PM, Thomas Stüfe wrote:
>>> Hi all,
>>>
>>> a small question.
>>>
>>> JVM_StartThread calls new JavaThread()
>>> JavaThread::JavaThread() calls os::create_thread()
>>> os::create_thread() starts the new thread and waits for the
>>> handshake, then returns
>>>
>>> Back in JVM_StartThread, we call JavaThread::prepare(), which adds the
>>> new thread to the Threads list. By that time, the new thread is
>>> already running, but how far it has gotten is unknown.
>>
>> Right - though the new thread can't enter run() until after it has been
>> prepared and "started". There are two parts to the handshake:
>>
>> Parent thread New Thread
>> start new Thread
>> wait for new thread
>> signal parent
>> wait for parent
>> prepare new thread
>> "start" new thread
>> signal new thread
>> run()
>>
>
> Ah, I see. The new thread is taken off the leash only at the end of
> JVM_StartThread(), when Thread::start() is called and the final part
> of the handshake is completed.
>
>>> The new thread's stack dimensions are set from within Thread::run()
>>> (for some reason, every child class does this on its own?) by calling
>>> Thread::record_stack_base_and_size(). So, after the handshake with its
>>> parent thread. Why?
>>
>> Good question. Undoubtedly historical. :)
>>
>>> This means we have a little race: in the Threads list there may be
>>> threads which have been just created and Thread::run() did not yet get
>>> around to set the stack size. In tests I stumbled over this, very
>>> rarely, when iterating Threads to check the stack sizes.
>>
>> Hmmm. Threads that are still _thread_new should really be invisible
>> until more fully initialized. How exactly were you iterating the
>> threads? This might be an oversight in the related APIs.
>>
>
> This was because of a little unrelated test I wrote to accumulate the
> combined thread stack sizes. They did not add up and I was confused.
>
> I am now less confused:
>
> In JVM_StartThread():
>
> {
> grab thread list lock
> new JavaThread()
> - calls pthread_create, new thread starts and waits for
> handshake. stack base, size still NULL,0.
> JavaThread::prepare()
> - thread gets added to Threads list
> a } // relinquish threads lock
> ...
> ...
> Threads::start()
> - signal new thread to run
> b - new thread completes handshake, calls Thread::run(), and all
> implementations pretty much immediately set the stackbase/size.
>
> Between (a) and (b) another thread could grab the Threads lock,
> iterate the threads and would see the new thread with uninitialized
> base/size.
>
> To prove this I did a little test right there, in JVM_StartThread, after (a):
>
> + {
> + MutexLocker mu(Threads_lock);
> + MyThreadClosure tc;
> + Threads::threads_do(&tc);
> + }
>
> the thread closure just prints the stack dimensions of the thrad. Sure
> enough, the new thread still has NULL/0 for stack base/size. In fact,
> Thread::stack_base() asserts because of this.
>
> So, could not another thread happen to do the same in this little time interval?
There _should_ be some rules about how thread closures gather their
target threads based on the thread state. Part of that should (now that
I think about it) filter out threads that are still "new" - but whether
they do or not is a different matter. This may well just be an oversight.
>>> Is there any reason why we could not just call
>>> record_stack_base_and_size() before calling Thread::run(), right at
>>> the start of the native entry function (thread_native_entry in the
>>> case of Linux)?
>>
>> Have you tried it? :)
>>
>> I can't immediately see why this can't happen in the
>> thread_native_entry. It's possible there was once a dependency with
>> something in thread preparation etc, but that's just speculation on my part.
>>
>
> Funny, I wanted to test it and then it occurred to me that we do this
> all along already on AIX: At the entrace of thread_native_entry I set
> stack base and size (that was even my own code from the initial AIX
> port). Unfortunately I have lost the history for that change and do
> not know anymore why I did this.
>
> Since we never had problems on AIX I guess this is okay for other
> platforms too - as long os::current_stack_base() /
> current_stack_size() have no side effects and do not rely on anything
> but OS functionality.
Okay so are you going to propose making such a change?
Cheers,
David
>
> Cheers, Thomas
>
>>> Am I missing something here?
>>
>> I guess we will find out :)
>>
>> Cheers,
>> David
>>
>>> Thanks,
>>>
>>> Thomas
>>>
More information about the hotspot-runtime-dev
mailing list