/*
 * Copyright 2003-2005 Sun Microsystems, Inc.  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 Sun Microsystems 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);
}
