/*
*
* 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.
*/
#include "hprof.h"
/*
* The tls table items have a key of it's serial number, but may be
* searched via a walk of the table looking for a jthread match.
* This isn't a performance
* issue because the table index should normally be stored in the
* Thread Local Storage for the thread. The table is only searched
* when the jthread is seen before the Thread Local Storage is set
* (e.g. before VM_INIT or the ThreadStart).
* The key is only used when we need to lookup a tls table entry by
* way of it's serial number, which should be unique per thread.
*
* Each active thread that we have seen should have a unique TlsIndex
* which is an index into this table.
*
* For cpu=times, each table entry will have a stack to hold the method
* that have been called, effectively keeping an active stack trace
* for the thread. As each method exits, the statistics for the trace
* associated with the current stack contents is updated.
*
* For cpu=samples, each thread is checked to see if it's runnable,
* and not suspended, and has a stack associated with it, and then
* that stack trace is updated with an additional 'hit'.
*
* This file also contains the dump logic for owned monitors, and for
* threads.
*
*/
/*
* Initial number of stack elements to track per thread. This
* value should be set to a reasonable guess as to the number of
* methods deep a thread calls. This stack doubles in size for each
* reallocation and does not shrink.
*/
typedef struct StackElement {
} StackElement;
typedef struct TlsInfo {
} TlsInfo;
typedef struct SearchData {
} SearchData;
typedef struct IterateInfo {
} IterateInfo;
typedef struct ThreadList {
} ThreadList;
typedef struct SampleData {
} SampleData;
/* Private internal functions. */
static SerialNumber
{
int key_len;
if ( index == 0 ) {
return 0;
}
key_len = 0;
return *pkey;
}
static TlsInfo *
{
}
static void
{
}
}
static void
{
/* Free up any allocated space in this TlsInfo structure */
}
}
}
}
static void
{
}
static void
{
}
static void
{
debug_message( "Tls 0x%08x: SN=%u, sample_status=%d, agent=%d, "
"thread=%p, monitor=0x%08x, "
"tracker_status=%d\n",
*(SerialNumber*)key_ptr,
}
static void
{
}
}
}
static TlsIndex
{
}
static void
{
} else {
}
}
void
{
}
static void
{
if ( !info->agent_thread ) {
}
}
static void
{
int nbytes;
int max_frames;
return;
}
}
}
}
static TraceIndex
{
}
return trace_index;
}
/* Find thread with certain object index */
static void
{
}
}
}
/* Get various lists on known threads */
static void
{
}
}
/* Local reference gets freed by caller */
} else {
/* If we don't use the local reference, delete it now */
}
}
}
static void
{
}
}
static void
{
HPROF_ASSERT(frame_index != 0);
}
static Stack *
{
void *p;
int depth;
int count;
int fcount;
int i;
/* If this method is on the stack, just return */
if ( p != NULL ) {
element = *(StackElement*)p;
return stack;
}
}
for ( i = 0 ; i < depth ; i++ ) {
p = stack_element(stack, i);
element = *(StackElement*)p;
return stack;
}
}
/* It wasn't found, create a new stack */
if ( count <= 0 ) {
}
/* Create a new stack */
(int)sizeof(StackElement));
for ( i = count-1; i >= 0 ; i-- ) {
}
if ( depth > 0 ) {
for ( i = depth-1 ; i >= 0; i-- ) {
}
}
return new_stack;
}
static void
{
void *p;
int depth;
int trace_depth;
int i;
HPROF_ASSERT(frame_index!=0);
if (p == NULL) {
return;
}
element = *(StackElement*)p;
/* The depth of frames we should keep track for reporting */
trace_depth = depth;
} else {
}
/* Create a trace entry */
for (i = 1; i < trace_depth; i++) {
StackElement e;
HPROF_ASSERT(e.frame_index!=0);
}
/* Calculate time spent */
if ( total_time < 0 ) {
total_time = 0;
self_time = 0;
} else {
}
/* Update stats */
if ( p != NULL ) {
} else {
}
}
static void
{
/* A 0 trace at this time means the thread is in unknown territory.
* The trace serial number MUST be a valid serial number, so we use
* the system trace (empty) just so it has a valid trace.
*/
if ( info->last_trace == 0 ) {
} else {
}
}
}
static SerialNumber
{
return gdata->unknown_thread_serial_num;
}
}
static void
{
int i;
if ( ocount > 0 ) {
for ( i = 0 ; i < ocount ; i++ ) {
int t;
char * sig;
(int)sizeof(SerialNumber)+1);
for ( t = 0 ; t < usage.waiter_count ; t++ ) {
waiter_nums[t] =
}
(int)sizeof(SerialNumber)+1);
for ( t = 0 ; t < usage.notify_waiter_count ; t++ ) {
notify_waiter_nums[t] =
}
}
}
}
}
static jlong
monitor_time(void)
{
return mtime;
}
static jlong
method_time(void)
{
return method_time;
}
/* External interfaces */
{
/*LINTED*/
if ( index != 0 ) {
return index;
}
if ( index != 0 ) {
return index;
}
info = empty_info;
info.monitor_index = 0;
(int)sizeof(StackElement));
index = table_create_entry(gdata->tls_table, &thread_serial_num, (int)sizeof(SerialNumber), (void*)&info);
return index;
}
/* Mark a new or existing entry as being an agent thread */
void
{
}
void
tls_init(void)
{
}
void
tls_list(void)
{
"--------------------- TLS Table ------------------------\n");
"----------------------------------------------------------\n");
}
tls_sum_sample_status(void)
{
sample_status_total = 0;
return sample_status_total;
}
void
{
}
{
}
if ( status != 0 ) {
return status;
}
if ( ptrace_index != NULL ) {
}
if ( pthread_serial_num != NULL ) {
}
return status;
}
{
return info->monitor_index;
}
void
{
}
{
}
void
{
}
void
tls_cleanup(void)
{
}
void
{
}
void
{
/* Sample thread stack for last time, do NOT free the entry yet. */
}
}
}
/* Sample ALL threads and update the trace costs */
void
{
int max_count;
int nbytes;
int i;
/* Get buffers to hold thread list and serial number list */
/* Get list of threads and serial numbers */
/* Increment the cost on the traces for these threads */
/* Loop over local refs and free them */
}
}
/* Free up allocated space */
}
void
{
}
void
{
void *p;
HPROF_ASSERT(frame_index != 0);
HPROF_ASSERT(frame_index!=0);
current_time = method_time();
if (p == NULL) {
return;
}
element = *(StackElement*)p;
if ( p == NULL ) {
break;
}
element = *(StackElement*)p;
}
if (p == NULL) {
}
}
void
{
void *p;
HPROF_ASSERT(frame_index != 0);
current_time = method_time();
HPROF_ASSERT(frame_index!=0);
HPROF_ASSERT(p!=NULL);
element = *(StackElement*)p;
if ( p == NULL ) {
break;
}
element = *(StackElement*)p;
}
}
/* For all TLS entries, update the last_trace on all threads */
static void
{
if ( gdata->max_trace_depth == 0 ) {
return;
}
int max_count;
int nbytes;
int i;
/* Get buffers to hold thread list and serial number list */
/* Get list of threads, serial numbers, and info pointers */
/* Get all stack trace index's for all these threadss */
/* Loop over traces and update last_trace's */
}
}
/* Free up all allocated space */
}
void
{
}
void
{
}
void
{
}
{
jlong t;
info->monitor_start_time = 0;
return t;
}
{
} else {
}
return trace_index;
}
void
{
}
{
return info->in_heap_dump;
}
static void
{
info->in_heap_dump = 0;
}
void
tls_clear_in_heap_dump(void)
{
}
{
if ( thread_serial_num == 0 ) {
return 0;
}
(void*)&thread_serial_num, (int)sizeof(SerialNumber));
return index;
}