[project @ 1998-11-26 09:17:22 by sof]
[ghc-hetmet.git] / ghc / includes / CostCentre.lh
1 %************************************************************************
2 %*                                                                      *
3 \section[CostCentre.lh]{Definitions for Cost Centre Profiling}
4 %*                                                                      *
5 %************************************************************************
6
7 Multi-slurp protection:
8 \begin{code}
9 #ifndef CostCentre_H
10 #define CostCentre_H
11 \end{code}
12
13 For threaded activity profiling, we need a few bits of the CostCentre
14 environment to be defined, despite the fact that we don't have CostCentre
15 fields in closures.
16
17 \begin{code}
18 #if defined(PROFILING) || defined(CONCURRENT)
19
20 # define CC_EXTERN(cc_ident)                                    \
21      extern struct cc CAT2(cc_ident,_struct);                   \
22      extern CostCentre cc_ident
23
24 extern CostCentre CCC;          /* the current cost centre */
25
26 extern CostCentre Registered_CC;/* registered cost centre list */
27
28 CC_EXTERN(CC_MAIN);             /* initial MAIN cost centre */
29 CC_EXTERN(CC_GC);               /* Garbage Collection cost center */
30
31 # ifdef PAR
32 CC_EXTERN(CC_MSG);              /* Communications cost center */
33 CC_EXTERN(CC_IDLE);             /* Idle-time cost centre */
34 # endif
35
36 # define REGISTERED_END (CostCentre)4   /* end of list */
37                                         /* That 4 look likes a HACK, Patrick.
38                                            (WDP 94/06) */
39 # define NOT_REGISTERED (CostCentre)0   /* not yet registered */
40
41 \end{code}
42
43 The compiler declares a static block for each @_scc_@ annotation in the
44 source using the @CC_DECLARE@ macro where @label@, @module@ and
45 @group@ are strings and @ident@ the cost centre identifier.
46
47 \begin{code} 
48 # define CC_IS_CAF      'c'
49 # define CC_IS_DICT     'd'
50 # define CC_IS_SUBSUMED 's'
51 # define CC_IS_BORING   'B'
52
53 # define STATIC_CC_REF(cc_ident) &CAT2(cc_ident,_struct)
54 # define DYN_CC_REF(cc_ident)    cc_ident /* unused */
55
56 # define CC_DECLARE(cc_ident,name,module,group,subsumed,is_local)       \
57      is_local struct cc CAT2(cc_ident,_struct)                          \
58         = {NOT_REGISTERED, UNHASHED, name, module, group,               \
59            subsumed, INIT_CC_STATS};                                    \
60      is_local CostCentre cc_ident = STATIC_CC_REF(cc_ident)
61
62 #endif /* defined(PROFILING) || defined(CONCURRENT) */
63 \end{code}
64
65 Definitions relating to the profiling field as a whole.
66
67 \begin{code}
68 #define PROF_FIXED_HDR                  (CC_HDR_SIZE)   
69 #define PROF_HDR_POSN                   AFTER_PAR_HDR
70 #define AFTER_PROF_HDR                  (PROF_FIXED_HDR+PROF_HDR_POSN)
71 #define SET_PROF_HDR(closure,cc)        SET_CC_HDR(closure,cc)
72 #define SET_STATIC_PROF_HDR(ident)      SET_STATIC_CC_HDR(ident)
73 \end{code}
74
75 %************************************************************************
76 %*                                                                      *
77 \subsection[no-cost-centres]{Dummy definitions if no cost centres}
78 %*                                                                      *
79 %************************************************************************
80
81 The cost-centre profiling is only on if the driver turns on
82 @PROFILING@.
83
84 These are the {\em dummy} definitions in force if we do {\em NOT}
85 turn on @PROFILING@.  Get them out of the way....
86
87 \begin{code}
88 #if !defined(PROFILING)
89
90 /*** Declaration Definitions ***/
91
92 # define CAT_DECLARE(base_name, kind, descr, type)
93
94 # define CC_HDR_SIZE 0                  /* No CC in fixed header */
95
96 # define SET_CC_HDR(closure, cc)        /* Dont set CC header */
97 # define SET_STATIC_CC_HDR(cc)          /* No static CC header */
98
99 # define SET_CCC(cc_ident,do_scc_count)
100 # define SET_DICT_CCC(cc_ident,do_scc_count)
101 # define SET_CCC_RTS(cc_ident,do_sub_count,do_count)
102
103 # define RESTORE_CCC(cc)
104
105 # define ENTER_CC_T(cc)
106 # define ENTER_CC_TCL(closure)
107 # define ENTER_CC_F(cc)
108 # define ENTER_CC_FCL(closure)
109 # define ENTER_CC_FSUB()
110 # define ENTER_CC_FCAF(cc)
111 # define ENTER_CC_FLOAD(cc)
112 # define ENTER_CC_PAP(cc)
113 # define ENTER_CC_PAP_CL(closure)
114
115 /*** Timer and Heap Definitions ***/
116
117 # define OR_INTERVAL_EXPIRED    /* No || as it is false */
118
119 # define CC_ALLOC(cc, size, kind)
120 # define HEAP_PROFILE_CLOSURE(closure,size)
121
122 # ifndef PAR
123 #  define START_TIME_PROFILER
124 #  define RESTART_TIME_PROFILER
125 #  define STOP_TIME_PROFILER
126 # endif
127
128 #endif /* !defined(PROFILING) */
129 \end{code}
130
131 %************************************************************************
132 %*                                                                      *
133 \subsection[declaring-cost-centres]{Declaring Cost Centres}
134 %*                                                                      *
135 %************************************************************************
136
137 Now for the cost-centre profiling stuff.
138
139 %************************************************************************
140 %*                                                                      *
141 \subsection[cost-centres]{Location of Cost Centres}
142 %*                                                                      *
143 %************************************************************************
144
145 We have a current cost centre, a list of registered cost centres, and
146 an additional cost centre field within the fixed header of all
147 closures. This is adjacent to the info pointer.
148
149 \begin{code}
150 #if defined(PROFILING)
151
152 CC_EXTERN(CC_SUBSUMED);         /* top level fns SUBSUMED cost centre */
153 CC_EXTERN(CC_OVERHEAD);         /* costs due only to profiling machinery */
154 CC_EXTERN(CC_DONTZuCARE);       /* placeholder only */
155
156 CC_EXTERN(CC_CAFs);             /* prelude cost centre (CAFs  only) */
157 CC_EXTERN(CC_DICTs);            /* prelude cost centre (DICTs only) */
158
159 # define IS_CAF_OR_DICT_OR_SUB_CC(cc) \
160     ((cc)->is_subsumed & ' ')   /* tests for lower case character */
161
162 \end{code}
163
164 Definitions referring to the Cost Centre sub-field of the fixed header.
165 \begin{code}
166
167 # define CC_HDR_SIZE            1       /* words of header */
168                                         /*R SMinterface.lh */
169
170 # define CC_HDR_POSN            PROF_HDR_POSN   /* position in header */
171
172 # define CC_HDR(closure)        (((P_)(closure))[CC_HDR_POSN])
173
174 # define SET_CC_HDR(closure, cc) \
175         CC_HDR(closure) = (W_)(cc)      /* Set closures cost centre */
176                                         /*R SMinterface.lh (CCC) */
177 \end{code}
178
179 For static closures ...
180 \begin{code}
181 # define SET_STATIC_CC_HDR(cc_ident) \
182         ,  (W_) STATIC_CC_REF(cc_ident)         /* static initialisation */
183                                                 /*R SMinterface.lh */
184 \end{code}
185
186 The @/*R @{\em file}@ */@ comments indicate that the macro is used
187 regardless in {\em file} so we need a null definition if cost centres
188 are not being used.
189
190 %************************************************************************
191 %*                                                                      *
192 \subsection{Setting the Current Cost Centre}
193 %*                                                                      *
194 %************************************************************************
195
196 On execution of an @_scc_@ expression a new cost centre is set.
197
198 If the new cost centre is different from the CCC we set the CCC and
199 count the entry.
200
201 If the cost centre is the same as the CCC no action is required. We do
202 not count the entry to avoid large counts arising from simple
203 recursion.  (Huh?  WDP 94/07)
204
205 \begin{code}
206 # define SET_CCC_X(cc,do_subcc_count,do_subdict_count,do_scc_count)                             \
207         do {                                                                                    \
208         if ((do_subcc_count)) { CCC->sub_scc_count++; }       /* inc subcc count of CCC */      \
209         if ((do_subdict_count)) { CCC->sub_dictcc_count++; }  /* inc sub dict count of CCC */   \
210         CCC = (CostCentre)(cc);                               /* set CCC to ident cc */         \
211         ASSERT_IS_REGISTERED(CCC,1);                                                            \
212         if ((do_scc_count)) { CCC->scc_count++; }             /* inc scc count of new CCC*/     \
213         } while(0)
214
215 # define SET_CCC(cc_ident,do_scc_count) \
216          SET_CCC_X(STATIC_CC_REF(cc_ident),do_scc_count,0,do_scc_count)
217
218 # define SET_DICT_CCC(cc_ident,do_scc_count) \
219          SET_CCC_X(STATIC_CC_REF(cc_ident),0,do_scc_count,do_scc_count)
220
221 # define SET_CCC_RTS(cc_ident,do_sub_count,do_scc_count) \
222          SET_CCC_X(STATIC_CC_REF(cc_ident),do_sub_count,0,do_scc_count)
223 \end{code}
224
225 We have this @RESTORE_CCC@ macro, rather than just an assignment,
226 in case we want to do any paranoia-checking here.
227 \begin{code}
228 # define RESTORE_CCC(cc)                \
229         do {                            \
230         CCC = (CostCentre) (cc);        \
231         ASSERT_IS_REGISTERED(CCC,1);    \
232         } while(0)
233 \end{code}
234
235 On entry to top level CAFs we count the scc ...
236 \begin{code}
237 # define ENTER_CC_CAF_X(cc)                                             \
238         do {                                                            \
239         CCC->sub_cafcc_count++; /* inc subcaf count of CCC */           \
240         CCC = (CostCentre)(cc); /* set CCC to ident cc */               \
241         ASSERT_IS_REGISTERED(CCC,1);                                    \
242         CCC->scc_count++;       /* inc scc count of CAF cc */           \
243         } while(0)
244
245 # define ENTER_CC_CAF(cc_ident)   ENTER_CC_CAF_X(STATIC_CC_REF(cc_ident))
246 # define ENTER_CC_CAF_CL(closure) ENTER_CC_CAF_X((CostCentre)CC_HDR(closure))
247 \end{code}
248
249 On entering a closure we only count the enter to thunks ...
250 \begin{code}
251 # define ENTER_CC_T(cc)                                 \
252         do {                                            \
253         CCC = (CostCentre)(cc);                         \
254         ASSERT_IS_REGISTERED(CCC,1);                    \
255         CCC_DETAIL_COUNT(CCC->thunk_count);             \
256         } while(0)      
257
258 # define ENTER_CC_TCL(closure)                          \
259         ENTER_CC_T(CC_HDR(closure))
260
261 /* Here is our special "hybrid" case when we do *not* set the CCC.
262    (a) The closure is a function, not a thunk;
263    (b) The CC is CAF/DICT-ish.
264 */
265 # define ENTER_CC_F(centre)                             \
266         do {                                            \
267         CostCentre cc = (CostCentre) (centre);          \
268         ASSERT_IS_REGISTERED(cc,1);                     \
269         if ( ! IS_CAF_OR_DICT_OR_SUB_CC(cc) ) {         \
270             CCC = cc;                                   \
271         } else {                                        \
272             CCC_DETAIL_COUNT(cc->caffun_subsumed);      \
273             CCC_DETAIL_COUNT(CCC->subsumed_caf_count);  \
274         }                                               \
275         CCC_DETAIL_COUNT(CCC->function_count);          \
276         } while(0)
277
278 # define ENTER_CC_FCL(closure)                          \
279         ENTER_CC_F(CC_HDR(closure))
280
281 # define ENTER_CC_FSUB()                                \
282         do {                                            \
283         CCC_DETAIL_COUNT(CCC->subsumed_fun_count);      \
284         CCC_DETAIL_COUNT(CCC->function_count);          \
285         } while(0)
286
287 # define ENTER_CC_FCAF(centre)                          \
288         do {                                            \
289         CostCentre cc = (CostCentre) (centre);          \
290         ASSERT_IS_REGISTERED(cc,1);                     \
291         CCC_DETAIL_COUNT(cc->caffun_subsumed);          \
292         CCC_DETAIL_COUNT(CCC->subsumed_caf_count);      \
293         CCC_DETAIL_COUNT(CCC->function_count);          \
294         } while(0)
295
296 # define ENTER_CC_FLOAD(cc)                             \
297         do {                                            \
298         CCC = (CostCentre)(cc);                         \
299         ASSERT_IS_REGISTERED(CCC,1);                    \
300         CCC_DETAIL_COUNT(CCC->function_count);          \
301         } while(0)
302
303 /* These ENTER_CC_PAP things are only used in the RTS */
304
305 # define ENTER_CC_PAP(centre)                           \
306         do {                                            \
307         CostCentre cc = (CostCentre) (centre);          \
308         ASSERT_IS_REGISTERED(cc,1);                     \
309         if ( ! IS_CAF_OR_DICT_OR_SUB_CC(cc) ) {         \
310             CCC = cc;                                   \
311             CCC->scc_count++;                           \
312         } else {                                        \
313             CCC_DETAIL_COUNT(cc->caffun_subsumed);      \
314             CCC_DETAIL_COUNT(CCC->subsumed_caf_count);  \
315         }                                               \
316         CCC_DETAIL_COUNT(CCC->pap_count);               \
317         } while(0)                      
318                                         
319 # define ENTER_CC_PAP_CL(closure)                       \
320         ENTER_CC_PAP(CC_HDR(closure))
321
322 # if defined(PROFILING_DETAIL_COUNTS)
323 # define CCC_DETAIL_COUNT(inc_this) ((inc_this)++)
324 # else
325 # define CCC_DETAIL_COUNT(inc_this) /*nothing*/
326 # endif
327
328 #endif /* PROFILING */
329 \end{code}
330
331 %************************************************************************
332 %*                                                                      *
333 \subsection{``Registering'' cost-centres}
334 %*                                                                      *
335 %************************************************************************
336
337 Cost centres are registered at startup by calling a registering
338 routine in each module. Each module registers its cost centres and
339 calls the registering routine for all imported modules. The RTS calls
340 the registering routine for the module Main. This registering must be
341 done before initialisation since the evaluation required for
342 initialisation may use the cost centres.
343
344 As the code for each module uses tail calls we use an auxiliary stack
345 (in the heap) to record imported modules still to be registered. At
346 the bottom of the stack is NULL which indicates that
347 @miniInterpretEnd@ should be resumed.
348
349 @START_REGISTER@ and @END_REGISTER@ are special macros used to
350 delimit the function. @END_REGISTER@ pops the next registering
351 routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
352 centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
353 the register stack.
354
355 \begin{code}
356 #if defined(PROFILING)
357
358 extern F_ _regMain (STG_NO_ARGS);
359 extern F_ *register_stack;
360
361 # define PUSH_REGISTER_STACK(reg_function)                              \
362         *(register_stack++) = (F_)reg_function
363
364 # define POP_REGISTER_STACK                                             \
365         *(--register_stack)
366
367 # define START_REGISTER_CCS(reg_mod_name)                               \
368         static int _module_registered = 0;                              \
369         STGFUN(reg_mod_name) {                                          \
370             FUNBEGIN;                                                   \
371             if (! _module_registered) {                                 \
372                 _module_registered = 1
373
374 # define START_REGISTER_PRELUDE(reg_mod_name)                           \
375         static int CAT2(reg_mod_name,_done) = 0;                        \
376         STGFUN(reg_mod_name) {                                          \
377             FUNBEGIN;                                                   \
378             if (! CAT2(reg_mod_name,_done)) {                           \
379                 CAT2(reg_mod_name,_done) = 1
380
381 # define REGISTER_IMPORT(reg_mod_name)                                  \
382         do { extern F_ reg_mod_name (STG_NO_ARGS) ;                     \
383           PUSH_REGISTER_STACK(reg_mod_name) ;                           \
384         } while (0)
385         
386 # define END_REGISTER_CCS()                                             \
387         };                                                              \
388         do {                                                            \
389             F_ cont = POP_REGISTER_STACK;                               \
390             if (cont == NULL) {                                         \
391                 RESUME_(miniInterpretEnd);                              \
392             } else {                                                    \
393                 JMP_(cont);                                             \
394             }                                                           \
395         } while(0);                                                     \
396         FUNEND; }
397
398 #else   /* PROFILING */
399
400 /* When things are working these shouldn't be emitted when not profiling,
401    but it was convenient at one point to have them expand to nothing 
402     when not profiling.  SLPJ Dec 96 */
403
404 #define START_REGISTER_CCS(reg_mod_name)
405 #define END_REGISTER_CCS()
406
407 #endif  /* PROFILING */
408 \end{code}
409
410 We don't want to attribute costs to an unregistered cost-centre:
411 \begin{code}
412 #if !defined(PROFILING) || !defined(DEBUG)
413 # define ASSERT_IS_REGISTERED(cc,chk_not_overhead) /*nothing*/
414 #else
415 # define ASSERT_IS_REGISTERED(cc,chk_not_overhead)                              \
416         do {    /* beware of cc name-capture */                                 \
417         CostCentre c_c = (CostCentre) (cc);                                     \
418         if (c_c->registered == NOT_REGISTERED) {                                \
419             fprintf(stderr,"Entering unregistered CC: %s %s\n",c_c->module, c_c->label);        \
420             /* unsafe c-call, BTW */                                            \
421         }                                                                       \
422         if ( (chk_not_overhead) && c_c == STATIC_CC_REF(CC_OVERHEAD) ) {        \
423             fprintf(stderr,"CC should not be OVERHEAD!: %s\n",c_c->label);      \
424             /* unsafe c-call, BTW */                                            \
425         } } while(0)
426 #endif
427
428 #define REGISTER_CC(cc)                                                 \
429         do {                                                            \
430         extern CostCentre cc;                                           \
431         if (((CostCentre)(cc))->registered == NOT_REGISTERED) {         \
432             ((CostCentre)(cc))->registered = Registered_CC;             \
433             Registered_CC = (CostCentre)(cc);                           \
434         }} while(0)
435
436 \end{code}
437
438 %************************************************************************
439 %*                                                                      *
440 \subsection[declaring-closure-categories]{Declaring Closure Categories}
441 %*                                                                      *
442 %************************************************************************
443
444 Closure category records are attached to the info table of the
445 closure. They are declared with the info table. Hashing will map
446 similar categories to the same hash value allowing statistics to be
447 grouped by closure category.
448
449 The declaration macros expand to nothing if cost centre profiling is
450 not required.
451
452 Note from ADR: Very dubious Malloc Ptr addition -- should probably just
453 reuse @CON_K@ (or something) in runtime/main/StgStartup.lhc.
454 Similarily, the SP stuff should probably be the highly uninformative
455 @INTERNAL_KIND@.
456
457 SOF 4/96: Renamed MallocPtr_K to ForeignObj_K 
458
459 \begin{code}
460 #if defined(PROFILING)
461
462 # define CON_K          1
463 # define FN_K           2
464 # define PAP_K          3
465 # define THK_K          4
466 # define BH_K           5
467 # define ARR_K          6
468
469 # ifndef PAR
470 #  define ForeignObj_K  7  /* Malloc Pointer */
471 #  define SPT_K         8  /* Stable Pointer Table */
472 # endif /* !PAR */
473
474 # define INTERNAL_KIND  10
475
476 typedef struct ClCat {
477    hash_t index_val;    /* hashed value */
478    I_    selected; /* is this category selected (-1 == not memoised, selected? 0 or 1) */
479    I_    kind;     /* closure kind -- as above */
480    char *descr;    /* source derived string detailing closure description */
481    char *type;      /* source derived string detailing closure type */
482 } *ClCategory;
483
484 /* We put pointers to these ClCat things in info tables.
485    We need these ClCat things because they are mutable,
486    whereas info tables are immutable.  (WDP 94/11)
487
488    We really should not make funny names by appending _CAT.
489 */
490
491 # define MK_CAT_IDENT(i)   CAT2(i,_CAT)
492 # define REF_CAT_IDENT(i)  (&MK_CAT_IDENT(i))
493
494 # define CAT_DECLARE(base_name, kind, descr, type) \
495         static struct ClCat MK_CAT_IDENT(base_name) = {UNHASHED,-1,kind,descr,type};
496
497 #endif /* PROFILING */
498 \end{code}
499
500 %************************************************************************
501 %*                                                                      *
502 \subsection[timer-interupts]{Processing of Timer Signals}
503 %*                                                                      *
504 %************************************************************************
505
506 Stuff to do with timer signals:
507 \begin{code}
508 #if defined(PROFILING) || defined(PAR)
509
510 extern I_ time_profiling;       /* Flag indicating if timer/serial profiling is required */
511
512 extern I_ interval_expired;     /* Flag set by signal handler */
513 extern I_ current_interval;     /* Current interval number -- used as time stamp */
514 extern I_ interval_ticks;       /* No of ticks in an interval */
515
516 extern I_ previous_ticks;       /* ticks in previous intervals */
517 extern I_ current_ticks;        /* ticks in current interval */
518
519 extern void set_time_profile_handler(STG_NO_ARGS);
520 extern void start_time_profiler(STG_NO_ARGS);
521 extern void restart_time_profiler(STG_NO_ARGS);
522 extern void stop_time_profiler(STG_NO_ARGS);
523
524 # define TICK_FREQUENCY         50                      /* ticks per second */
525 # define TICK_MILLISECS         (1000/TICK_FREQUENCY)   /* milli-seconds per tick */
526
527 # define DEFAULT_INTERVAL       TICK_FREQUENCY          /* 1 second */
528
529 /* These are never called directly from threaded code */
530 # define START_TIME_PROFILER    ULTRASAFESTGCALL0(void,(void *),start_time_profiler)            /*R StgOverflow.lc */
531 # define RESTART_TIME_PROFILER  ULTRASAFESTGCALL0(void,(void *),restart_time_profiler)          /*R StgOverflow.lc */
532 # define STOP_TIME_PROFILER     ULTRASAFESTGCALL0(void,(void *),stop_time_profiler)             /*R StgOverflow.lc */
533
534 # if defined(PROFILING)
535 #  define OR_INTERVAL_EXPIRED   || (interval_expired)           /*R StgMacros.h */
536 # endif
537 \end{code}
538
539
540 %************************************************************************
541 %*                                                                      *
542 \subsection[indexing]{Indexing of Cost Centres and Categories}
543 %*                                                                      *
544 %************************************************************************
545
546 Cost Centres and Closure Categories are hashed to provide indexes
547 against which arbitrary information can be stored. These indexes are
548 memoised in the appropriate cost centre or category record and
549 subsequent hashes avoided by the index routine (it simply returns the
550 memoised index).
551
552 There are different features which can be hashed allowing information
553 to be stored for different groupings. Cost centres have the cost
554 centre recorded (using the pointer), module and group. Closure
555 categories have the closure description and the type
556 description. Records with the same feature will be hashed to the same
557 index value.
558
559 The initialisation routines, @init_index_<feature>@, allocate a hash
560 table in which the cost centre / category records are stored. The
561 lower bound for the table size is taken from @max_<feature>_no@. They
562 return the actual table size used (the next power of 2). Unused
563 locations in the hash table are indicated by a 0 entry. Successive
564 @init_index_<feature>@ calls just return the actual table size.
565
566 Calls to @index_<feature>@ will insert the cost centre / category
567 record in the <feature> hash table, if not already inserted. The hash
568 index is memoised in the record and returned. 
569
570 CURRENTLY ONLY ONE MEMOISATION SLOT IS AVILABLE IN EACH RECORD SO
571 HASHING CAN ONLY BE DONE ON ONE FEATURE FOR EACH RECORD. This can be
572 easily relaxed at the expense of extra memoisation space or continued
573 rehashing.
574
575 The initialisation routines must be called before initialisation of
576 the stacks and heap as they require to allocate storage. It is also
577 expected that the caller may want to allocate additional storage in
578 which to store profiling information based on the return table size
579 value(s).
580
581 \begin{code}
582 # if defined(PROFILING)
583
584 #  define DEFAULT_MAX_CC     4096
585 #  define DEFAULT_MAX_MOD     256
586 #  define DEFAULT_MAX_GRP     128
587 #  define DEFAULT_MAX_DESCR  4096
588 #  define DEFAULT_MAX_TYPE   1024
589
590 extern hash_t max_cc_no;                        /* Hash on CC ptr */
591 extern CostCentre *index_cc_table;
592 extern hash_t init_index_cc(STG_NO_ARGS);
593 extern hash_t index_cc PROTO((CostCentre cc));
594
595 extern hash_t max_mod_no;                       /* Hash on CC module */
596 extern CostCentre *index_mod_table;
597 extern hash_t init_index_mod(STG_NO_ARGS);
598 extern hash_t index_mod PROTO((CostCentre cc));
599
600 extern hash_t max_grp_no;                       /* Hash on CC group */
601 extern CostCentre *index_grp_table;
602 extern hash_t init_index_grp(STG_NO_ARGS);
603 extern hash_t index_grp PROTO((CostCentre cc));
604
605 extern hash_t max_descr_no;                     /* Hash on closure description */
606 extern ClCategory *index_descr_table;
607 extern hash_t init_index_descr(STG_NO_ARGS);
608 extern hash_t index_descr PROTO((ClCategory clcat));
609
610 extern hash_t max_type_no;                      /* Hash on type description */
611 extern ClCategory *index_type_table;
612 extern hash_t init_index_type(STG_NO_ARGS);
613 extern hash_t index_type PROTO((ClCategory clcat));
614
615 # endif /* PROFILING */
616 \end{code}
617
618
619 %************************************************************************
620 %*                                                                      *
621 \subsection[metering]{Metering of Statistics}
622 %*                                                                      *
623 %************************************************************************
624
625 @scc_count@ is incremented by the @SetCC@ macro in section
626 \ref{manipulating-cost-centres} above. Below we have the time tick and
627 memory alloc macros.
628
629 \begin{code}
630 # define CC_TICK(centre)                                                \
631         do { CostCentre cc = (CostCentre) (centre);                     \
632         ASSERT_IS_REGISTERED(cc,1);                                     \
633         cc->time_ticks += 1;                                            \
634         } while(0)
635
636 # if defined(PROFILING)
637 # define CC_ALLOC(centre, size, kind)                                   \
638         do { CostCentre cc = (CostCentre) (centre);                     \
639         ASSERT_IS_REGISTERED(cc,0/*OK if OVERHEAD*/);                   \
640         CCC_DETAIL_COUNT(cc->mem_allocs);                               \
641         cc->mem_alloc += (size) - (PROF_FIXED_HDR + TICKY_FIXED_HDR);   \
642         } while(0) 
643 # endif
644 \end{code}
645
646
647 %************************************************************************
648 %*                                                                      *
649 \subsection[cost-centre-profiling]{Cost Centre Profiling}
650 %*                                                                      *
651 %************************************************************************
652
653 \begin{code}
654 I_      init_cc_profiling PROTO((I_ rts_argc, char *rts_argv[], char *prog_argv[]));
655 void    report_cc_profiling PROTO((I_ final));
656
657 void    cc_register(STG_NO_ARGS);
658 void    cc_sort PROTO((CostCentre *sort, char sort_on));
659 rtsBool cc_to_ignore PROTO((CostCentre));
660 \end{code}
661
662 %************************************************************************
663 %*                                                                      *
664 \subsection[heap-profiling]{Heap Profiling}
665 %*                                                                      *
666 %************************************************************************
667
668 \begin{code}
669 # if defined(PROFILING)
670
671 I_ heap_profile_init PROTO((char *argv[]));
672
673 void heap_profile_finish(STG_NO_ARGS);
674
675 void heap_profile_setup(STG_NO_ARGS);      /* called at start of heap profile */
676 void heap_profile_done(STG_NO_ARGS);      /* called at end of heap profile */
677
678 void (* heap_profile_fn) PROTO((P_ closure,I_ size));
679
680 extern I_ earlier_ticks;                /* no. of earlier ticks grouped */
681 extern hash_t time_intervals;           /* no. of time intervals reported -- 18 */
682
683 # define HEAP_PROFILE_CLOSURE(closure,size)     \
684         do {                                    \
685         if (heap_profile_fn) {                  \
686             STGCALL2(void,(void *, P_, I_),(*heap_profile_fn),closure,size); \
687         }} while(0)
688
689 # endif /* PROFILING */
690 \end{code}
691
692 End multi-slurp protection:
693 \begin{code}
694 #endif /* PROFILING || PAR */
695
696 #endif /* CostCentre_H */
697 \end{code}