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