Path: blob/master/test/hotspot/gtest/gc/g1/test_g1FreeIdSet.cpp
41149 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "gc/g1/g1FreeIdSet.hpp"26#include "memory/allocation.hpp"27#include "runtime/atomic.hpp"28#include "runtime/interfaceSupport.inline.hpp"29#include "runtime/semaphore.inline.hpp"30#include "runtime/thread.hpp"31#include "utilities/debug.hpp"32#include "utilities/globalDefinitions.hpp"33#include "utilities/ostream.hpp"34#include "threadHelper.inline.hpp"35#include "unittest.hpp"3637struct G1FreeIdSet::TestSupport : AllStatic {38static uint next(const G1FreeIdSet& set, uint index) {39assert(index < set._size, "precondition");40return set._next[index];41}4243static uint start(const G1FreeIdSet& set) { return set._start; }44static uint size(const G1FreeIdSet& set) { return set._size; }45static uintx mask(const G1FreeIdSet& set) { return set._head_index_mask; }46static uintx head(const G1FreeIdSet& set) { return Atomic::load(&set._head); }4748static uint head_index(const G1FreeIdSet& set, uintx head) {49return set.head_index(head);50}51};5253typedef G1FreeIdSet::TestSupport TestSupport;5455TEST_VM(G1FreeIdSetTest, initial_state) {56const uint start = 5;57const uint size = 4;58G1FreeIdSet set(start, size);5960ASSERT_EQ(start, TestSupport::start(set));61ASSERT_EQ(size, TestSupport::size(set));62ASSERT_EQ(7u, TestSupport::mask(set));63ASSERT_EQ(0u, TestSupport::head(set));64for (uint i = 0; i < size; ++i) {65ASSERT_EQ(i + 1, TestSupport::next(set, i));66}67}6869TEST_VM(G1FreeIdSetTest, non_blocking_ops) {70const uint start = 5;71const uint size = 3;72G1FreeIdSet set(start, size);7374ASSERT_EQ(5u, set.claim_par_id());75ASSERT_EQ(1u, TestSupport::head_index(set, TestSupport::head(set)));76ASSERT_EQ(6u, set.claim_par_id());77ASSERT_EQ(2u, TestSupport::head_index(set, TestSupport::head(set)));78ASSERT_EQ(7u, set.claim_par_id());79ASSERT_EQ(3u, TestSupport::head_index(set, TestSupport::head(set)));8081set.release_par_id(5u);82set.release_par_id(6u);83ASSERT_EQ(6u, set.claim_par_id());84ASSERT_EQ(5u, set.claim_par_id());85}8687class TestG1FreeIdSetThread : public JavaTestThread {88G1FreeIdSet* _set;89volatile size_t* _total_allocations;90volatile bool* _continue_running;91size_t _allocations;92uint _thread_number;9394public:95TestG1FreeIdSetThread(uint thread_number,96Semaphore* post,97G1FreeIdSet* set,98volatile size_t* total_allocations,99volatile bool* continue_running) :100JavaTestThread(post),101_set(set),102_total_allocations(total_allocations),103_continue_running(continue_running),104_allocations(0),105_thread_number(thread_number)106{}107108virtual void main_run() {109while (Atomic::load_acquire(_continue_running)) {110uint id = _set->claim_par_id();111_set->release_par_id(id);112++_allocations;113ThreadBlockInVM tbiv(this); // Safepoint check.114}115tty->print_cr("%u allocations: " SIZE_FORMAT, _thread_number, _allocations);116Atomic::add(_total_allocations, _allocations);117}118};119120TEST_VM(G1FreeIdSetTest, stress) {121const uint start = 5;122const uint size = 3;123const uint nthreads = size + 1;124const uint milliseconds_to_run = 1000;125126Semaphore post;127volatile size_t total_allocations = 0;128volatile bool continue_running = true;129130G1FreeIdSet set(start, size);131132TestG1FreeIdSetThread* threads[nthreads] = {};133for (uint i = 0; i < nthreads; ++i) {134threads[i] = new TestG1FreeIdSetThread(i,135&post,136&set,137&total_allocations,138&continue_running);139threads[i]->doit();140}141142JavaThread* this_thread = JavaThread::current();143tty->print_cr("Stressing G1FreeIdSet for %u ms", milliseconds_to_run);144{145ThreadInVMfromNative invm(this_thread);146this_thread->sleep(milliseconds_to_run);147}148Atomic::release_store(&continue_running, false);149for (uint i = 0; i < nthreads; ++i) {150ThreadInVMfromNative invm(this_thread);151post.wait_with_safepoint_check(this_thread);152}153tty->print_cr("total allocations: " SIZE_FORMAT, total_allocations);154tty->print_cr("final free list: ");155uint ids[size] = {};156for (uint i = 0; i < size; ++i) {157uint id = set.claim_par_id();158uint index = id - TestSupport::start(set);159ASSERT_LT(index, TestSupport::size(set));160tty->print_cr(" %u: %u", i, index);161}162ASSERT_EQ(size, TestSupport::head_index(set, TestSupport::head(set)));163}164165166