/*
*
* 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
*
* - 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* Trace table. */
/*
* A trace is an optional thread serial number plus N frames.
*
* The thread serial number is added to the key only if the user asks for
* threads in traces, which will cause many more traces to be created.
* Without it all threads share the traces.
*
* This is a variable length Key, depending on the number of frames.
* The frames are FrameIndex values into the frame table.
*
* It is important that the thread serial number is used and not the
* TlsIndex, threads come and go, and TlsIndex values are re-used
* but the thread serial number is unique per thread.
*
* The cpu=times and cpu=samples dumps rely heavily on traces, the trace
* dump preceeds the cpu information and uses the trace information.
* Depending on the cpu= request, different sorts are applied to the
* traces that are dumped.
*
*/
#include "hprof.h"
typedef struct TraceKey {
} TraceKey;
typedef struct TraceInfo {
} TraceInfo;
typedef struct IterateInfo {
int count;
} IterateInfo;
/* Private internal functions. */
static TraceKey*
{
void * pkey;
int key_len;
}
static TraceInfo *
{
return info;
}
static TraceIndex
{
int key_len;
if ( n_frames > 1 ) {
}
if ( n_frames > 0 ) {
}
if ( new_one ) {
}
return index;
}
static void
{
int i;
HPROF_ASSERT(key_len>0);
debug_message( "Trace 0x%08x: SN=%u, threadSN=%u, n_frames=%d, frames=(",
}
debug_message( "), traceSN=%u, num_hits=%d, self_cost=(%d,%d), "
"total_cost=(%d,%d), status=0x%08x\n",
}
static void
{
HPROF_ASSERT(key_len>0);
info->total_cost = 0;
}
/* Get the names for a frame in order to dump it. */
static void
{
HPROF_ASSERT(frame_index!=0);
}
*plineno = -1;
}
*pcnum = 0;
}
}
}
}
}
/* Write out a stack trace. */
static void
{
int i;
char *phase_str;
struct FrameNames {
char * sname;
char * csig;
char * mname;
int lineno;
} *finfo;
return;
}
if ( n_frames > 0 ) {
/* Write frames, but save information for trace later */
for (i = 0; i < n_frames; i++) {
char *msig;
if (frame_get_status(frame_index) == 0) {
}
}
}
/* Find phase string */
} else {
}
for (i = 0; i < n_frames; i++) {
}
}
}
/* Output a specific list of traces. */
static void
{
int i;
for ( i = 0; i < count ; i++ ) {
void * pkey;
int key_len;
}
}
static void
{
HPROF_ASSERT(key_len>0);
}
static int
{
/*LINTED*/
}
static int
{
}
/* External interfaces. */
void
trace_init(void)
{
}
void
trace_list(void)
{
"--------------------- Trace Table ------------------------\n");
"----------------------------------------------------------\n");
}
void
trace_cleanup(void)
{
}
{
if ( index == 0 ) {
return 0;
}
return info->serial_num;
}
void
{
}
trace_find_or_create(SerialNumber thread_serial_num, jint n_frames, FrameIndex *frames, jvmtiFrameInfo *jframes_buffer)
{
}
/* We may need to ask for more frames than the user asked for */
static int
{
int extra_frames;
extra_frames = 0;
/* This is only needed if we are doing BCI */
/* Account for Java and native Tracker methods */
extra_frames = 2;
if ( skip_init ) {
/* Also allow for ignoring the java.lang.Object.<init> method */
extra_frames += 1;
}
}
return depth + extra_frames;
}
/* Fill in FrameIndex array from jvmtiFrameInfo array, return n_frames */
static int
{
int n_frames;
/* If real_depth is 0, just return 0 */
if ( real_depth == 0 ) {
return 0;
}
/* Assume top frame index is 0 for now */
topframe = 0;
/* Possible top frames belong to the hprof Tracker class, remove them */
while ( ( ( frame_count - topframe ) > 0 ) &&
) {
topframe++;
}
}
/* Adjust count to match depth request */
}
/* The actual frame count we will process */
if ( n_frames > 0 ) {
int i;
for (i = 0; i < n_frames; i++) {
}
}
return n_frames;
}
/* Get the trace for the supplied thread */
{
int real_depth;
int n_frames;
/* We may need to ask for more frames than the user asked for */
/* Get the stack trace for this one thread */
frame_count = 0;
if ( real_depth > 0 ) {
}
/* Create FrameIndex's */
/* Lookup or create new TraceIndex */
return index;
}
/* Get traces for all threads in list (traces[i]==0 if thread not running) */
void
{
int nbytes;
int real_depth;
int i;
HPROF_ASSERT(thread_count > 0);
/* Find out what the phase is for all these traces */
/* We may need to ask for more frames than the user asked for */
/* Get the stack traces for all the threads */
/* Allocate a frames_buffer and trace key buffer */
/* Loop over the stack traces we have for these 'thread_count' threads */
for ( i = 0 ; i < thread_count ; i++ ) {
int n_frames;
/* Assume 0 at first (no trace) */
traces[i] = 0;
/* If thread has frames, is runnable, and isn't suspended, we care */
if ( always_care ||
( stack_info[i].frame_count > 0
) {
/* Create FrameIndex's */
/* Lookup or create new TraceIndex */
}
}
/* Make sure we free the space */
}
/* Increment the trace costs for all the threads (for cpu=samples) */
void
{
int nbytes;
HPROF_ASSERT(thread_count > 0);
HPROF_ASSERT(depth >= 0);
if ( depth == 0 ) {
return;
}
/* Allocate a traces array */
/* Get all the current traces for these threads */
/* Increment the cpu=samples cost on these traces */
int i;
for ( i = 0 ; i < thread_count ; i++ ) {
/* Each trace gets a hit and an increment of it's total cost */
if ( traces[i] != 0 ) {
}
}
/* Free up the memory allocated */
}
void
{
}
/* output info on the cost associated with traces */
void
{
double accum;
int n_entries;
iterate.grand_total_cost = 0;
/* sort all the traces according to the cost */
n_items = 0;
for (i = 0; i < trace_table_size; i++) {
double percent;
/* As soon as a trace with zero hits is seen, we need no others */
break;
}
break;
}
n_items++;
}
/* Now write all trace we might refer to. */
accum = 0;
for (i = 0; i < n_items; i++) {
double percent;
char *csig;
char *mname;
char *msig;
}
}
}
/* output the trace cost in old prof format */
void
{
int i, trace_table_size;
int n_entries;
iterate.grand_total_cost = 0;
/* sort all the traces according to the number of hits */
for (i = 0; i < trace_table_size; i++) {
int num_frames;
int num_hits;
char *csig_callee;
char *mname_callee;
char *msig_callee;
char *csig_caller;
char *mname_caller;
char *msig_caller;
if (num_hits == 0) {
break;
}
csig_callee = NULL;
mname_callee = NULL;
msig_callee = NULL;
csig_caller = NULL;
mname_caller = NULL;
msig_caller = NULL;
if (num_frames >= 1) {
&csig_callee, NULL,
}
if (num_frames > 1) {
&csig_caller, NULL,
}
(int)info->total_cost);
}
}
void
trace_clear_cost(void)
{
}