/*
 * Copyright (c) 2015, 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.
 */

/*
 * @test TestGreyReclaimedHumongousObjects.java
 * @bug 8069367
 * @requires vm.gc == "G1" | vm.gc == "null"
 * @summary Test handling of marked but unscanned reclaimed humongous objects.
 * @key gc
 * @run main/othervm -XX:+UseG1GC -Xss32m -Xmx128m -XX:G1HeapRegionSize=1m
 *      -XX:+UnlockExperimentalVMOptions
 *          -XX:+G1EagerReclaimHumongousObjects
 *          -XX:+G1EagerReclaimHumongousObjectsWithStaleRefs
 *      TestGreyReclaimedHumongousObjects 1048576 90
 */

// This test spawns a bunch of threads, each of them rapidly
// allocating large objects and storing them into a circular buffer
// associated with the thread.  The circular buffer results in these
// objects becoming dead in fairly short order.
//
// The situation we're trying to provoke is
//
// (1) A humongous object H is marked and added to the mark stack.
//
// (2) An evacuation pause determines H is no longer live, and
// reclaims it.  This occurs before concurrent marking has gotten
// around to processing the mark stack entry for H.
//
// (3) Concurrent marking processes the mark stack entry for H.  The
// bug is that it would attempt to scan the now dead object.
//
// Unfortunately, this test is *very* sensitive to configuration.
// Among the parameters that affect whether / how often we'll get into
// the desired situation within a reasonable amount of time are:
//
// - THREAD_COUNT: The number of allocating threads.
//
// - OLD_COUNT: The number of objects each thread keeps.
//
// - MAX_MEMORY: The maximum heap size.
//
// - G1HeapRegionSize
//
// - The size of the objects being allocated.
//
// The parameter values specified here:
//
// - THREAD_COUNT = 12
// - OLD_COUNT == 4
// - MAX_MEMORY == 128m
// - G1HeapRegionSize = 1m
// - Object size = 1048576 (2 regions after header overhead and roundup)
//
// seems to work well at provoking the desired state fairly quickly.
// Even relatively small perturbations may change that.  The key
// factors seem to be keeping the heap mostly full of live objects but
// having them become dead fairly quickly.

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import sun.management.ManagementFactoryHelper;
import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.management.VMOption;

public class TestGreyReclaimedHumongousObjects {

    static class NamedThreadFactory implements ThreadFactory {
       private int threadNum = 0;

       @Override
       public Thread newThread(Runnable r) {
         return new Thread(r, THREAD_NAME + (threadNum++));
       }
    }

    static class Runner extends Thread {
        private final Date startDate = new Date();
        private final int obj_size;
        private final Object[] old_garbage;
        private int old_index = 0;

        public Runner(int obj_size) {
            this.obj_size = obj_size;
            old_garbage = new Object[OLD_COUNT];
        }

        private void allocate_garbage() {
            byte[] garbage = new byte[obj_size];
            old_garbage[Math.abs(++old_index % OLD_COUNT)] = garbage;
        }

        @Override
        public void run() {
            try {
                while (!isInterrupted()) {
                    allocate_garbage();
                    Thread.sleep(0); // Yield, to ensure interruptable.
                }
            } catch (InterruptedException e) {
                System.out.println("Aborted after "
                                   + (new Date().getTime() - startDate.getTime())
                                   + " ms");
                interrupt();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();

        System.out.println("Max memory= " + MAX_MEMORY + " bytes");

        int obj_size = 0;
        long seconds_to_run = 0;
        if (args.length != 2) {
            throw new RuntimeException("Object size argument must be supplied");
        } else {
            obj_size = Integer.parseInt(args[0]);
            seconds_to_run = Integer.parseInt(args[1]);
        }
        System.out.println("Objects size= " + obj_size + " bytes");
        System.out.println("Seconds to run=" + seconds_to_run);

        int region_size =
            Integer.parseInt(diagnostic.getVMOption("G1HeapRegionSize").getValue());
        if (obj_size < (region_size / 2)) {
            throw new RuntimeException("Object size " + obj_size +
                                       " is not humongous with region size " + region_size);
        }

        ExecutorService executor =
            Executors.newFixedThreadPool(THREAD_COUNT, new NamedThreadFactory());
        System.out.println("Starting " + THREAD_COUNT + " threads");

        for (int i = 0; i < THREAD_COUNT; i++) {
            executor.execute(new Runner(obj_size));
        }

        Thread.sleep(seconds_to_run * 1000);
        executor.shutdownNow();

        if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
            System.err.println("Thread pool did not terminate after 10 seconds after shutdown");
        }
    }

    private static final long MAX_MEMORY = Runtime.getRuntime().maxMemory();
    private static final int OLD_COUNT = 4;
    private static final int THREAD_COUNT = 12;
    private static final String THREAD_NAME = "TestGreyRH-";
}

