2012-02-05 11:35:58 -05:00
|
|
|
/****************************************************************
|
|
|
|
* *
|
2012-03-24 14:06:46 -04:00
|
|
|
* Copyright 2011, 2012 Fidelity Information Services, Inc *
|
2012-02-05 11:35:58 -05:00
|
|
|
* *
|
|
|
|
* This source code contains the intellectual property *
|
|
|
|
* of its copyright holder(s), and is made available *
|
|
|
|
* under a license. If you do not know the terms of *
|
|
|
|
* the license, please stop and do not read further. *
|
|
|
|
* *
|
|
|
|
****************************************************************/
|
|
|
|
|
|
|
|
#include "mdef.h"
|
|
|
|
#include "mprof.h"
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define MPROF_CHUNK_SIZE 2 * SIZEOF(mprof_stack_frame) /* for debug only store 2 frames per chunk */
|
|
|
|
#else
|
|
|
|
#define MPROF_CHUNK_SIZE 8096 /* in pro make each chunk about 8K */
|
|
|
|
#endif
|
|
|
|
#define MPROF_STACK_ALLOC_CNT (MPROF_CHUNK_SIZE / SIZEOF(mprof_stack_frame)) /* size of allocation chunk in number of frames */
|
|
|
|
|
2012-03-24 14:06:46 -04:00
|
|
|
GBLREF int process_exiting;
|
|
|
|
|
2012-02-05 11:35:58 -05:00
|
|
|
/* Preallocate space for MPROF_STACK_ALLOC_CNT elements of the stack. */
|
|
|
|
void mprof_stack_init(void)
|
|
|
|
{
|
|
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
|
|
if (NULL == TREF(mprof_stack_next_frame))
|
|
|
|
TREF(mprof_stack_next_frame) = (mprof_stack_frame *)malloc(SIZEOF(mprof_stack_frame) * MPROF_STACK_ALLOC_CNT);
|
|
|
|
TREF(mprof_stack_curr_frame) = NULL;
|
|
|
|
TREF(mprof_chunk_avail_size) = MPROF_STACK_ALLOC_CNT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Push a new frame onto the MPROF stack and return a reference to it. */
|
|
|
|
mprof_stack_frame *mprof_stack_push(void)
|
|
|
|
{
|
|
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
|
|
if (0 == TREF(mprof_chunk_avail_size))
|
|
|
|
{
|
|
|
|
TREF(mprof_stack_next_frame) = (mprof_stack_frame *)malloc(SIZEOF(mprof_stack_frame) * MPROF_STACK_ALLOC_CNT);
|
|
|
|
TREF(mprof_chunk_avail_size) = MPROF_STACK_ALLOC_CNT;
|
|
|
|
}
|
|
|
|
(TREF(mprof_stack_next_frame))->prev = TREF(mprof_stack_curr_frame);
|
|
|
|
TREF(mprof_stack_curr_frame) = TREF(mprof_stack_next_frame);
|
|
|
|
(TREF(mprof_stack_next_frame))++;
|
|
|
|
(TREF(mprof_chunk_avail_size))--;
|
|
|
|
return TREF(mprof_stack_curr_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Pop the top frame off the MPROF stack. */
|
|
|
|
mprof_stack_frame *mprof_stack_pop(void)
|
|
|
|
{
|
|
|
|
mprof_stack_frame *last_frame;
|
|
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
|
|
last_frame = (TREF(mprof_stack_curr_frame))->prev;
|
|
|
|
if (NULL == TREF(mprof_stack_curr_frame))
|
|
|
|
assert(FALSE);
|
|
|
|
/* only let mprof_chunk_avail_size become 0 if there have been previously allocated chunks */
|
|
|
|
if (((MPROF_STACK_ALLOC_CNT - 1) == TREF(mprof_chunk_avail_size)) && (NULL != last_frame))
|
|
|
|
{
|
|
|
|
free(TREF(mprof_stack_curr_frame));
|
|
|
|
TREF(mprof_chunk_avail_size) = -1;
|
|
|
|
}
|
|
|
|
TREF(mprof_stack_next_frame) = TREF(mprof_stack_curr_frame);
|
|
|
|
TREF(mprof_stack_curr_frame) = last_frame;
|
|
|
|
(TREF(mprof_chunk_avail_size))++;
|
|
|
|
return TREF(mprof_stack_curr_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the memory allocated for MPROF stack. */
|
|
|
|
void mprof_stack_free(void)
|
|
|
|
{
|
|
|
|
mprof_stack_frame *chunk_start, *prev_chunk_start;
|
|
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
2012-03-24 14:06:46 -04:00
|
|
|
if (process_exiting) /* no point trying to clean after ourselves if we are exiting */
|
|
|
|
return;
|
2012-02-05 11:35:58 -05:00
|
|
|
/* there are no elements on the stack */
|
|
|
|
if (MPROF_STACK_ALLOC_CNT == TREF(mprof_chunk_avail_size))
|
|
|
|
{
|
|
|
|
free(TREF(mprof_stack_next_frame));
|
|
|
|
TREF(mprof_stack_next_frame) = TREF(mprof_stack_curr_frame) = NULL;
|
|
|
|
TREF(mprof_chunk_avail_size) = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
chunk_start = TREF(mprof_stack_curr_frame) - (MPROF_STACK_ALLOC_CNT - TREF(mprof_chunk_avail_size) - 1);
|
|
|
|
while (NULL != chunk_start)
|
|
|
|
{
|
|
|
|
if (NULL != chunk_start->prev)
|
|
|
|
prev_chunk_start = chunk_start->prev - (MPROF_STACK_ALLOC_CNT - 1);
|
|
|
|
else
|
|
|
|
prev_chunk_start = NULL;
|
|
|
|
free(chunk_start);
|
|
|
|
chunk_start = prev_chunk_start;
|
|
|
|
}
|
|
|
|
TREF(mprof_stack_next_frame) = TREF(mprof_stack_curr_frame) = NULL;
|
|
|
|
TREF(mprof_chunk_avail_size) = 0;
|
|
|
|
return;
|
|
|
|
}
|