[project @ 2002-04-19 12:31:07 by simonmar]
[ghc-hetmet.git] / ghc / rts / Storage.c
1 /* -----------------------------------------------------------------------------
2  * $Id: Storage.c,v 1.61 2002/04/19 12:31:07 simonmar Exp $
3  *
4  * (c) The GHC Team, 1998-1999
5  *
6  * Storage manager front end
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #include "PosixSource.h"
11 #include "Rts.h"
12 #include "RtsUtils.h"
13 #include "RtsFlags.h"
14 #include "Stats.h"
15 #include "Hooks.h"
16 #include "BlockAlloc.h"
17 #include "MBlock.h"
18 #include "Weak.h"
19 #include "Sanity.h"
20 #include "Arena.h"
21
22 #include "Storage.h"
23 #include "Schedule.h"
24 #include "OSThreads.h"
25 #include "StoragePriv.h"
26
27 #include "RetainerProfile.h"    // for counting memory blocks (memInventory)
28
29 #ifdef darwin_TARGET_OS
30 #include <mach-o/getsect.h>
31 unsigned long macho_etext = 0;
32 unsigned long macho_edata = 0;
33
34 static void macosx_get_memory_layout(void)
35 {
36   struct segment_command *seg;
37
38   seg = getsegbyname("__TEXT");
39   macho_etext = seg->vmaddr + seg->vmsize;
40   seg = getsegbyname("__DATA");
41   macho_edata = seg->vmaddr + seg->vmsize;
42 }
43 #endif
44
45 StgClosure    *caf_list         = NULL;
46
47 bdescr *small_alloc_list;       /* allocate()d small objects */
48 bdescr *large_alloc_list;       /* allocate()d large objects */
49 bdescr *pinned_object_block;    /* allocate pinned objects into this block */
50 nat alloc_blocks;               /* number of allocate()d blocks since GC */
51 nat alloc_blocks_lim;           /* approximate limit on alloc_blocks */
52
53 StgPtr alloc_Hp    = NULL;      /* next free byte in small_alloc_list */
54 StgPtr alloc_HpLim = NULL;      /* end of block at small_alloc_list   */
55
56 generation *generations;        /* all the generations */
57 generation *g0;                 /* generation 0, for convenience */
58 generation *oldest_gen;         /* oldest generation, for convenience */
59 step *g0s0;                     /* generation 0, step 0, for convenience */
60
61 lnat total_allocated = 0;       /* total memory allocated during run */
62
63 /*
64  * Storage manager mutex:  protects all the above state from
65  * simultaneous access by two STG threads.
66  */
67 #ifdef SMP
68 Mutex sm_mutex = INIT_MUTEX_VAR;
69 #endif
70
71 /*
72  * Forward references
73  */
74 static void *stgAllocForGMP   (size_t size_in_bytes);
75 static void *stgReallocForGMP (void *ptr, size_t old_size, size_t new_size);
76 static void  stgDeallocForGMP (void *ptr, size_t size);
77
78 void
79 initStorage( void )
80 {
81   nat g, s;
82   step *stp;
83   generation *gen;
84
85 #if defined(darwin_TARGET_OS)
86     macosx_get_memory_layout();
87 #endif
88
89     /* Sanity check to make sure we are able to make the distinction
90      * between closures and infotables
91      */
92   if (!LOOKS_LIKE_GHC_INFO(&stg_BLACKHOLE_info)) {
93     barf("LOOKS_LIKE_GHC_INFO+ is incorrectly defined");
94     exit(0);
95   }
96   if (LOOKS_LIKE_GHC_INFO(&stg_dummy_ret_closure)) {
97     barf("LOOKS_LIKE_GHC_INFO- is incorrectly defined");
98     exit(0);
99   }
100   if (LOOKS_LIKE_STATIC_CLOSURE(&stg_BLACKHOLE_info)) {
101     barf("LOOKS_LIKE_STATIC_CLOSURE- is incorrectly defined");
102     exit(0);
103   }
104   if (!LOOKS_LIKE_STATIC_CLOSURE(&stg_dummy_ret_closure)) {
105     barf("LOOKS_LIKE_STATIC_CLOSURE+ is incorrectly defined");
106     exit(0);
107   }
108
109   if (RtsFlags.GcFlags.maxHeapSize != 0 &&
110       RtsFlags.GcFlags.heapSizeSuggestion > 
111       RtsFlags.GcFlags.maxHeapSize) {
112     RtsFlags.GcFlags.maxHeapSize = RtsFlags.GcFlags.heapSizeSuggestion;
113   }
114
115   if (RtsFlags.GcFlags.maxHeapSize != 0 &&
116       RtsFlags.GcFlags.minAllocAreaSize > 
117       RtsFlags.GcFlags.maxHeapSize) {
118       prog_belch("maximum heap size (-M) is smaller than minimum alloc area size (-A)");
119       exit(1);
120   }
121
122   initBlockAllocator();
123   
124 #if defined(SMP)
125   initCondition(&sm_mutex);
126 #endif
127
128   /* allocate generation info array */
129   generations = (generation *)stgMallocBytes(RtsFlags.GcFlags.generations 
130                                              * sizeof(struct _generation),
131                                              "initStorage: gens");
132
133   /* Initialise all generations */
134   for(g = 0; g < RtsFlags.GcFlags.generations; g++) {
135     gen = &generations[g];
136     gen->no = g;
137     gen->mut_list = END_MUT_LIST;
138     gen->mut_once_list = END_MUT_LIST;
139     gen->collections = 0;
140     gen->failed_promotions = 0;
141     gen->max_blocks = 0;
142   }
143
144   /* A couple of convenience pointers */
145   g0 = &generations[0];
146   oldest_gen = &generations[RtsFlags.GcFlags.generations-1];
147
148   /* Allocate step structures in each generation */
149   if (RtsFlags.GcFlags.generations > 1) {
150     /* Only for multiple-generations */
151
152     /* Oldest generation: one step */
153     oldest_gen->n_steps = 1;
154     oldest_gen->steps = 
155       stgMallocBytes(1 * sizeof(struct _step), "initStorage: last step");
156
157     /* set up all except the oldest generation with 2 steps */
158     for(g = 0; g < RtsFlags.GcFlags.generations-1; g++) {
159       generations[g].n_steps = RtsFlags.GcFlags.steps;
160       generations[g].steps  = 
161         stgMallocBytes (RtsFlags.GcFlags.steps * sizeof(struct _step),
162                         "initStorage: steps");
163     }
164     
165   } else {
166     /* single generation, i.e. a two-space collector */
167     g0->n_steps = 1;
168     g0->steps = stgMallocBytes (sizeof(struct _step), "initStorage: steps");
169   }
170
171   /* Initialise all steps */
172   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
173     for (s = 0; s < generations[g].n_steps; s++) {
174       stp = &generations[g].steps[s];
175       stp->no = s;
176       stp->blocks = NULL;
177       stp->n_blocks = 0;
178       stp->gen = &generations[g];
179       stp->gen_no = g;
180       stp->hp = NULL;
181       stp->hpLim = NULL;
182       stp->hp_bd = NULL;
183       stp->scan = NULL;
184       stp->scan_bd = NULL;
185       stp->large_objects = NULL;
186       stp->n_large_blocks = 0;
187       stp->new_large_objects = NULL;
188       stp->scavenged_large_objects = NULL;
189       stp->n_scavenged_large_blocks = 0;
190       stp->is_compacted = 0;
191       stp->bitmap = NULL;
192     }
193   }
194   
195   /* Set up the destination pointers in each younger gen. step */
196   for (g = 0; g < RtsFlags.GcFlags.generations-1; g++) {
197     for (s = 0; s < generations[g].n_steps-1; s++) {
198       generations[g].steps[s].to = &generations[g].steps[s+1];
199     }
200     generations[g].steps[s].to = &generations[g+1].steps[0];
201   }
202   
203   /* The oldest generation has one step and it is compacted. */
204   if (RtsFlags.GcFlags.compact) {
205       if (RtsFlags.GcFlags.generations == 1) {
206           belch("WARNING: compaction is incompatible with -G1; disabled");
207       } else {
208           oldest_gen->steps[0].is_compacted = 1;
209       }
210   }
211   oldest_gen->steps[0].to = &oldest_gen->steps[0];
212
213   /* generation 0 is special: that's the nursery */
214   generations[0].max_blocks = 0;
215
216   /* G0S0: the allocation area.  Policy: keep the allocation area
217    * small to begin with, even if we have a large suggested heap
218    * size.  Reason: we're going to do a major collection first, and we
219    * don't want it to be a big one.  This vague idea is borne out by 
220    * rigorous experimental evidence.
221    */
222   g0s0 = &generations[0].steps[0];
223
224   allocNurseries();
225
226   weak_ptr_list = NULL;
227   caf_list = NULL;
228    
229   /* initialise the allocate() interface */
230   small_alloc_list = NULL;
231   large_alloc_list = NULL;
232   alloc_blocks = 0;
233   alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize;
234
235   /* Tell GNU multi-precision pkg about our custom alloc functions */
236   mp_set_memory_functions(stgAllocForGMP, stgReallocForGMP, stgDeallocForGMP);
237
238 #if defined(SMP)
239   initMutex(&sm_mutex);
240 #endif
241
242   IF_DEBUG(gc, statDescribeGens());
243 }
244
245 void
246 exitStorage (void)
247 {
248     stat_exit(calcAllocated());
249 }
250
251 /* -----------------------------------------------------------------------------
252    CAF management.
253
254    The entry code for every CAF does the following:
255      
256       - builds a CAF_BLACKHOLE in the heap
257       - pushes an update frame pointing to the CAF_BLACKHOLE
258       - invokes UPD_CAF(), which:
259           - calls newCaf, below
260           - updates the CAF with a static indirection to the CAF_BLACKHOLE
261       
262    Why do we build a BLACKHOLE in the heap rather than just updating
263    the thunk directly?  It's so that we only need one kind of update
264    frame - otherwise we'd need a static version of the update frame too.
265
266    newCaf() does the following:
267        
268       - it puts the CAF on the oldest generation's mut-once list.
269         This is so that we can treat the CAF as a root when collecting
270         younger generations.
271
272    For GHCI, we have additional requirements when dealing with CAFs:
273
274       - we must *retain* all dynamically-loaded CAFs ever entered,
275         just in case we need them again.
276       - we must be able to *revert* CAFs that have been evaluated, to
277         their pre-evaluated form.
278
279       To do this, we use an additional CAF list.  When newCaf() is
280       called on a dynamically-loaded CAF, we add it to the CAF list
281       instead of the old-generation mutable list, and save away its
282       old info pointer (in caf->saved_info) for later reversion.
283
284       To revert all the CAFs, we traverse the CAF list and reset the
285       info pointer to caf->saved_info, then throw away the CAF list.
286       (see GC.c:revertCAFs()).
287
288       -- SDM 29/1/01
289
290    -------------------------------------------------------------------------- */
291
292 void
293 newCAF(StgClosure* caf)
294 {
295   /* Put this CAF on the mutable list for the old generation.
296    * This is a HACK - the IND_STATIC closure doesn't really have
297    * a mut_link field, but we pretend it has - in fact we re-use
298    * the STATIC_LINK field for the time being, because when we
299    * come to do a major GC we won't need the mut_link field
300    * any more and can use it as a STATIC_LINK.
301    */
302   ACQUIRE_SM_LOCK;
303
304   if (is_dynamically_loaded_rwdata_ptr((StgPtr)caf)) {
305       ((StgIndStatic *)caf)->saved_info  = (StgInfoTable *)caf->header.info;
306       ((StgIndStatic *)caf)->static_link = caf_list;
307       caf_list = caf;
308   } else {
309       ((StgIndStatic *)caf)->saved_info = NULL;
310       ((StgMutClosure *)caf)->mut_link = oldest_gen->mut_once_list;
311       oldest_gen->mut_once_list = (StgMutClosure *)caf;
312   }
313
314   RELEASE_SM_LOCK;
315
316 #ifdef PAR
317   /* If we are PAR or DIST then  we never forget a CAF */
318   { globalAddr *newGA;
319     //belch("<##> Globalising CAF %08x %s",caf,info_type(caf));
320     newGA=makeGlobal(caf,rtsTrue); /*given full weight*/
321     ASSERT(newGA);
322   } 
323 #endif /* PAR */
324 }
325
326 /* -----------------------------------------------------------------------------
327    Nursery management.
328    -------------------------------------------------------------------------- */
329
330 void
331 allocNurseries( void )
332
333 #ifdef SMP
334   {
335     Capability *cap;
336     bdescr *bd;
337
338     g0s0->blocks = NULL;
339     g0s0->n_blocks = 0;
340     for (cap = free_capabilities; cap != NULL; cap = cap->link) {
341       cap->r.rNursery = allocNursery(NULL, RtsFlags.GcFlags.minAllocAreaSize);
342       cap->r.rCurrentNursery = cap->r.rNursery;
343       for (bd = cap->r.rNursery; bd != NULL; bd = bd->link) {
344         bd->u.back = (bdescr *)cap;
345       }
346     }
347     /* Set the back links to be equal to the Capability,
348      * so we can do slightly better informed locking.
349      */
350   }
351 #else /* SMP */
352   g0s0->blocks      = allocNursery(NULL, RtsFlags.GcFlags.minAllocAreaSize);
353   g0s0->n_blocks    = RtsFlags.GcFlags.minAllocAreaSize;
354   g0s0->to_blocks   = NULL;
355   g0s0->n_to_blocks = 0;
356   MainCapability.r.rNursery        = g0s0->blocks;
357   MainCapability.r.rCurrentNursery = g0s0->blocks;
358   /* hp, hpLim, hp_bd, to_space etc. aren't used in G0S0 */
359 #endif
360 }
361       
362 void
363 resetNurseries( void )
364 {
365   bdescr *bd;
366 #ifdef SMP
367   Capability *cap;
368   
369   /* All tasks must be stopped */
370   ASSERT(n_free_capabilities == RtsFlags.ParFlags.nNodes);
371
372   for (cap = free_capabilities; cap != NULL; cap = cap->link) {
373     for (bd = cap->r.rNursery; bd; bd = bd->link) {
374       bd->free = bd->start;
375       ASSERT(bd->gen_no == 0);
376       ASSERT(bd->step == g0s0);
377       IF_DEBUG(sanity,memset(bd->start, 0xaa, BLOCK_SIZE));
378     }
379     cap->r.rCurrentNursery = cap->r.rNursery;
380   }
381 #else
382   for (bd = g0s0->blocks; bd; bd = bd->link) {
383     bd->free = bd->start;
384     ASSERT(bd->gen_no == 0);
385     ASSERT(bd->step == g0s0);
386     IF_DEBUG(sanity,memset(bd->start, 0xaa, BLOCK_SIZE));
387   }
388   MainCapability.r.rNursery = g0s0->blocks;
389   MainCapability.r.rCurrentNursery = g0s0->blocks;
390 #endif
391 }
392
393 bdescr *
394 allocNursery (bdescr *tail, nat blocks)
395 {
396   bdescr *bd;
397   nat i;
398
399   // Allocate a nursery: we allocate fresh blocks one at a time and
400   // cons them on to the front of the list, not forgetting to update
401   // the back pointer on the tail of the list to point to the new block.
402   for (i=0; i < blocks; i++) {
403     // @LDV profiling
404     /*
405       processNursery() in LdvProfile.c assumes that every block group in
406       the nursery contains only a single block. So, if a block group is
407       given multiple blocks, change processNursery() accordingly.
408      */
409     bd = allocBlock();
410     bd->link = tail;
411     // double-link the nursery: we might need to insert blocks
412     if (tail != NULL) {
413         tail->u.back = bd;
414     }
415     bd->step = g0s0;
416     bd->gen_no = 0;
417     bd->flags = 0;
418     bd->free = bd->start;
419     tail = bd;
420   }
421   tail->u.back = NULL;
422   return tail;
423 }
424
425 void
426 resizeNursery ( nat blocks )
427 {
428   bdescr *bd;
429   nat nursery_blocks;
430
431 #ifdef SMP
432   barf("resizeNursery: can't resize in SMP mode");
433 #endif
434
435   nursery_blocks = g0s0->n_blocks;
436   if (nursery_blocks == blocks) {
437     return;
438   }
439
440   else if (nursery_blocks < blocks) {
441     IF_DEBUG(gc, fprintf(stderr, "Increasing size of nursery to %d blocks\n", 
442                          blocks));
443     g0s0->blocks = allocNursery(g0s0->blocks, blocks-nursery_blocks);
444   } 
445
446   else {
447     bdescr *next_bd;
448     
449     IF_DEBUG(gc, fprintf(stderr, "Decreasing size of nursery to %d blocks\n", 
450                          blocks));
451
452     bd = g0s0->blocks;
453     while (nursery_blocks > blocks) {
454         next_bd = bd->link;
455         next_bd->u.back = NULL;
456         nursery_blocks -= bd->blocks; // might be a large block
457         freeGroup(bd);
458         bd = next_bd;
459     }
460     g0s0->blocks = bd;
461     // might have gone just under, by freeing a large block, so make
462     // up the difference.
463     if (nursery_blocks < blocks) {
464         g0s0->blocks = allocNursery(g0s0->blocks, blocks-nursery_blocks);
465     }
466   }
467   
468   g0s0->n_blocks = blocks;
469   ASSERT(countBlocks(g0s0->blocks) == g0s0->n_blocks);
470 }
471
472 /* -----------------------------------------------------------------------------
473    The allocate() interface
474
475    allocate(n) always succeeds, and returns a chunk of memory n words
476    long.  n can be larger than the size of a block if necessary, in
477    which case a contiguous block group will be allocated.
478    -------------------------------------------------------------------------- */
479
480 StgPtr
481 allocate( nat n )
482 {
483   bdescr *bd;
484   StgPtr p;
485
486   ACQUIRE_SM_LOCK;
487
488   TICK_ALLOC_HEAP_NOCTR(n);
489   CCS_ALLOC(CCCS,n);
490
491   /* big allocation (>LARGE_OBJECT_THRESHOLD) */
492   /* ToDo: allocate directly into generation 1 */
493   if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
494     nat req_blocks =  (lnat)BLOCK_ROUND_UP(n*sizeof(W_)) / BLOCK_SIZE;
495     bd = allocGroup(req_blocks);
496     dbl_link_onto(bd, &g0s0->large_objects);
497     bd->gen_no  = 0;
498     bd->step = g0s0;
499     bd->flags = BF_LARGE;
500     bd->free = bd->start;
501     /* don't add these blocks to alloc_blocks, since we're assuming
502      * that large objects are likely to remain live for quite a while
503      * (eg. running threads), so garbage collecting early won't make
504      * much difference.
505      */
506     alloc_blocks += req_blocks;
507     RELEASE_SM_LOCK;
508     return bd->start;
509
510   /* small allocation (<LARGE_OBJECT_THRESHOLD) */
511   } else if (small_alloc_list == NULL || alloc_Hp + n > alloc_HpLim) {
512     if (small_alloc_list) {
513       small_alloc_list->free = alloc_Hp;
514     }
515     bd = allocBlock();
516     bd->link = small_alloc_list;
517     small_alloc_list = bd;
518     bd->gen_no = 0;
519     bd->step = g0s0;
520     bd->flags = 0;
521     alloc_Hp = bd->start;
522     alloc_HpLim = bd->start + BLOCK_SIZE_W;
523     alloc_blocks++;
524   }
525
526   p = alloc_Hp;
527   alloc_Hp += n;
528   RELEASE_SM_LOCK;
529   return p;
530 }
531
532 lnat
533 allocated_bytes( void )
534 {
535   return (alloc_blocks * BLOCK_SIZE_W - (alloc_HpLim - alloc_Hp));
536 }
537
538 /* ---------------------------------------------------------------------------
539    Allocate a fixed/pinned object.
540
541    We allocate small pinned objects into a single block, allocating a
542    new block when the current one overflows.  The block is chained
543    onto the large_object_list of generation 0 step 0.
544
545    NOTE: The GC can't in general handle pinned objects.  This
546    interface is only safe to use for ByteArrays, which have no
547    pointers and don't require scavenging.  It works because the
548    block's descriptor has the BF_LARGE flag set, so the block is
549    treated as a large object and chained onto various lists, rather
550    than the individual objects being copied.  However, when it comes
551    to scavenge the block, the GC will only scavenge the first object.
552    The reason is that the GC can't linearly scan a block of pinned
553    objects at the moment (doing so would require using the
554    mostly-copying techniques).  But since we're restricting ourselves
555    to pinned ByteArrays, not scavenging is ok.
556
557    This function is called by newPinnedByteArray# which immediately
558    fills the allocated memory with a MutableByteArray#.
559    ------------------------------------------------------------------------- */
560
561 StgPtr
562 allocatePinned( nat n )
563 {
564     StgPtr p;
565     bdescr *bd = pinned_object_block;
566
567     ACQUIRE_SM_LOCK;
568     
569     TICK_ALLOC_HEAP_NOCTR(n);
570     CCS_ALLOC(CCCS,n);
571
572     // If the request is for a large object, then allocate()
573     // will give us a pinned object anyway.
574     if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
575         RELEASE_SM_LOCK;
576         return allocate(n);
577     }
578
579     // If we don't have a block of pinned objects yet, or the current
580     // one isn't large enough to hold the new object, allocate a new one.
581     if (bd == NULL || (bd->free + n) > (bd->start + BLOCK_SIZE_W)) {
582         pinned_object_block = bd = allocBlock();
583         dbl_link_onto(bd, &g0s0->large_objects);
584         bd->gen_no = 0;
585         bd->step   = g0s0;
586         bd->flags  = BF_LARGE;
587         bd->free   = bd->start;
588         alloc_blocks++;
589     }
590
591     p = bd->free;
592     bd->free += n;
593     RELEASE_SM_LOCK;
594     return p;
595 }
596
597 /* -----------------------------------------------------------------------------
598    Allocation functions for GMP.
599
600    These all use the allocate() interface - we can't have any garbage
601    collection going on during a gmp operation, so we use allocate()
602    which always succeeds.  The gmp operations which might need to
603    allocate will ask the storage manager (via doYouWantToGC()) whether
604    a garbage collection is required, in case we get into a loop doing
605    only allocate() style allocation.
606    -------------------------------------------------------------------------- */
607
608 static void *
609 stgAllocForGMP (size_t size_in_bytes)
610 {
611   StgArrWords* arr;
612   nat data_size_in_words, total_size_in_words;
613   
614   /* should be a multiple of sizeof(StgWord) (whole no. of limbs) */
615   ASSERT(size_in_bytes % sizeof(W_) == 0);
616   
617   data_size_in_words  = size_in_bytes / sizeof(W_);
618   total_size_in_words = sizeofW(StgArrWords) + data_size_in_words;
619   
620   /* allocate and fill it in. */
621   arr = (StgArrWords *)allocate(total_size_in_words);
622   SET_ARR_HDR(arr, &stg_ARR_WORDS_info, CCCS, data_size_in_words);
623   
624   /* and return a ptr to the goods inside the array */
625   return(BYTE_ARR_CTS(arr));
626 }
627
628 static void *
629 stgReallocForGMP (void *ptr, size_t old_size, size_t new_size)
630 {
631     void *new_stuff_ptr = stgAllocForGMP(new_size);
632     nat i = 0;
633     char *p = (char *) ptr;
634     char *q = (char *) new_stuff_ptr;
635
636     for (; i < old_size; i++, p++, q++) {
637         *q = *p;
638     }
639
640     return(new_stuff_ptr);
641 }
642
643 static void
644 stgDeallocForGMP (void *ptr STG_UNUSED, 
645                   size_t size STG_UNUSED)
646 {
647     /* easy for us: the garbage collector does the dealloc'n */
648 }
649
650 /* -----------------------------------------------------------------------------
651  * Stats and stuff
652  * -------------------------------------------------------------------------- */
653
654 /* -----------------------------------------------------------------------------
655  * calcAllocated()
656  *
657  * Approximate how much we've allocated: number of blocks in the
658  * nursery + blocks allocated via allocate() - unused nusery blocks.
659  * This leaves a little slop at the end of each block, and doesn't
660  * take into account large objects (ToDo).
661  * -------------------------------------------------------------------------- */
662
663 lnat
664 calcAllocated( void )
665 {
666   nat allocated;
667   bdescr *bd;
668
669 #ifdef SMP
670   Capability *cap;
671
672   /* All tasks must be stopped.  Can't assert that all the
673      capabilities are owned by the scheduler, though: one or more
674      tasks might have been stopped while they were running (non-main)
675      threads. */
676   /*  ASSERT(n_free_capabilities == RtsFlags.ParFlags.nNodes); */
677
678   allocated = 
679     n_free_capabilities * RtsFlags.GcFlags.minAllocAreaSize * BLOCK_SIZE_W
680     + allocated_bytes();
681
682   for (cap = free_capabilities; cap != NULL; cap = cap->link) {
683     for ( bd = cap->r.rCurrentNursery->link; bd != NULL; bd = bd->link ) {
684       allocated -= BLOCK_SIZE_W;
685     }
686     if (cap->r.rCurrentNursery->free < cap->r.rCurrentNursery->start 
687         + BLOCK_SIZE_W) {
688       allocated -= (cap->r.rCurrentNursery->start + BLOCK_SIZE_W)
689         - cap->r.rCurrentNursery->free;
690     }
691   }
692
693 #else /* !SMP */
694   bdescr *current_nursery = MainCapability.r.rCurrentNursery;
695
696   allocated = (g0s0->n_blocks * BLOCK_SIZE_W) + allocated_bytes();
697   for ( bd = current_nursery->link; bd != NULL; bd = bd->link ) {
698     allocated -= BLOCK_SIZE_W;
699   }
700   if (current_nursery->free < current_nursery->start + BLOCK_SIZE_W) {
701     allocated -= (current_nursery->start + BLOCK_SIZE_W)
702       - current_nursery->free;
703   }
704 #endif
705
706   total_allocated += allocated;
707   return allocated;
708 }  
709
710 /* Approximate the amount of live data in the heap.  To be called just
711  * after garbage collection (see GarbageCollect()).
712  */
713 extern lnat 
714 calcLive(void)
715 {
716   nat g, s;
717   lnat live = 0;
718   step *stp;
719
720   if (RtsFlags.GcFlags.generations == 1) {
721     live = (g0s0->n_to_blocks - 1) * BLOCK_SIZE_W + 
722       ((lnat)g0s0->hp_bd->free - (lnat)g0s0->hp_bd->start) / sizeof(W_);
723     return live;
724   }
725
726   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
727     for (s = 0; s < generations[g].n_steps; s++) {
728       /* approximate amount of live data (doesn't take into account slop
729        * at end of each block).
730        */
731       if (g == 0 && s == 0) { 
732           continue; 
733       }
734       stp = &generations[g].steps[s];
735       live += (stp->n_large_blocks + stp->n_blocks - 1) * BLOCK_SIZE_W;
736       if (stp->hp_bd != NULL) {
737           live += ((lnat)stp->hp_bd->free - (lnat)stp->hp_bd->start) 
738               / sizeof(W_);
739       }
740     }
741   }
742   return live;
743 }
744
745 /* Approximate the number of blocks that will be needed at the next
746  * garbage collection.
747  *
748  * Assume: all data currently live will remain live.  Steps that will
749  * be collected next time will therefore need twice as many blocks
750  * since all the data will be copied.
751  */
752 extern lnat 
753 calcNeeded(void)
754 {
755     lnat needed = 0;
756     nat g, s;
757     step *stp;
758     
759     for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
760         for (s = 0; s < generations[g].n_steps; s++) {
761             if (g == 0 && s == 0) { continue; }
762             stp = &generations[g].steps[s];
763             if (generations[g].steps[0].n_blocks +
764                 generations[g].steps[0].n_large_blocks 
765                 > generations[g].max_blocks
766                 && stp->is_compacted == 0) {
767                 needed += 2 * stp->n_blocks;
768             } else {
769                 needed += stp->n_blocks;
770             }
771         }
772     }
773     return needed;
774 }
775
776 /* -----------------------------------------------------------------------------
777    Debugging
778
779    memInventory() checks for memory leaks by counting up all the
780    blocks we know about and comparing that to the number of blocks
781    allegedly floating around in the system.
782    -------------------------------------------------------------------------- */
783
784 #ifdef DEBUG
785
786 void
787 memInventory(void)
788 {
789   nat g, s;
790   step *stp;
791   bdescr *bd;
792   lnat total_blocks = 0, free_blocks = 0;
793
794   /* count the blocks we current have */
795
796   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
797     for (s = 0; s < generations[g].n_steps; s++) {
798       stp = &generations[g].steps[s];
799       total_blocks += stp->n_blocks;
800       if (RtsFlags.GcFlags.generations == 1) {
801         /* two-space collector has a to-space too :-) */
802         total_blocks += g0s0->n_to_blocks;
803       }
804       for (bd = stp->large_objects; bd; bd = bd->link) {
805         total_blocks += bd->blocks;
806         /* hack for megablock groups: they have an extra block or two in
807            the second and subsequent megablocks where the block
808            descriptors would normally go.
809         */
810         if (bd->blocks > BLOCKS_PER_MBLOCK) {
811           total_blocks -= (MBLOCK_SIZE / BLOCK_SIZE - BLOCKS_PER_MBLOCK)
812                           * (bd->blocks/(MBLOCK_SIZE/BLOCK_SIZE));
813         }
814       }
815     }
816   }
817
818   /* any blocks held by allocate() */
819   for (bd = small_alloc_list; bd; bd = bd->link) {
820     total_blocks += bd->blocks;
821   }
822   for (bd = large_alloc_list; bd; bd = bd->link) {
823     total_blocks += bd->blocks;
824   }
825
826 #ifdef PROFILING
827   if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_RETAINER) {
828     for (bd = firstStack; bd != NULL; bd = bd->link) 
829       total_blocks += bd->blocks;
830   }
831 #endif
832
833   // count the blocks allocated by the arena allocator
834   total_blocks += arenaBlocks();
835
836   /* count the blocks on the free list */
837   free_blocks = countFreeList();
838
839   if (total_blocks + free_blocks != mblocks_allocated *
840       BLOCKS_PER_MBLOCK) {
841     fprintf(stderr, "Blocks: %ld live + %ld free  = %ld total (%ld around)\n",
842             total_blocks, free_blocks, total_blocks + free_blocks,
843             mblocks_allocated * BLOCKS_PER_MBLOCK);
844   }
845
846   ASSERT(total_blocks + free_blocks == mblocks_allocated * BLOCKS_PER_MBLOCK);
847 }
848
849
850 nat
851 countBlocks(bdescr *bd)
852 {
853     nat n;
854     for (n=0; bd != NULL; bd=bd->link) {
855         n += bd->blocks;
856     }
857     return n;
858 }
859
860 /* Full heap sanity check. */
861 void
862 checkSanity( void )
863 {
864     nat g, s;
865
866     if (RtsFlags.GcFlags.generations == 1) {
867         checkHeap(g0s0->to_blocks);
868         checkChain(g0s0->large_objects);
869     } else {
870         
871         for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
872             for (s = 0; s < generations[g].n_steps; s++) {
873                 ASSERT(countBlocks(generations[g].steps[s].blocks)
874                        == generations[g].steps[s].n_blocks);
875                 ASSERT(countBlocks(generations[g].steps[s].large_objects)
876                        == generations[g].steps[s].n_large_blocks);
877                 if (g == 0 && s == 0) { continue; }
878                 checkHeap(generations[g].steps[s].blocks);
879                 checkChain(generations[g].steps[s].large_objects);
880                 if (g > 0) {
881                     checkMutableList(generations[g].mut_list, g);
882                     checkMutOnceList(generations[g].mut_once_list, g);
883                 }
884             }
885         }
886         checkFreeListSanity();
887     }
888 }
889
890 // handy function for use in gdb, because Bdescr() is inlined.
891 extern bdescr *_bdescr( StgPtr p );
892
893 bdescr *
894 _bdescr( StgPtr p )
895 {
896     return Bdescr(p);
897 }
898
899 #endif