/*
 * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "precompiled.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/threadSMR.hpp"
#include "unittest.hpp"

class ThreadsListHandleTest : public ::testing::Test {
  public:
    // Accessors for the Threads class:
    //
    // Return the protected Thread::_threads_hazard_ptr field:
    static ThreadsList* get_Thread_threads_hazard_ptr(Thread* thr) {
      return thr->get_threads_hazard_ptr();
    }
    // Return the protected Thread::_threads_list_ptr field:
    static SafeThreadsListPtr* get_Thread_threads_list_ptr(Thread* thr) {
      return thr->_threads_list_ptr;
    }
    // Return the protected Thread::_nested_threads_hazard_ptr_cnt field:
    static uint get_Thread_nested_threads_hazard_ptr_cnt(Thread* thr) {
      return thr->nested_threads_hazard_ptr_cnt();
    }

    // Accessors for the ThreadsListHandle class:
    //
    // Return the private ThreadsListHandle::_list_ptr field:
    static SafeThreadsListPtr* get_TLH_list_ptr(ThreadsListHandle* tlh_p) {
      return &tlh_p->_list_ptr;
    }

    // Accessors for the ThreadsList class:
    //
    // Return the private ThreadsList::_nested_handle_cnt field:
    static intx get_TL_nested_handle_cnt(ThreadsList* tl_p) {
      return tl_p->_nested_handle_cnt;
    }

    // Accessors for the SafeThreadsListPtr class:
    //
    // Return the private SafeThreadsListPtr::_thread field:
    static Thread* get_STLP_thread(SafeThreadsListPtr* stlp_p) {
      return stlp_p->_thread;
    }
    // Return the private SafeThreadsListPtr::_has_ref_count field:
    static bool get_STLP_has_ref_count(SafeThreadsListPtr* stlp_p) {
      return stlp_p->_has_ref_count;
    }
    // Return the private SafeThreadsListPtr::_needs_release field:
    static bool get_STLP_needs_release(SafeThreadsListPtr* stlp_p) {
      return stlp_p->_needs_release;
    }
};

TEST_VM(ThreadsListHandle, sanity) {
  bool saved_flag_val = EnableThreadSMRStatistics;
  EnableThreadSMRStatistics = true;  // enable Thread::_nested_threads_hazard_ptr_cnt

  Thread* thr = Thread::current();

  // Test case: no ThreadsListHandle
  //

  // Verify the current thread refers to no ThreadsListHandle:
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), (ThreadsList*)nullptr)
      << "thr->_threads_hazard_ptr must be null";
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), (SafeThreadsListPtr*) nullptr)
      << "thr->_threads_list_ptr must be null";
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
      << "thr->_nested_threads_hazard_ptr_cnt must be 0";

  // Test case: single ThreadsListHandle, no recursion
  //
  {
    ThreadsListHandle tlh1;
    SafeThreadsListPtr* list_ptr1 = ThreadsListHandleTest::get_TLH_list_ptr(&tlh1);

    // Verify the current thread refers to tlh1:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh1.list())
        << "thr->_threads_hazard_ptr must match tlh1.list()";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr1)
        << "thr->_threads_list_ptr must match list_ptr1";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
        << "thr->_nested_threads_hazard_ptr_cnt must be 0";

    // Verify tlh1 has the right field values:
    EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
        << "list_ptr1->previous() must be null";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
        << "list_ptr1->_thread must match current thread";
    EXPECT_EQ(list_ptr1->list(), tlh1.list())
        << "list_ptr1->list() must match tlh1.list()";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), false)
        << "list_ptr1->_has_ref_count must be false";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
        << "list_ptr1->_needs_release must be true";

    // Verify tlh1 ThreadsList has the right field values:
    EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)0)
        << "list_ptr1->list()->_nested_handle_cnt must be 0";
  } // destroy tlh1

  // Test case: after first ThreadsListHandle (tlh1) has been destroyed
  //

  // Verify the current thread refers to no ThreadsListHandle:
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), (ThreadsList*)nullptr)
      << "thr->_threads_hazard_ptr must match be null";
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), (SafeThreadsListPtr*) nullptr)
      << "thr->_threads_list_ptr must be null";
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
      << "thr->_nested_threads_hazard_ptr_cnt must be 0";

  // Test case: first ThreadsListHandle to prepare for nesting
  //
  {
    ThreadsListHandle tlh1;
    SafeThreadsListPtr* list_ptr1 = ThreadsListHandleTest::get_TLH_list_ptr(&tlh1);

    // Verify the current thread refers to tlh1:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh1.list())
        << "thr->_threads_hazard_ptr must match tlh1.list()";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr1)
        << "thr->_threads_list_ptr must match list_ptr1";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
        << "thr->_nested_threads_hazard_ptr_cnt must be 0";

    // Verify tlh1 has the right field values:
    EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
        << "list_ptr1->previous() must be null";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
        << "list_ptr1->_thread must match current thread";
    EXPECT_EQ(list_ptr1->list(), tlh1.list())
        << "list_ptr1->list() must match tlh1.list()";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), false)
        << "list_ptr1->_has_ref_count must be false";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
        << "list_ptr1->_needs_release must be true";

    // Verify tlh1 ThreadsList has the right field values:
    EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)0)
        << "list_ptr1->list()->_nested_handle_cnt must be 0";

    // Test case: first nested ThreadsListHandle
    //
    {
      ThreadsListHandle tlh2;
      SafeThreadsListPtr* list_ptr2 = ThreadsListHandleTest::get_TLH_list_ptr(&tlh2);

      // Verify the current thread refers to tlh2:
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh2.list())
          << "thr->_threads_hazard_ptr must match tlh2.list()";
    // Disable unstable check of ThreadsListHandle.sanity_vm ThreadList values,
    // until the root cause of test failure(JDK-8315141) has been fixed
    //   EXPECT_EQ(tlh1.list(), tlh2.list())
    //       << "tlh1.list() must match tlh2.list()";
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr2)
          << "thr->_threads_list_ptr must match list_ptr2";
      EXPECT_NE(list_ptr1, list_ptr2)
          << "list_ptr1 must not match list_ptr2";
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)1)
          << "thr->_nested_threads_hazard_ptr_cnt must be 1";

      // Verify tlh2 has the right field values:
      EXPECT_EQ(list_ptr2->previous(), list_ptr1)
          << "list_ptr2->previous() must be list_ptr1";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr2), thr)
          << "list_ptr2->_thread must match current thread";
      EXPECT_EQ(list_ptr2->list(), tlh2.list())
          << "list_ptr2->list() must match tlh2.list()";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr2), false)
          << "list_ptr2->_has_ref_count must be false";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr2), true)
          << "list_ptr2->_needs_release must be true";

      // Verify tlh1 has the right field values:
      EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
          << "list_ptr1->previous() must be null";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
          << "list_ptr1->_thread must match current thread";
      EXPECT_EQ(list_ptr1->list(), tlh1.list())
          << "list_ptr1->list() must match tlh1.list()";
      // When tlh2 was created, tlh1's _has_ref_count was set to true and
      // tlh1's list->_nested_handle_cnt was incremented.
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), true)
          << "list_ptr1->_has_ref_count must be true";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
          << "list_ptr1->_needs_release must be true";

      // Verify tlh1 ThreadsList has the right field values:
      EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)1)
          << "list_ptr1->list()->_nested_handle_cnt must be 1";
    } // destroy tlh2

    // Test case: after first nested ThreadsListHandle (tlh2) has been destroyed

    // Verify the current thread's hazard ptr is null:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), (ThreadsList*)nullptr)
        << "thr->_threads_hazard_ptr must be null";
    // Verify the current thread's threads list ptr refers to tlh1:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr1)
        << "thr->_threads_list_ptr must match list_ptr1";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
        << "thr->_nested_threads_hazard_ptr_cnt must be 0";

    // Verify tlh1 has the right field values:
    EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
        << "list_ptr1->previous() must be null";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
        << "list_ptr1->_thread must match current thread";
    EXPECT_EQ(list_ptr1->list(), tlh1.list())
        << "list_ptr1->list() must match tlh1.list()";
    // When tlh2 was created, tlh1's _has_ref_count was set to true and
    // tlh1's list->_nested_handle_cnt was incremented.
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), true)
        << "list_ptr1->_has_ref_count must be true";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
        << "list_ptr1->_needs_release must be true";

      // Verify tlh1 ThreadsList has the right field values:
      EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)1)
          << "list_ptr1->list()->_nested_handle_cnt must be 1";
  } // destroy tlh1

  // Test case: after first ThreadsListHandle to prepare for nesting has been destroyed
  //

  // Verify the current thread refers to no ThreadsListHandle:
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), (ThreadsList*)nullptr)
      << "thr->_threads_hazard_ptr must match be null";
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), (SafeThreadsListPtr*) nullptr)
      << "thr->_threads_list_ptr must be null";
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
      << "thr->_nested_threads_hazard_ptr_cnt must be 0";

  // Test case: first ThreadsListHandle to prepare for double nesting
  //
  {
    ThreadsListHandle tlh1;
    SafeThreadsListPtr* list_ptr1 = ThreadsListHandleTest::get_TLH_list_ptr(&tlh1);

    // Verify the current thread refers to tlh1:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh1.list())
        << "thr->_threads_hazard_ptr must match tlh1.list()";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr1)
        << "thr->_threads_list_ptr must match list_ptr1";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
        << "thr->_nested_threads_hazard_ptr_cnt must be 0";

    // Verify tlh1 has the right field values:
    EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
        << "list_ptr1->previous() must be null";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
        << "list_ptr1->_thread must match current thread";
    EXPECT_EQ(list_ptr1->list(), tlh1.list())
        << "list_ptr1->list() must match tlh1.list()";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), false)
        << "list_ptr1->_has_ref_count must be false";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
        << "list_ptr1->_needs_release must be true";

    // Verify tlh1 ThreadsList has the right field values:
    EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)0)
        << "list_ptr1->list()->_nested_handle_cnt must be 0";

    // Test case: first nested ThreadsListHandle
    //
    {
      ThreadsListHandle tlh2;
      SafeThreadsListPtr* list_ptr2 = ThreadsListHandleTest::get_TLH_list_ptr(&tlh2);

      // Verify the current thread refers to tlh2:
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh2.list())
          << "thr->_threads_hazard_ptr must match tlh2.list()";
    // Disable unstable check of ThreadsListHandle.sanity_vm ThreadList values,
    // until the root cause of test failure(JDK-8315141) has been fixed
    //   EXPECT_EQ(tlh1.list(), tlh2.list())
    //       << "tlh1.list() must match tlh2.list()";
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr2)
          << "thr->_threads_list_ptr must match list_ptr2";
      EXPECT_NE(list_ptr1, list_ptr2)
          << "list_ptr1 must not match list_ptr2";
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)1)
          << "thr->_nested_threads_hazard_ptr_cnt must be 1";

      // Verify tlh2 has the right field values:
      EXPECT_EQ(list_ptr2->previous(), list_ptr1)
          << "list_ptr2->previous() must be list_ptr1";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr2), thr)
          << "list_ptr2->_thread must match current thread";
      EXPECT_EQ(list_ptr2->list(), tlh2.list())
          << "list_ptr2->list() must match tlh2.list()";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr2), false)
          << "list_ptr2->_has_ref_count must be false";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr2), true)
          << "list_ptr2->_needs_release must be true";

      // Verify tlh1 has the right field values:
      EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
          << "list_ptr1->previous() must be null";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
          << "list_ptr1->_thread must match current thread";
      EXPECT_EQ(list_ptr1->list(), tlh1.list())
          << "list_ptr1->list() must match tlh1.list()";
      // When tlh2 was created, tlh1's _has_ref_count was set to true and
      // tlh1's list->_nested_handle_cnt was incremented.
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), true)
          << "list_ptr1->_has_ref_count must be true";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
          << "list_ptr1->_needs_release must be true";

      // Verify tlh1 ThreadsList has the right field values:
      EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)1)
          << "list_ptr1->list()->_nested_handle_cnt must be 1";

      // Test case: double nested ThreadsListHandle
      //
      {
        ThreadsListHandle tlh3;
        SafeThreadsListPtr* list_ptr3 = ThreadsListHandleTest::get_TLH_list_ptr(&tlh3);

        // Verify the current thread refers to tlh3:
        EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh3.list())
            << "thr->_threads_hazard_ptr must match tlh3.list()";
        // Disable unstable check of ThreadsListHandle.sanity_vm ThreadList values,
        // until the root cause of test failure(JDK-8315141) has been fixed
        // EXPECT_EQ(tlh1.list(), tlh3.list())
        //     << "tlh1.list() must match tlh3.list()";
        EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr3)
            << "thr->_threads_list_ptr must match list_ptr3";
        EXPECT_NE(list_ptr1, list_ptr3)
            << "list_ptr1 must not match list_ptr3";
        EXPECT_NE(list_ptr2, list_ptr3)
            << "list_ptr. must not match list_ptr3";
        EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)2)
            << "thr->_nested_threads_hazard_ptr_cnt must be 2";

        // Verify tlh3 has the right field values:
        EXPECT_EQ(list_ptr3->previous(), list_ptr2)
            << "list_ptr3->previous() must be list_ptr2";
        EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr3), thr)
            << "list_ptr3->_thread must match current thread";
        EXPECT_EQ(list_ptr3->list(), tlh3.list())
            << "list_ptr3->list() must match tlh3.list()";
        EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr3), false)
            << "list_ptr3->_has_ref_count must be false";
        EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr3), true)
            << "list_ptr3->_needs_release must be true";

        // Verify tlh2 has the right field values:
        EXPECT_EQ(list_ptr2->previous(), list_ptr1)
            << "list_ptr2->previous() must be list_ptr1";
        EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr2), thr)
            << "list_ptr2->_thread must match current thread";
        EXPECT_EQ(list_ptr2->list(), tlh2.list())
            << "list_ptr2->list() must match tlh2.list()";
        // When tlh3 was created, tlh2's _has_ref_count was set to true and
        // tlh2's list->_nested_handle_cnt was incremented.
        EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr2), true)
            << "list_ptr2->_has_ref_count must be true";
        EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr2), true)
            << "list_ptr2->_needs_release must be true";

        // Verify tlh1 has the right field values:
        EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
            << "list_ptr1->previous() must be null";
        EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
            << "list_ptr1->_thread must match current thread";
        EXPECT_EQ(list_ptr1->list(), tlh1.list())
            << "list_ptr1->list() must match tlh1.list()";
        // When tlh2 was created, tlh1's _has_ref_count was set to true and
        // tlh1's list->_nested_handle_cnt was incremented.
        EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), true)
            << "list_ptr1->_has_ref_count must be true";
        EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
            << "list_ptr1->_needs_release must be true";

        // Verify tlh1 ThreadsList has the right field values:
        EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)2)
            << "list_ptr1->list()->_nested_handle_cnt must be 2";
      } // destroy tlh3

      // Test case: after double nested ThreadsListHandle (tlh3) has been destroyed

      // Verify the current thread's hazard ptr is null:
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), (ThreadsList*)nullptr)
          << "thr->_threads_hazard_ptr must be null";
      // Verify the current thread's threads list ptr refers to tlh2:
      EXPECT_EQ(tlh1.list(), tlh2.list())
          << "tlh1.list() must match tlh2.list()";
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr2)
          << "thr->_threads_list_ptr must match list_ptr2";
      EXPECT_NE(list_ptr1, list_ptr2)
          << "list_ptr1 must not match list_ptr2";
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)1)
          << "thr->_nested_threads_hazard_ptr_cnt must be 1";

      // Verify tlh2 has the right field values:
      EXPECT_EQ(list_ptr2->previous(), list_ptr1)
          << "list_ptr2->previous() must be list_ptr1";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr2), thr)
          << "list_ptr2->_thread must match current thread";
      EXPECT_EQ(list_ptr2->list(), tlh2.list())
          << "list_ptr2->list() must match tlh2.list()";
      // When tlh3 was created, tlh2's _has_ref_count was set to true and
      // tlh2's list->_nested_handle_cnt was incremented.
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr2), true)
          << "list_ptr2->_has_ref_count must be true";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr2), true)
          << "list_ptr2->_needs_release must be true";

      // Verify tlh1 has the right field values:
      EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
          << "list_ptr1->previous() must be null";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
          << "list_ptr1->_thread must match current thread";
      EXPECT_EQ(list_ptr1->list(), tlh1.list())
          << "list_ptr1->list() must match tlh1.list()";
      // When tlh2 was created, tlh1's _has_ref_count was set to true and
      // tlh1's list->_nested_handle_cnt was incremented.
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), true)
          << "list_ptr1->_has_ref_count must be true";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
          << "list_ptr1->_needs_release must be true";

      // Verify tlh1 ThreadsList has the right field values:
      EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)2)
          << "list_ptr1->list()->_nested_handle_cnt must be 2";
    } // destroy tlh2

    // Test case: after first nested ThreadsListHandle (tlh2) has been destroyed

    // Verify the current thread's hazard ptr is null:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), (ThreadsList*)nullptr)
        << "thr->_threads_hazard_ptr must be null";
    // Verify the current thread's threads list ptr refers to tlh1:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr1)
        << "thr->_threads_list_ptr must match list_ptr1";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
        << "thr->_nested_threads_hazard_ptr_cnt must be 0";

    // Verify tlh1 has the right field values:
    EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
        << "list_ptr1->previous() must be null";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
        << "list_ptr1->_thread must match current thread";
    EXPECT_EQ(list_ptr1->list(), tlh1.list())
        << "list_ptr1->list() must match tlh1.list()";
    // When tlh2 was created, tlh1's _has_ref_count was set to true and
    // tlh1's list->_nested_handle_cnt was incremented.
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), true)
        << "list_ptr1->_has_ref_count must be true";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
        << "list_ptr1->_needs_release must be true";

    // Verify tlh1 ThreadsList has the right field values:
    EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)1)
        << "list_ptr1->list()->_nested_handle_cnt must be 1";
  } // destroy tlh1

  // Test case: after first ThreadsListHandle to prepare for double nesting has been destroyed
  //

  // Verify the current thread refers to no ThreadsListHandle:
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), (ThreadsList*)nullptr)
      << "thr->_threads_hazard_ptr must match be null";
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), (SafeThreadsListPtr*) nullptr)
      << "thr->_threads_list_ptr must be null";
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
      << "thr->_nested_threads_hazard_ptr_cnt must be 0";

  // Test case: first ThreadsListHandle to prepare for back-to-back nesting
  //
  {
    ThreadsListHandle tlh1;
    SafeThreadsListPtr* list_ptr1 = ThreadsListHandleTest::get_TLH_list_ptr(&tlh1);

    // Verify the current thread refers to tlh1:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh1.list())
        << "thr->_threads_hazard_ptr must match tlh1.list()";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr1)
        << "thr->_threads_list_ptr must match list_ptr1";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
        << "thr->_nested_threads_hazard_ptr_cnt must be 0";

    // Verify tlh1 has the right field values:
    EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
        << "list_ptr1->previous() must be null";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
        << "list_ptr1->_thread must match current thread";
    EXPECT_EQ(list_ptr1->list(), tlh1.list())
        << "list_ptr1->list() must match tlh1.list()";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), false)
        << "list_ptr1->_has_ref_count must be false";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
        << "list_ptr1->_needs_release must be true";

    // Verify tlh1 ThreadsList has the right field values:
    EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)0)
        << "list_ptr1->list()->_nested_handle_cnt must be 0";

    // Test case: first back-to-back nested ThreadsListHandle
    //
    {
      ThreadsListHandle tlh2a;
      SafeThreadsListPtr* list_ptr2a = ThreadsListHandleTest::get_TLH_list_ptr(&tlh2a);

      // Verify the current thread refers to tlh2a:
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh2a.list())
          << "thr->_threads_hazard_ptr must match tlh2a.list()";
    // Disable unstable check of ThreadsListHandle.sanity_vm ThreadList values,
    // until the root cause of test failure(JDK-8315141) has been fixed
    //   EXPECT_EQ(tlh1.list(), tlh2a.list())
    //       << "tlh1.list() must match tlh2a.list()";
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr2a)
          << "thr->_threads_list_ptr must match list_ptr2a";
      EXPECT_NE(list_ptr1, list_ptr2a)
          << "list_ptr1 must not match list_ptr2a";
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)1)
          << "thr->_nested_threads_hazard_ptr_cnt must be 1";

      // Verify tlh2a has the right field values:
      EXPECT_EQ(list_ptr2a->previous(), list_ptr1)
          << "list_ptr2a->previous() must be list_ptr1";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr2a), thr)
          << "list_ptr2a->_thread must match current thread";
      EXPECT_EQ(list_ptr2a->list(), tlh2a.list())
          << "list_ptr2a->list() must match tlh2a.list()";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr2a), false)
          << "list_ptr2a->_has_ref_count must be false";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr2a), true)
          << "list_ptr2a->_needs_release must be true";

      // Verify tlh1 has the right field values:
      EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
          << "list_ptr1->previous() must be null";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
          << "list_ptr1->_thread must match current thread";
      EXPECT_EQ(list_ptr1->list(), tlh1.list())
          << "list_ptr1->list() must match tlh1.list()";
      // When tlh2a was created, tlh1's _has_ref_count was set to true and
      // tlh1's list->_nested_handle_cnt was incremented.
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), true)
          << "list_ptr1->_has_ref_count must be true";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
          << "list_ptr1->_needs_release must be true";

      // Verify tlh1 ThreadsList has the right field values:
      EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)1)
          << "list_ptr1->list()->_nested_handle_cnt must be 1";
    } // destroy tlh2a

    // Test case: after first back-to-back nested ThreadsListHandle (tlh2a) has been destroyed

    // Verify the current thread's hazard ptr is null:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), (ThreadsList*)nullptr)
        << "thr->_threads_hazard_ptr must be null";
    // Verify the current thread's threads list ptr refers to tlh1:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr1)
        << "thr->_threads_list_ptr must match list_ptr1";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
        << "thr->_nested_threads_hazard_ptr_cnt must be 0";

    // Verify tlh1 has the right field values:
    EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
        << "list_ptr1->previous() must be null";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
        << "list_ptr1->_thread must match current thread";
    EXPECT_EQ(list_ptr1->list(), tlh1.list())
        << "list_ptr1->list() must match tlh1.list()";
    // When tlh2a was created, tlh1's _has_ref_count was set to true and
    // tlh1's list->_nested_handle_cnt was incremented.
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), true)
        << "list_ptr1->_has_ref_count must be true";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
        << "list_ptr1->_needs_release must be true";

    // Verify tlh1 ThreadsList has the right field values:
    EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)1)
        << "list_ptr1->list()->_nested_handle_cnt must be 1";

    // Test case: second back-to-back nested ThreadsListHandle
    //
    {
      ThreadsListHandle tlh2b;
      SafeThreadsListPtr* list_ptr2b = ThreadsListHandleTest::get_TLH_list_ptr(&tlh2b);

      // Verify the current thread refers to tlh2b:
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), tlh2b.list())
          << "thr->_threads_hazard_ptr must match tlh2b.list()";
    // Disable unstable check of ThreadsListHandle.sanity_vm ThreadList values,
    // until the root cause of test failure(JDK-8315141) has been fixed
    //   EXPECT_EQ(tlh1.list(), tlh2b.list())
    //       << "tlh1.list() must match tlh2b.list()";
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr2b)
          << "thr->_threads_list_ptr must match list_ptr2b";
      EXPECT_NE(list_ptr1, list_ptr2b)
          << "list_ptr1 must not match list_ptr2b";
      EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)1)
          << "thr->_nested_threads_hazard_ptr_cnt must be 1";

      // Verify tlh2b has the right field values:
      EXPECT_EQ(list_ptr2b->previous(), list_ptr1)
          << "list_ptr2b->previous() must be list_ptr1";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr2b), thr)
          << "list_ptr2b->_thread must match current thread";
      EXPECT_EQ(list_ptr2b->list(), tlh2b.list())
          << "list_ptr2b->list() must match tlh2b.list()";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr2b), false)
          << "list_ptr2b->_has_ref_count must be false";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr2b), true)
          << "list_ptr2b->_needs_release must be true";

      // Verify tlh1 has the right field values:
      EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
          << "list_ptr1->previous() must be null";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
          << "list_ptr1->_thread must match current thread";
      EXPECT_EQ(list_ptr1->list(), tlh1.list())
          << "list_ptr1->list() must match tlh1.list()";
      // When tlh2a was created, tlh1's _has_ref_count was set to true and
      // tlh1's list->_nested_handle_cnt was incremented.
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), true)
          << "list_ptr1->_has_ref_count must be true";
      EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
          << "list_ptr1->_needs_release must be true";

      // Verify tlh1 ThreadsList has the right field values:
      EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)1)
          << "list_ptr1->list()->_nested_handle_cnt must be 1";
    } // destroy tlh2b

    // Test case: after second back-to-back nested ThreadsListHandle (tlh2b) has been destroyed

    // Verify the current thread's hazard ptr is null:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), (ThreadsList*)nullptr)
        << "thr->_threads_hazard_ptr must be null";
    // Verify the current thread's threads list ptr refers to tlh1:
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), list_ptr1)
        << "thr->_threads_list_ptr must match list_ptr1";
    EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
        << "thr->_nested_threads_hazard_ptr_cnt must be 0";

    // Verify tlh1 has the right field values:
    EXPECT_EQ(list_ptr1->previous(), (SafeThreadsListPtr*)nullptr)
        << "list_ptr1->previous() must be null";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_thread(list_ptr1), thr)
        << "list_ptr1->_thread must match current thread";
    EXPECT_EQ(list_ptr1->list(), tlh1.list())
        << "list_ptr1->list() must match tlh1.list()";
    // When tlh2a was created, tlh1's _has_ref_count was set to true and
    // tlh1's list->_nested_handle_cnt was incremented.
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_has_ref_count(list_ptr1), true)
        << "list_ptr1->_has_ref_count must be true";
    EXPECT_EQ(ThreadsListHandleTest::get_STLP_needs_release(list_ptr1), true)
        << "list_ptr1->_needs_release must be true";

    // Verify tlh1 ThreadsList has the right field values:
    EXPECT_EQ(ThreadsListHandleTest::get_TL_nested_handle_cnt(list_ptr1->list()), (intx)1)
        << "list_ptr1->list()->_nested_handle_cnt must be 1";
  } // destroy tlh1

  // Test case: after first ThreadsListHandle to prepare for back-to-back nesting has been destroyed
  //

  // Verify the current thread refers to no ThreadsListHandle:
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_hazard_ptr(thr), (ThreadsList*)nullptr)
      << "thr->_threads_hazard_ptr must match be null";
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_threads_list_ptr(thr), (SafeThreadsListPtr*) nullptr)
      << "thr->_threads_list_ptr must be null";
  EXPECT_EQ(ThreadsListHandleTest::get_Thread_nested_threads_hazard_ptr_cnt(thr), (uint)0)
      << "thr->_nested_threads_hazard_ptr_cnt must be 0";

  EnableThreadSMRStatistics = saved_flag_val;
}