Path: blob/master/test/hotspot/gtest/gc/g1/test_g1ServiceThread.cpp
41152 views
/*1* Copyright (c) 2020, 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/g1ServiceThread.hpp"26#include "runtime/interfaceSupport.inline.hpp"27#include "runtime/os.hpp"28#include "utilities/autoRestore.hpp"29#include "unittest.hpp"3031class CheckTask : public G1ServiceTask {32int _execution_count;33bool _reschedule;3435public:36CheckTask(const char* name) :37G1ServiceTask(name),38_execution_count(0),39_reschedule(true) { }40virtual void execute() {41_execution_count++;42if (_reschedule) {43schedule(100);44}45}4647int execution_count() { return _execution_count;}48void set_reschedule(bool reschedule) { _reschedule = reschedule; }49};5051static void stop_service_thread(G1ServiceThread* thread) {52ThreadInVMfromNative tvn(JavaThread::current());53thread->stop();54}5556// Test that a task that is added during runtime gets run.57TEST_VM(G1ServiceThread, test_add) {58// Create thread and let it start.59G1ServiceThread* st = new G1ServiceThread();60os::naked_short_sleep(500);6162CheckTask ct("AddAndRun");63st->register_task(&ct);6465// Give CheckTask time to run.66os::naked_short_sleep(500);67stop_service_thread(st);6869ASSERT_GT(ct.execution_count(), 0);70}7172// Test that a task that is added while the service thread is73// waiting gets run in a timely manner.74TEST_VM(G1ServiceThread, test_add_while_waiting) {75// Make sure default tasks use long intervals so that the service thread76// is doing a long wait for the next execution.77AutoModifyRestore<uintx> f1(G1PeriodicGCInterval, 100000);78AutoModifyRestore<uintx> f2(G1ConcRefinementServiceIntervalMillis, 100000);7980// Create thread and let it start.81G1ServiceThread* st = new G1ServiceThread();82os::naked_short_sleep(500);8384// Register a new task that should run right away.85CheckTask ct("AddWhileWaiting");86st->register_task(&ct);8788// Give CheckTask time to run.89os::naked_short_sleep(500);90stop_service_thread(st);9192ASSERT_GT(ct.execution_count(), 0);93}9495// Test that a task with negative timeout is not rescheduled.96TEST_VM(G1ServiceThread, test_add_run_once) {97// Create thread and let it start.98G1ServiceThread* st = new G1ServiceThread();99os::naked_short_sleep(500);100101// Set reschedule to false to only run once.102CheckTask ct("AddRunOnce");103ct.set_reschedule(false);104st->register_task(&ct);105106// Give CheckTask time to run.107os::naked_short_sleep(500);108stop_service_thread(st);109110// Should be exactly 1 since negative timeout should111// prevent rescheduling.112ASSERT_EQ(ct.execution_count(), 1);113}114115class TestTask : public G1ServiceTask {116jlong _delay_ms;117public:118TestTask(jlong delay) :119G1ServiceTask("TestTask"),120_delay_ms(delay) {121set_time(delay);122}123virtual void execute() {}124void update_time(jlong now, int multiplier) {125set_time(now + (_delay_ms * multiplier));126}127};128129TEST_VM(G1ServiceTaskQueue, add_ordered) {130G1ServiceTaskQueue queue;131132int num_test_tasks = 5;133for (int i = 1; i <= num_test_tasks; i++) {134// Create tasks with different timeout.135TestTask* task = new TestTask(100 * i);136queue.add_ordered(task);137}138139// Now fake a run-loop, that reschedules the tasks using a140// random multiplier.141for (jlong now = 0; now < 1000000; now++) {142// Random multiplier is at least 1 to ensure progress.143int multiplier = 1 + os::random() % 10;144while (queue.peek()->time() < now) {145TestTask* task = (TestTask*) queue.pop();146// Update delay multiplier.147task->execute();148task->update_time(now, multiplier);149// All additions will verify that the queue is sorted.150queue.add_ordered(task);151}152}153154while (!queue.is_empty()) {155G1ServiceTask* task = queue.pop();156delete task;157}158}159160#ifdef ASSERT161TEST_VM_ASSERT_MSG(G1ServiceTaskQueue, pop_empty,162".*Should never try to verify empty queue") {163G1ServiceTaskQueue queue;164queue.pop();165}166167TEST_VM_ASSERT_MSG(G1ServiceTaskQueue, peek_empty,168".*Should never try to verify empty queue") {169G1ServiceTaskQueue queue;170queue.peek();171}172173TEST_VM_ASSERT_MSG(G1ServiceTaskQueue, set_time_in_queue,174".*Not allowed to update time while in queue") {175G1ServiceTaskQueue queue;176TestTask a(100);177queue.add_ordered(&a);178// Not allowed to update time while in queue.179a.update_time(500, 1);180}181182#endif183184185