/* ----------------------------------------------------------------------------- * * (c) The GHC Team, 2009 * * Macros for profiling operations in STG code * * Do not #include this file directly: #include "Rts.h" instead. * * To understand the structure of the RTS headers, see the wiki: * http://hackage.haskell.org/trac/ghc/wiki/Commentary/SourceTree/Includes * * ---------------------------------------------------------------------------*/ #ifndef RTS_PROF_CCS_H #define RTS_PROF_CCS_H // Returns non-zero if the RTS is a profiling version int rts_isProfiled(void); /* ----------------------------------------------------------------------------- * Data Structures * ---------------------------------------------------------------------------*/ /* * Note [struct alignment] * NB. be careful to avoid unwanted padding between fields, by * putting the 8-byte fields on an 8-byte boundary. Padding can * vary between C compilers, and we don't take into account any * possible padding when generating CCS and CC decls in the code * generator (compiler/codeGen/CgProf.hs). */ typedef struct CostCentre_ { StgInt ccID; // Unique Id, allocated by the RTS char * label; char * module; char * srcloc; // used for accumulating costs at the end of the run... StgWord64 mem_alloc; // align 8 (Note [struct alignment]) StgWord time_ticks; StgInt is_caf; // non-zero for a CAF cost centre struct CostCentre_ *link; } CostCentre; typedef struct CostCentreStack_ { StgInt ccsID; // unique ID, allocated by the RTS CostCentre *cc; // Cost centre at the top of the stack struct CostCentreStack_ *prevStack; // parent struct IndexTable_ *indexTable; // children struct CostCentreStack_ *root; // root of stack StgWord depth; // number of items in the stack StgWord64 scc_count; // Count of times this CCS is entered // align 8 (Note [struct alignment]) StgWord selected; // is this CCS shown in the heap // profile? (zero if excluded via -hc // -hm etc.) StgWord time_ticks; // number of time ticks accumulated by // this CCS StgWord64 mem_alloc; // mem allocated by this CCS // align 8 (Note [struct alignment]) StgWord64 inherited_alloc; // sum of mem_alloc over all children // (calculated at the end) // align 8 (Note [struct alignment]) StgWord inherited_ticks; // sum of time_ticks over all children // (calculated at the end) } CostCentreStack; /* ----------------------------------------------------------------------------- * The rest is PROFILING only... * ---------------------------------------------------------------------------*/ #if defined(PROFILING) /* ----------------------------------------------------------------------------- * Constants * ---------------------------------------------------------------------------*/ #define EMPTY_STACK NULL #define EMPTY_TABLE NULL /* Constants used to set is_caf flag on CostCentres */ #define CC_IS_CAF 'c' /* 'c' => *is* a CAF cc */ #define CC_NOT_CAF 0 /* ----------------------------------------------------------------------------- * Data Structures * ---------------------------------------------------------------------------*/ // IndexTable is the list of children of a CCS. (Alternatively it is a // cache of the results of pushing onto a CCS, so that the second and // subsequent times we push a certain CC on a CCS we get the same // result). typedef struct IndexTable_ { CostCentre *cc; CostCentreStack *ccs; struct IndexTable_ *next; unsigned int back_edge; } IndexTable; /* ----------------------------------------------------------------------------- Pre-defined cost centres and cost centre stacks -------------------------------------------------------------------------- */ #if IN_STG_CODE extern StgWord CC_MAIN[]; extern StgWord CCS_MAIN[]; // Top CCS extern StgWord CC_SYSTEM[]; extern StgWord CCS_SYSTEM[]; // RTS costs extern StgWord CC_GC[]; extern StgWord CCS_GC[]; // Garbage collector costs extern StgWord CC_OVERHEAD[]; extern StgWord CCS_OVERHEAD[]; // Profiling overhead extern StgWord CC_DONT_CARE[]; extern StgWord CCS_DONT_CARE[]; // CCS attached to static constructors #else extern CostCentre CC_MAIN[]; extern CostCentreStack CCS_MAIN[]; // Top CCS extern CostCentre CC_SYSTEM[]; extern CostCentreStack CCS_SYSTEM[]; // RTS costs extern CostCentre CC_GC[]; extern CostCentreStack CCS_GC[]; // Garbage collector costs extern CostCentre CC_OVERHEAD[]; extern CostCentreStack CCS_OVERHEAD[]; // Profiling overhead extern CostCentre CC_DONT_CARE[]; extern CostCentreStack CCS_DONT_CARE[]; // shouldn't ever get set extern CostCentre CC_PINNED[]; extern CostCentreStack CCS_PINNED[]; // pinned memory extern CostCentre CC_IDLE[]; extern CostCentreStack CCS_IDLE[]; // capability is idle #endif /* IN_STG_CODE */ extern unsigned int RTS_VAR(CC_ID); // global ids extern unsigned int RTS_VAR(CCS_ID); extern unsigned int RTS_VAR(era); /* ----------------------------------------------------------------------------- * Functions * ---------------------------------------------------------------------------*/ CostCentreStack * pushCostCentre (CostCentreStack *, CostCentre *); void enterFunCCS (StgRegTable *reg, CostCentreStack *); /* ----------------------------------------------------------------------------- Registering CCs and CCSs Registering a CC or CCS consists of - assigning it a unique ID - linking it onto the list of registered CCs/CCSs Cost centres are registered at startup by a C constructor function generated by the compiler in the _stub.c file for each module. The macros below are invoked by that C code to register CCs and CCSs. -------------------------------------------------------------------------- */ extern CostCentre * RTS_VAR(CC_LIST); // registered CC list extern CostCentreStack * RTS_VAR(CCS_LIST); // registered CCS list #define REGISTER_CC(cc) \ do { \ if ((cc)->link == (CostCentre *)0) { \ (cc)->link = CC_LIST; \ CC_LIST = (cc); \ (cc)->ccID = CC_ID++; \ }} while(0) #define REGISTER_CCS(ccs) \ do { \ if ((ccs)->prevStack == (CostCentreStack *)0) { \ (ccs)->prevStack = CCS_LIST; \ CCS_LIST = (ccs); \ (ccs)->ccsID = CCS_ID++; \ }} while(0) /* ----------------------------------------------------------------------------- * Declaring Cost Centres & Cost Centre Stacks. * -------------------------------------------------------------------------- */ # define CC_DECLARE(cc_ident,name,mod,loc,caf,is_local) \ is_local CostCentre cc_ident[1] \ = {{ ccID : 0, \ label : name, \ module : mod, \ srcloc : loc, \ time_ticks : 0, \ mem_alloc : 0, \ link : 0, \ is_caf : caf \ }}; # define CCS_DECLARE(ccs_ident,cc_ident,is_local) \ is_local CostCentreStack ccs_ident[1] \ = {{ ccsID : 0, \ cc : cc_ident, \ prevStack : NULL, \ indexTable : NULL, \ root : NULL, \ depth : 0, \ selected : 0, \ scc_count : 0, \ time_ticks : 0, \ mem_alloc : 0, \ inherited_ticks : 0, \ inherited_alloc : 0 \ }}; /* ----------------------------------------------------------------------------- * Time / Allocation Macros * ---------------------------------------------------------------------------*/ /* eliminate profiling overhead from allocation costs */ #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader)) #else /* !PROFILING */ #define CCS_ALLOC(ccs, amount) doNothing() #endif /* PROFILING */ #endif /* RTS_PROF_CCS_H */