/*
 * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "hprof.h"

/* This file contains the cpu loop for the option cpu=samples */

/* The cpu_loop thread basically waits for gdata->sample_interval millisecs
 *   then wakes up, and for each running thread it gets their stack trace,
 *   and updates the traces with 'hits'.
 *
 * No threads are suspended or resumed, and the thread sampling is in the
 *   file hprof_tls.c, which manages all active threads. The sampling
 *   technique (what is sampled) is also in hprof_tls.c.
 *
 * No adjustments are made to the pause time or sample interval except
 *   by the user via the interval=n option (default is 10ms).
 *
 * This thread can cause havoc when started prematurely or not terminated
 *   properly, see cpu_sample_init() and cpu_term(), and their calls in hprof_init.c.
 *
 * The listener loop (hprof_listener.c) can dynamically turn on or off the
 *  sampling of all or selected threads.
 *
 */

/* Private functions */

static void JNICALL
cpu_loop_function(jvmtiEnv *jvmti, JNIEnv *env, void *p)
{
    int         loop_trip_counter;
    jboolean    cpu_loop_running;

    loop_trip_counter          = 0;

    rawMonitorEnter(gdata->cpu_loop_lock); {
        gdata->cpu_loop_running = JNI_TRUE;
        cpu_loop_running = gdata->cpu_loop_running;
        /* Notify cpu_sample_init() that we have started */
        rawMonitorNotifyAll(gdata->cpu_loop_lock);
    } rawMonitorExit(gdata->cpu_loop_lock);

    rawMonitorEnter(gdata->cpu_sample_lock); /* Only waits inside loop let go */

    while ( cpu_loop_running ) {

        ++loop_trip_counter;

        LOG3("cpu_loop()", "iteration", loop_trip_counter);

        /* If a dump is in progress, we pause sampling. */
        rawMonitorEnter(gdata->dump_lock); {
            if (gdata->dump_in_process) {
                gdata->pause_cpu_sampling = JNI_TRUE;
            }
        } rawMonitorExit(gdata->dump_lock);

        /* Check to see if we need to pause sampling (listener_loop command) */
        if (gdata->pause_cpu_sampling) {

            /*
             * Pause sampling for now. Reset sample controls if
             * sampling is resumed again.
             */

            rawMonitorWait(gdata->cpu_sample_lock, 0);

            rawMonitorEnter(gdata->cpu_loop_lock); {
                cpu_loop_running = gdata->cpu_loop_running;
            } rawMonitorExit(gdata->cpu_loop_lock);

            /* Continue the while loop, which will terminate if done. */
            continue;
        }

        /* This is the normal short timed wait before getting a sample */
        rawMonitorWait(gdata->cpu_sample_lock,  (jlong)gdata->sample_interval);

        /* Make sure we really want to continue */
        rawMonitorEnter(gdata->cpu_loop_lock); {
            cpu_loop_running = gdata->cpu_loop_running;
        } rawMonitorExit(gdata->cpu_loop_lock);

        /* Break out if we are done */
        if ( !cpu_loop_running ) {
            break;
        }

        /*
         * If a dump request came in after we checked at the top of
         * the while loop, then we catch that fact here. We
         * don't want to perturb the data that is being dumped so
         * we just ignore the data from this sampling loop.
         */
        rawMonitorEnter(gdata->dump_lock); {
            if (gdata->dump_in_process) {
                gdata->pause_cpu_sampling = JNI_TRUE;
            }
        } rawMonitorExit(gdata->dump_lock);

        /* Sample all the threads and update trace costs */
        if ( !gdata->pause_cpu_sampling) {
            tls_sample_all_threads(env);
        }

        /* Check to see if we need to finish */
        rawMonitorEnter(gdata->cpu_loop_lock); {
            cpu_loop_running = gdata->cpu_loop_running;
        } rawMonitorExit(gdata->cpu_loop_lock);

    }
    rawMonitorExit(gdata->cpu_sample_lock);

    rawMonitorEnter(gdata->cpu_loop_lock); {
        /* Notify cpu_sample_term() that we are done. */
        rawMonitorNotifyAll(gdata->cpu_loop_lock);
    } rawMonitorExit(gdata->cpu_loop_lock);

    LOG2("cpu_loop()", "clean termination");
}

/* External functions */

void
cpu_sample_init(JNIEnv *env)
{
    gdata->cpu_sampling  = JNI_TRUE;

    /* Create the raw monitors needed */
    gdata->cpu_loop_lock = createRawMonitor("HPROF cpu loop lock");
    gdata->cpu_sample_lock = createRawMonitor("HPROF cpu sample lock");

    rawMonitorEnter(gdata->cpu_loop_lock); {
        createAgentThread(env, "HPROF cpu sampling thread",
                            &cpu_loop_function);
        /* Wait for cpu_loop_function() to notify us it has started. */
        rawMonitorWait(gdata->cpu_loop_lock, 0);
    } rawMonitorExit(gdata->cpu_loop_lock);
}

void
cpu_sample_off(JNIEnv *env, ObjectIndex object_index)
{
    jint count;

    count = 1;
    if (object_index != 0) {
        tls_set_sample_status(object_index, 0);
        count = tls_sum_sample_status();
    }
    if ( count == 0 ) {
        gdata->pause_cpu_sampling = JNI_TRUE;
    } else {
        gdata->pause_cpu_sampling = JNI_FALSE;
    }
}

void
cpu_sample_on(JNIEnv *env, ObjectIndex object_index)
{
    if ( gdata->cpu_loop_lock == NULL ) {
        cpu_sample_init(env);
    }

    if (object_index == 0) {
        gdata->cpu_sampling             = JNI_TRUE;
        gdata->pause_cpu_sampling       = JNI_FALSE;
    } else {
        jint     count;

        tls_set_sample_status(object_index, 1);
        count = tls_sum_sample_status();
        if ( count > 0 ) {
            gdata->pause_cpu_sampling   = JNI_FALSE;
        }
    }

    /* Notify the CPU sampling thread that sampling is on */
    rawMonitorEnter(gdata->cpu_sample_lock); {
        rawMonitorNotifyAll(gdata->cpu_sample_lock);
    } rawMonitorExit(gdata->cpu_sample_lock);

}

void
cpu_sample_term(JNIEnv *env)
{
    gdata->pause_cpu_sampling   = JNI_FALSE;
    rawMonitorEnter(gdata->cpu_sample_lock); {
        /* Notify the CPU sampling thread to get out of any sampling Wait */
        rawMonitorNotifyAll(gdata->cpu_sample_lock);
    } rawMonitorExit(gdata->cpu_sample_lock);
    rawMonitorEnter(gdata->cpu_loop_lock); {
        if ( gdata->cpu_loop_running ) {
            gdata->cpu_loop_running = JNI_FALSE;
            /* Wait for cpu_loop_function() thread to tell us it completed. */
            rawMonitorWait(gdata->cpu_loop_lock, 0);
        }
    } rawMonitorExit(gdata->cpu_loop_lock);
}
