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