Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8212173

Thread._stack_base/_stack_size initialized too late for new threads

    XMLWordPrintable

Details

    • b18

    Backports

      Description

        Thread._stack_base/_stack_size are initialized in the Thread child classes' implementation of Thread.run(), typically right at the beginning. Still this is too late since by that time the new Thread has already been added to the Threads list.

        Code iterating that list by e.g. Threads::do_threads() may see the Thread object without stack information. Also, accessing Thread::stack_size() will assert in that case.

        Prior discussion: http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2018-October/030516.html

        --

        Details:

        During initialization of newborn (created by VM) threads, things happen in the following sequence (on Linux and BSD):


        (parent thread)
        JVM_StartThread
        calls new JavaThread
        calls os::create_thread()
        - calls pthread_create.
        - Child thread starts.
        - parent thread waits on Child thread coming up (Handshake part 1)
        - child waits. parent continues.
        calls JavaThread::prepare()
        calls Threads::add and adds newly created thread to thread list (A)

        calls Thread::start(Thread)
        calls os::start_thread()
        - wakes up child thread
        - child thread continues to run. Child thread calls <ChildThreadClass>::run(). That function has to be overwritten by every child class.
        - Inside <ChildThreadClass>::run(), Thread::record_stack_base_and_size() is called which sets Thread::stack_base and Thread::stack_stize. (B)

        On Solaris, Windows and AIX the situations is a bit different:


        (parent thread)
        JVM_StartThread
        calls new JavaThread
        calls os::create_thread()
        - calls pthread_create.
        - Child thread does *not* start but is suspended for now.
        - parent continues.
        calls JavaThread::prepare()
        calls Threads::add and adds newly created thread to thread list (A)

        calls Thread::start(Thread)
        calls os::start_thread()
        - unsuspends the child thread. Child thread starts running for the first time.
        - Child thread calls <ChildThreadClass>::run(). That function has to be overwritten by every child class.
        - Inside <ChildThreadClass>::run(), Thread::record_stack_base_and_size() is called which sets Thread::stack_base and Thread::stack_stize. (B)


        Between (A) and (B) the newly created thread is visible when iterating the Threads list, and has no stack dimensions set.


        -------------

        Solution: move the initialization of Thread::stack_base/stack_size up, before the Thread is added to the Threads list. This is possible on Linux+BSD, but it is not possible on Windows+Solaris+AIX.

        We only can get the stack dimensions from within the newly created thread. On Linux+BSD, we have a time window where the newly created child thread runs and is not yet visible from the outside (before the handshake with the parent thread). This time window does not exist on Windows+Solaris+AIX. Even if we move the initialization of Thread::stack_base/stack_size up to the start of thread_native_entry, this is still too late since by that time the thread is already visible via Threads list.




        Attachments

          Issue Links

            Activity

              People

                stuefe Thomas Stuefe
                stuefe Thomas Stuefe
                Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved: