free the gc_thread structures during shutdown
[ghc-hetmet.git] / rts / sm / Storage.c
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2008
4  *
5  * Storage manager front end
6  *
7  * Documentation on the architecture of the Storage Manager can be
8  * found in the online commentary:
9  * 
10  *   http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage
11  *
12  * ---------------------------------------------------------------------------*/
13
14 #include "PosixSource.h"
15 #include "Rts.h"
16 #include "RtsUtils.h"
17 #include "RtsFlags.h"
18 #include "Stats.h"
19 #include "Hooks.h"
20 #include "BlockAlloc.h"
21 #include "MBlock.h"
22 #include "Weak.h"
23 #include "Sanity.h"
24 #include "Arena.h"
25 #include "OSThreads.h"
26 #include "Capability.h"
27 #include "Storage.h"
28 #include "Schedule.h"
29 #include "RetainerProfile.h"    // for counting memory blocks (memInventory)
30 #include "OSMem.h"
31 #include "Trace.h"
32 #include "GC.h"
33 #include "Evac.h"
34
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "ffi.h"
39
40 /* 
41  * All these globals require sm_mutex to access in THREADED_RTS mode.
42  */
43 StgClosure    *caf_list         = NULL;
44 StgClosure    *revertible_caf_list = NULL;
45 rtsBool       keepCAFs;
46
47 bdescr *pinned_object_block;    /* allocate pinned objects into this block */
48 nat alloc_blocks;               /* number of allocate()d blocks since GC */
49 nat alloc_blocks_lim;           /* approximate limit on alloc_blocks */
50
51 static bdescr *exec_block;
52
53 generation *generations = NULL; /* all the generations */
54 generation *g0          = NULL; /* generation 0, for convenience */
55 generation *oldest_gen  = NULL; /* oldest generation, for convenience */
56 step *g0s0              = NULL; /* generation 0, step 0, for convenience */
57
58 nat total_steps         = 0;
59 step *all_steps         = NULL; /* single array of steps */
60
61 ullong total_allocated = 0;     /* total memory allocated during run */
62
63 nat n_nurseries         = 0;    /* == RtsFlags.ParFlags.nNodes, convenience */
64 step *nurseries         = NULL; /* array of nurseries, >1 only if THREADED_RTS */
65
66 #ifdef THREADED_RTS
67 /*
68  * Storage manager mutex:  protects all the above state from
69  * simultaneous access by two STG threads.
70  */
71 Mutex sm_mutex;
72 #endif
73
74
75 static void
76 initStep (step *stp, int g, int s)
77 {
78     stp->no = s;
79     stp->abs_no = RtsFlags.GcFlags.steps * g + s;
80     stp->blocks = NULL;
81     stp->n_blocks = 0;
82     stp->n_words = 0;
83     stp->live_estimate = 0;
84     stp->old_blocks = NULL;
85     stp->n_old_blocks = 0;
86     stp->gen = &generations[g];
87     stp->gen_no = g;
88     stp->large_objects = NULL;
89     stp->n_large_blocks = 0;
90     stp->scavenged_large_objects = NULL;
91     stp->n_scavenged_large_blocks = 0;
92     stp->mark = 0;
93     stp->compact = 0;
94     stp->bitmap = NULL;
95 #ifdef THREADED_RTS
96     initSpinLock(&stp->sync_large_objects);
97 #endif
98     stp->threads = END_TSO_QUEUE;
99     stp->old_threads = END_TSO_QUEUE;
100 }
101
102 void
103 initStorage( void )
104 {
105   nat g, s;
106   generation *gen;
107
108   if (generations != NULL) {
109       // multi-init protection
110       return;
111   }
112
113   initMBlocks();
114
115   /* Sanity check to make sure the LOOKS_LIKE_ macros appear to be
116    * doing something reasonable.
117    */
118   /* We use the NOT_NULL variant or gcc warns that the test is always true */
119   ASSERT(LOOKS_LIKE_INFO_PTR_NOT_NULL((StgWord)&stg_BLACKHOLE_info));
120   ASSERT(LOOKS_LIKE_CLOSURE_PTR(&stg_dummy_ret_closure));
121   ASSERT(!HEAP_ALLOCED(&stg_dummy_ret_closure));
122   
123   if (RtsFlags.GcFlags.maxHeapSize != 0 &&
124       RtsFlags.GcFlags.heapSizeSuggestion > 
125       RtsFlags.GcFlags.maxHeapSize) {
126     RtsFlags.GcFlags.maxHeapSize = RtsFlags.GcFlags.heapSizeSuggestion;
127   }
128
129   if (RtsFlags.GcFlags.maxHeapSize != 0 &&
130       RtsFlags.GcFlags.minAllocAreaSize > 
131       RtsFlags.GcFlags.maxHeapSize) {
132       errorBelch("maximum heap size (-M) is smaller than minimum alloc area size (-A)");
133       RtsFlags.GcFlags.minAllocAreaSize = RtsFlags.GcFlags.maxHeapSize;
134   }
135
136   initBlockAllocator();
137   
138 #if defined(THREADED_RTS)
139   initMutex(&sm_mutex);
140 #endif
141
142   ACQUIRE_SM_LOCK;
143
144   /* allocate generation info array */
145   generations = (generation *)stgMallocBytes(RtsFlags.GcFlags.generations 
146                                              * sizeof(struct generation_),
147                                              "initStorage: gens");
148
149   /* allocate all the steps into an array.  It is important that we do
150      it this way, because we need the invariant that two step pointers
151      can be directly compared to see which is the oldest.
152      Remember that the last generation has only one step. */
153   total_steps = 1 + (RtsFlags.GcFlags.generations - 1) * RtsFlags.GcFlags.steps;
154   all_steps   = stgMallocBytes(total_steps * sizeof(struct step_),
155                                "initStorage: steps");
156
157   /* Initialise all generations */
158   for(g = 0; g < RtsFlags.GcFlags.generations; g++) {
159     gen = &generations[g];
160     gen->no = g;
161     gen->mut_list = allocBlock();
162     gen->collections = 0;
163     gen->par_collections = 0;
164     gen->failed_promotions = 0;
165     gen->max_blocks = 0;
166   }
167
168   /* A couple of convenience pointers */
169   g0 = &generations[0];
170   oldest_gen = &generations[RtsFlags.GcFlags.generations-1];
171
172   /* Allocate step structures in each generation */
173   if (RtsFlags.GcFlags.generations > 1) {
174     /* Only for multiple-generations */
175
176     /* Oldest generation: one step */
177     oldest_gen->n_steps = 1;
178     oldest_gen->steps   = all_steps + (RtsFlags.GcFlags.generations - 1)
179                                       * RtsFlags.GcFlags.steps;
180
181     /* set up all except the oldest generation with 2 steps */
182     for(g = 0; g < RtsFlags.GcFlags.generations-1; g++) {
183       generations[g].n_steps = RtsFlags.GcFlags.steps;
184       generations[g].steps   = all_steps + g * RtsFlags.GcFlags.steps;
185     }
186     
187   } else {
188     /* single generation, i.e. a two-space collector */
189     g0->n_steps = 1;
190     g0->steps   = all_steps;
191   }
192
193 #ifdef THREADED_RTS
194   n_nurseries = n_capabilities;
195 #else
196   n_nurseries = 1;
197 #endif
198   nurseries = stgMallocBytes (n_nurseries * sizeof(struct step_),
199                               "initStorage: nurseries");
200
201   /* Initialise all steps */
202   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
203     for (s = 0; s < generations[g].n_steps; s++) {
204         initStep(&generations[g].steps[s], g, s);
205     }
206   }
207   
208   for (s = 0; s < n_nurseries; s++) {
209       initStep(&nurseries[s], 0, s);
210   }
211   
212   /* Set up the destination pointers in each younger gen. step */
213   for (g = 0; g < RtsFlags.GcFlags.generations-1; g++) {
214     for (s = 0; s < generations[g].n_steps-1; s++) {
215       generations[g].steps[s].to = &generations[g].steps[s+1];
216     }
217     generations[g].steps[s].to = &generations[g+1].steps[0];
218   }
219   oldest_gen->steps[0].to = &oldest_gen->steps[0];
220   
221   for (s = 0; s < n_nurseries; s++) {
222       nurseries[s].to = generations[0].steps[0].to;
223   }
224   
225   /* The oldest generation has one step. */
226   if (RtsFlags.GcFlags.compact || RtsFlags.GcFlags.sweep) {
227       if (RtsFlags.GcFlags.generations == 1) {
228           errorBelch("WARNING: compact/sweep is incompatible with -G1; disabled");
229       } else {
230           oldest_gen->steps[0].mark = 1;
231           if (RtsFlags.GcFlags.compact)
232               oldest_gen->steps[0].compact = 1;
233       }
234   }
235
236   generations[0].max_blocks = 0;
237   g0s0 = &generations[0].steps[0];
238
239   /* The allocation area.  Policy: keep the allocation area
240    * small to begin with, even if we have a large suggested heap
241    * size.  Reason: we're going to do a major collection first, and we
242    * don't want it to be a big one.  This vague idea is borne out by 
243    * rigorous experimental evidence.
244    */
245   allocNurseries();
246
247   weak_ptr_list = NULL;
248   caf_list = NULL;
249   revertible_caf_list = NULL;
250    
251   /* initialise the allocate() interface */
252   alloc_blocks = 0;
253   alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize;
254
255   exec_block = NULL;
256
257 #ifdef THREADED_RTS
258   initSpinLock(&gc_alloc_block_sync);
259   whitehole_spin = 0;
260 #endif
261
262   N = 0;
263
264   initGcThreads();
265
266   IF_DEBUG(gc, statDescribeGens());
267
268   RELEASE_SM_LOCK;
269 }
270
271 void
272 exitStorage (void)
273 {
274     stat_exit(calcAllocated());
275 }
276
277 void
278 freeStorage (void)
279 {
280     stgFree(g0s0); // frees all the steps
281     stgFree(generations);
282     freeAllMBlocks();
283 #if defined(THREADED_RTS)
284     closeMutex(&sm_mutex);
285 #endif
286     stgFree(nurseries);
287     freeGcThreads();
288 }
289
290 /* -----------------------------------------------------------------------------
291    CAF management.
292
293    The entry code for every CAF does the following:
294      
295       - builds a CAF_BLACKHOLE in the heap
296       - pushes an update frame pointing to the CAF_BLACKHOLE
297       - invokes UPD_CAF(), which:
298           - calls newCaf, below
299           - updates the CAF with a static indirection to the CAF_BLACKHOLE
300       
301    Why do we build a BLACKHOLE in the heap rather than just updating
302    the thunk directly?  It's so that we only need one kind of update
303    frame - otherwise we'd need a static version of the update frame too.
304
305    newCaf() does the following:
306        
307       - it puts the CAF on the oldest generation's mut-once list.
308         This is so that we can treat the CAF as a root when collecting
309         younger generations.
310
311    For GHCI, we have additional requirements when dealing with CAFs:
312
313       - we must *retain* all dynamically-loaded CAFs ever entered,
314         just in case we need them again.
315       - we must be able to *revert* CAFs that have been evaluated, to
316         their pre-evaluated form.
317
318       To do this, we use an additional CAF list.  When newCaf() is
319       called on a dynamically-loaded CAF, we add it to the CAF list
320       instead of the old-generation mutable list, and save away its
321       old info pointer (in caf->saved_info) for later reversion.
322
323       To revert all the CAFs, we traverse the CAF list and reset the
324       info pointer to caf->saved_info, then throw away the CAF list.
325       (see GC.c:revertCAFs()).
326
327       -- SDM 29/1/01
328
329    -------------------------------------------------------------------------- */
330
331 void
332 newCAF(StgClosure* caf)
333 {
334   ACQUIRE_SM_LOCK;
335
336   if(keepCAFs)
337   {
338     // HACK:
339     // If we are in GHCi _and_ we are using dynamic libraries,
340     // then we can't redirect newCAF calls to newDynCAF (see below),
341     // so we make newCAF behave almost like newDynCAF.
342     // The dynamic libraries might be used by both the interpreted
343     // program and GHCi itself, so they must not be reverted.
344     // This also means that in GHCi with dynamic libraries, CAFs are not
345     // garbage collected. If this turns out to be a problem, we could
346     // do another hack here and do an address range test on caf to figure
347     // out whether it is from a dynamic library.
348     ((StgIndStatic *)caf)->saved_info  = (StgInfoTable *)caf->header.info;
349     ((StgIndStatic *)caf)->static_link = caf_list;
350     caf_list = caf;
351   }
352   else
353   {
354     /* Put this CAF on the mutable list for the old generation.
355     * This is a HACK - the IND_STATIC closure doesn't really have
356     * a mut_link field, but we pretend it has - in fact we re-use
357     * the STATIC_LINK field for the time being, because when we
358     * come to do a major GC we won't need the mut_link field
359     * any more and can use it as a STATIC_LINK.
360     */
361     ((StgIndStatic *)caf)->saved_info = NULL;
362     recordMutableGen(caf, oldest_gen->no);
363   }
364   
365   RELEASE_SM_LOCK;
366 }
367
368 // An alternate version of newCaf which is used for dynamically loaded
369 // object code in GHCi.  In this case we want to retain *all* CAFs in
370 // the object code, because they might be demanded at any time from an
371 // expression evaluated on the command line.
372 // Also, GHCi might want to revert CAFs, so we add these to the
373 // revertible_caf_list.
374 //
375 // The linker hackily arranges that references to newCaf from dynamic
376 // code end up pointing to newDynCAF.
377 void
378 newDynCAF(StgClosure *caf)
379 {
380     ACQUIRE_SM_LOCK;
381
382     ((StgIndStatic *)caf)->saved_info  = (StgInfoTable *)caf->header.info;
383     ((StgIndStatic *)caf)->static_link = revertible_caf_list;
384     revertible_caf_list = caf;
385
386     RELEASE_SM_LOCK;
387 }
388
389 /* -----------------------------------------------------------------------------
390    Nursery management.
391    -------------------------------------------------------------------------- */
392
393 static bdescr *
394 allocNursery (step *stp, 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 = stp;
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 static void
426 assignNurseriesToCapabilities (void)
427 {
428 #ifdef THREADED_RTS
429     nat i;
430
431     for (i = 0; i < n_nurseries; i++) {
432         capabilities[i].r.rNursery        = &nurseries[i];
433         capabilities[i].r.rCurrentNursery = nurseries[i].blocks;
434         capabilities[i].r.rCurrentAlloc   = NULL;
435     }
436 #else /* THREADED_RTS */
437     MainCapability.r.rNursery        = &nurseries[0];
438     MainCapability.r.rCurrentNursery = nurseries[0].blocks;
439     MainCapability.r.rCurrentAlloc   = NULL;
440 #endif
441 }
442
443 void
444 allocNurseries( void )
445
446     nat i;
447
448     for (i = 0; i < n_nurseries; i++) {
449         nurseries[i].blocks = 
450             allocNursery(&nurseries[i], NULL, 
451                          RtsFlags.GcFlags.minAllocAreaSize);
452         nurseries[i].n_blocks    = RtsFlags.GcFlags.minAllocAreaSize;
453         nurseries[i].old_blocks   = NULL;
454         nurseries[i].n_old_blocks = 0;
455     }
456     assignNurseriesToCapabilities();
457 }
458       
459 void
460 resetNurseries( void )
461 {
462     nat i;
463     bdescr *bd;
464     step *stp;
465
466     for (i = 0; i < n_nurseries; i++) {
467         stp = &nurseries[i];
468         for (bd = stp->blocks; bd; bd = bd->link) {
469             bd->free = bd->start;
470             ASSERT(bd->gen_no == 0);
471             ASSERT(bd->step == stp);
472             IF_DEBUG(sanity,memset(bd->start, 0xaa, BLOCK_SIZE));
473         }
474     }
475     assignNurseriesToCapabilities();
476 }
477
478 lnat
479 countNurseryBlocks (void)
480 {
481     nat i;
482     lnat blocks = 0;
483
484     for (i = 0; i < n_nurseries; i++) {
485         blocks += nurseries[i].n_blocks;
486     }
487     return blocks;
488 }
489
490 static void
491 resizeNursery ( step *stp, nat blocks )
492 {
493   bdescr *bd;
494   nat nursery_blocks;
495
496   nursery_blocks = stp->n_blocks;
497   if (nursery_blocks == blocks) return;
498
499   if (nursery_blocks < blocks) {
500       debugTrace(DEBUG_gc, "increasing size of nursery to %d blocks", 
501                  blocks);
502     stp->blocks = allocNursery(stp, stp->blocks, blocks-nursery_blocks);
503   } 
504   else {
505     bdescr *next_bd;
506     
507     debugTrace(DEBUG_gc, "decreasing size of nursery to %d blocks", 
508                blocks);
509
510     bd = stp->blocks;
511     while (nursery_blocks > blocks) {
512         next_bd = bd->link;
513         next_bd->u.back = NULL;
514         nursery_blocks -= bd->blocks; // might be a large block
515         freeGroup(bd);
516         bd = next_bd;
517     }
518     stp->blocks = bd;
519     // might have gone just under, by freeing a large block, so make
520     // up the difference.
521     if (nursery_blocks < blocks) {
522         stp->blocks = allocNursery(stp, stp->blocks, blocks-nursery_blocks);
523     }
524   }
525   
526   stp->n_blocks = blocks;
527   ASSERT(countBlocks(stp->blocks) == stp->n_blocks);
528 }
529
530 // 
531 // Resize each of the nurseries to the specified size.
532 //
533 void
534 resizeNurseriesFixed (nat blocks)
535 {
536     nat i;
537     for (i = 0; i < n_nurseries; i++) {
538         resizeNursery(&nurseries[i], blocks);
539     }
540 }
541
542 // 
543 // Resize the nurseries to the total specified size.
544 //
545 void
546 resizeNurseries (nat blocks)
547 {
548     // If there are multiple nurseries, then we just divide the number
549     // of available blocks between them.
550     resizeNurseriesFixed(blocks / n_nurseries);
551 }
552
553
554 /* -----------------------------------------------------------------------------
555    move_TSO is called to update the TSO structure after it has been
556    moved from one place to another.
557    -------------------------------------------------------------------------- */
558
559 void
560 move_TSO (StgTSO *src, StgTSO *dest)
561 {
562     ptrdiff_t diff;
563
564     // relocate the stack pointer... 
565     diff = (StgPtr)dest - (StgPtr)src; // In *words* 
566     dest->sp = (StgPtr)dest->sp + diff;
567 }
568
569 /* -----------------------------------------------------------------------------
570    The allocate() interface
571
572    allocateInGen() function allocates memory directly into a specific
573    generation.  It always succeeds, and returns a chunk of memory n
574    words long.  n can be larger than the size of a block if necessary,
575    in which case a contiguous block group will be allocated.
576
577    allocate(n) is equivalent to allocateInGen(g0).
578    -------------------------------------------------------------------------- */
579
580 StgPtr
581 allocateInGen (generation *g, lnat n)
582 {
583     step *stp;
584     bdescr *bd;
585     StgPtr ret;
586
587     ACQUIRE_SM_LOCK;
588     
589     TICK_ALLOC_HEAP_NOCTR(n);
590     CCS_ALLOC(CCCS,n);
591
592     stp = &g->steps[0];
593
594     if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_))
595     {
596         lnat req_blocks =  (lnat)BLOCK_ROUND_UP(n*sizeof(W_)) / BLOCK_SIZE;
597
598         // Attempting to allocate an object larger than maxHeapSize
599         // should definitely be disallowed.  (bug #1791)
600         if (RtsFlags.GcFlags.maxHeapSize > 0 && 
601             req_blocks >= RtsFlags.GcFlags.maxHeapSize) {
602             heapOverflow();
603             // heapOverflow() doesn't exit (see #2592), but we aren't
604             // in a position to do a clean shutdown here: we
605             // either have to allocate the memory or exit now.
606             // Allocating the memory would be bad, because the user
607             // has requested that we not exceed maxHeapSize, so we
608             // just exit.
609             stg_exit(EXIT_HEAPOVERFLOW);
610         }
611
612         bd = allocGroup(req_blocks);
613         dbl_link_onto(bd, &stp->large_objects);
614         stp->n_large_blocks += bd->blocks; // might be larger than req_blocks
615         alloc_blocks += bd->blocks;
616         bd->gen_no  = g->no;
617         bd->step = stp;
618         bd->flags = BF_LARGE;
619         bd->free = bd->start + n;
620         ret = bd->start;
621     }
622     else
623     {
624         // small allocation (<LARGE_OBJECT_THRESHOLD) */
625         bd = stp->blocks;
626         if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) {
627             bd = allocBlock();
628             bd->gen_no = g->no;
629             bd->step = stp;
630             bd->flags = 0;
631             bd->link = stp->blocks;
632             stp->blocks = bd;
633             stp->n_blocks++;
634             alloc_blocks++;
635         }
636         ret = bd->free;
637         bd->free += n;
638     }
639
640     RELEASE_SM_LOCK;
641
642     return ret;
643 }
644
645 StgPtr
646 allocate (lnat n)
647 {
648     return allocateInGen(g0,n);
649 }
650
651 lnat
652 allocatedBytes( void )
653 {
654     lnat allocated;
655
656     allocated = alloc_blocks * BLOCK_SIZE_W;
657     if (pinned_object_block != NULL) {
658         allocated -= (pinned_object_block->start + BLOCK_SIZE_W) - 
659             pinned_object_block->free;
660     }
661         
662     return allocated;
663 }
664
665 // split N blocks off the front of the given bdescr, returning the
666 // new block group.  We treat the remainder as if it
667 // had been freshly allocated in generation 0.
668 bdescr *
669 splitLargeBlock (bdescr *bd, nat blocks)
670 {
671     bdescr *new_bd;
672
673     // subtract the original number of blocks from the counter first
674     bd->step->n_large_blocks -= bd->blocks;
675
676     new_bd = splitBlockGroup (bd, blocks);
677
678     dbl_link_onto(new_bd, &g0s0->large_objects);
679     g0s0->n_large_blocks += new_bd->blocks;
680     new_bd->gen_no  = g0s0->no;
681     new_bd->step    = g0s0;
682     new_bd->flags   = BF_LARGE;
683     new_bd->free    = bd->free;
684     ASSERT(new_bd->free <= new_bd->start + new_bd->blocks * BLOCK_SIZE_W);
685
686     // add the new number of blocks to the counter.  Due to the gaps
687     // for block descriptor, new_bd->blocks + bd->blocks might not be
688     // equal to the original bd->blocks, which is why we do it this way.
689     bd->step->n_large_blocks += bd->blocks;
690
691     return new_bd;
692 }
693
694 /* -----------------------------------------------------------------------------
695    allocateLocal()
696
697    This allocates memory in the current thread - it is intended for
698    use primarily from STG-land where we have a Capability.  It is
699    better than allocate() because it doesn't require taking the
700    sm_mutex lock in the common case.
701
702    Memory is allocated directly from the nursery if possible (but not
703    from the current nursery block, so as not to interfere with
704    Hp/HpLim).
705    -------------------------------------------------------------------------- */
706
707 StgPtr
708 allocateLocal (Capability *cap, lnat n)
709 {
710     bdescr *bd;
711     StgPtr p;
712
713     if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
714         return allocateInGen(g0,n);
715     }
716
717     /* small allocation (<LARGE_OBJECT_THRESHOLD) */
718
719     TICK_ALLOC_HEAP_NOCTR(n);
720     CCS_ALLOC(CCCS,n);
721     
722     bd = cap->r.rCurrentAlloc;
723     if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) {
724         
725         // The CurrentAlloc block is full, we need to find another
726         // one.  First, we try taking the next block from the
727         // nursery:
728         bd = cap->r.rCurrentNursery->link;
729         
730         if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) {
731             // The nursery is empty, or the next block is already
732             // full: allocate a fresh block (we can't fail here).
733             ACQUIRE_SM_LOCK;
734             bd = allocBlock();
735             cap->r.rNursery->n_blocks++;
736             RELEASE_SM_LOCK;
737             bd->gen_no = 0;
738             bd->step = cap->r.rNursery;
739             bd->flags = 0;
740             // NO: alloc_blocks++;
741             // calcAllocated() uses the size of the nursery, and we've
742             // already bumpted nursery->n_blocks above.  We'll GC
743             // pretty quickly now anyway, because MAYBE_GC() will
744             // notice that CurrentNursery->link is NULL.
745         } else {
746             // we have a block in the nursery: take it and put
747             // it at the *front* of the nursery list, and use it
748             // to allocate() from.
749             cap->r.rCurrentNursery->link = bd->link;
750             if (bd->link != NULL) {
751                 bd->link->u.back = cap->r.rCurrentNursery;
752             }
753         }
754         dbl_link_onto(bd, &cap->r.rNursery->blocks);
755         cap->r.rCurrentAlloc = bd;
756         IF_DEBUG(sanity, checkNurserySanity(cap->r.rNursery));
757     }
758     p = bd->free;
759     bd->free += n;
760     return p;
761 }
762
763 /* ---------------------------------------------------------------------------
764    Allocate a fixed/pinned object.
765
766    We allocate small pinned objects into a single block, allocating a
767    new block when the current one overflows.  The block is chained
768    onto the large_object_list of generation 0 step 0.
769
770    NOTE: The GC can't in general handle pinned objects.  This
771    interface is only safe to use for ByteArrays, which have no
772    pointers and don't require scavenging.  It works because the
773    block's descriptor has the BF_LARGE flag set, so the block is
774    treated as a large object and chained onto various lists, rather
775    than the individual objects being copied.  However, when it comes
776    to scavenge the block, the GC will only scavenge the first object.
777    The reason is that the GC can't linearly scan a block of pinned
778    objects at the moment (doing so would require using the
779    mostly-copying techniques).  But since we're restricting ourselves
780    to pinned ByteArrays, not scavenging is ok.
781
782    This function is called by newPinnedByteArray# which immediately
783    fills the allocated memory with a MutableByteArray#.
784    ------------------------------------------------------------------------- */
785
786 StgPtr
787 allocatePinned( lnat n )
788 {
789     StgPtr p;
790     bdescr *bd = pinned_object_block;
791
792     // If the request is for a large object, then allocate()
793     // will give us a pinned object anyway.
794     if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
795         p = allocate(n);
796         Bdescr(p)->flags |= BF_PINNED;
797         return p;
798     }
799
800     ACQUIRE_SM_LOCK;
801     
802     TICK_ALLOC_HEAP_NOCTR(n);
803     CCS_ALLOC(CCCS,n);
804
805     // If we don't have a block of pinned objects yet, or the current
806     // one isn't large enough to hold the new object, allocate a new one.
807     if (bd == NULL || (bd->free + n) > (bd->start + BLOCK_SIZE_W)) {
808         pinned_object_block = bd = allocBlock();
809         dbl_link_onto(bd, &g0s0->large_objects);
810         g0s0->n_large_blocks++;
811         bd->gen_no = 0;
812         bd->step   = g0s0;
813         bd->flags  = BF_PINNED | BF_LARGE;
814         bd->free   = bd->start;
815         alloc_blocks++;
816     }
817
818     p = bd->free;
819     bd->free += n;
820     RELEASE_SM_LOCK;
821     return p;
822 }
823
824 /* -----------------------------------------------------------------------------
825    Write Barriers
826    -------------------------------------------------------------------------- */
827
828 /*
829    This is the write barrier for MUT_VARs, a.k.a. IORefs.  A
830    MUT_VAR_CLEAN object is not on the mutable list; a MUT_VAR_DIRTY
831    is.  When written to, a MUT_VAR_CLEAN turns into a MUT_VAR_DIRTY
832    and is put on the mutable list.
833 */
834 void
835 dirty_MUT_VAR(StgRegTable *reg, StgClosure *p)
836 {
837     Capability *cap = regTableToCapability(reg);
838     bdescr *bd;
839     if (p->header.info == &stg_MUT_VAR_CLEAN_info) {
840         p->header.info = &stg_MUT_VAR_DIRTY_info;
841         bd = Bdescr((StgPtr)p);
842         if (bd->gen_no > 0) recordMutableCap(p,cap,bd->gen_no);
843     }
844 }
845
846 // Setting a TSO's link field with a write barrier.
847 // It is *not* necessary to call this function when
848 //    * setting the link field to END_TSO_QUEUE
849 //    * putting a TSO on the blackhole_queue
850 //    * setting the link field of the currently running TSO, as it
851 //      will already be dirty.
852 void
853 setTSOLink (Capability *cap, StgTSO *tso, StgTSO *target)
854 {
855     bdescr *bd;
856     if ((tso->flags & (TSO_DIRTY|TSO_LINK_DIRTY)) == 0) {
857         tso->flags |= TSO_LINK_DIRTY;
858         bd = Bdescr((StgPtr)tso);
859         if (bd->gen_no > 0) recordMutableCap((StgClosure*)tso,cap,bd->gen_no);
860     }
861     tso->_link = target;
862 }
863
864 void
865 dirty_TSO (Capability *cap, StgTSO *tso)
866 {
867     bdescr *bd;
868     if ((tso->flags & (TSO_DIRTY|TSO_LINK_DIRTY)) == 0) {
869         bd = Bdescr((StgPtr)tso);
870         if (bd->gen_no > 0) recordMutableCap((StgClosure*)tso,cap,bd->gen_no);
871     }
872     tso->flags |= TSO_DIRTY;
873 }
874
875 /*
876    This is the write barrier for MVARs.  An MVAR_CLEAN objects is not
877    on the mutable list; a MVAR_DIRTY is.  When written to, a
878    MVAR_CLEAN turns into a MVAR_DIRTY and is put on the mutable list.
879    The check for MVAR_CLEAN is inlined at the call site for speed,
880    this really does make a difference on concurrency-heavy benchmarks
881    such as Chaneneos and cheap-concurrency.
882 */
883 void
884 dirty_MVAR(StgRegTable *reg, StgClosure *p)
885 {
886     Capability *cap = regTableToCapability(reg);
887     bdescr *bd;
888     bd = Bdescr((StgPtr)p);
889     if (bd->gen_no > 0) recordMutableCap(p,cap,bd->gen_no);
890 }
891
892 /* -----------------------------------------------------------------------------
893  * Stats and stuff
894  * -------------------------------------------------------------------------- */
895
896 /* -----------------------------------------------------------------------------
897  * calcAllocated()
898  *
899  * Approximate how much we've allocated: number of blocks in the
900  * nursery + blocks allocated via allocate() - unused nusery blocks.
901  * This leaves a little slop at the end of each block, and doesn't
902  * take into account large objects (ToDo).
903  * -------------------------------------------------------------------------- */
904
905 lnat
906 calcAllocated( void )
907 {
908   nat allocated;
909   bdescr *bd;
910
911   allocated = allocatedBytes();
912   allocated += countNurseryBlocks() * BLOCK_SIZE_W;
913   
914   {
915 #ifdef THREADED_RTS
916   nat i;
917   for (i = 0; i < n_nurseries; i++) {
918       Capability *cap;
919       for ( bd = capabilities[i].r.rCurrentNursery->link; 
920             bd != NULL; bd = bd->link ) {
921           allocated -= BLOCK_SIZE_W;
922       }
923       cap = &capabilities[i];
924       if (cap->r.rCurrentNursery->free < 
925           cap->r.rCurrentNursery->start + BLOCK_SIZE_W) {
926           allocated -= (cap->r.rCurrentNursery->start + BLOCK_SIZE_W)
927               - cap->r.rCurrentNursery->free;
928       }
929   }
930 #else
931   bdescr *current_nursery = MainCapability.r.rCurrentNursery;
932
933   for ( bd = current_nursery->link; bd != NULL; bd = bd->link ) {
934       allocated -= BLOCK_SIZE_W;
935   }
936   if (current_nursery->free < current_nursery->start + BLOCK_SIZE_W) {
937       allocated -= (current_nursery->start + BLOCK_SIZE_W)
938           - current_nursery->free;
939   }
940 #endif
941   }
942
943   total_allocated += allocated;
944   return allocated;
945 }  
946
947 /* Approximate the amount of live data in the heap.  To be called just
948  * after garbage collection (see GarbageCollect()).
949  */
950 lnat 
951 calcLiveBlocks(void)
952 {
953   nat g, s;
954   lnat live = 0;
955   step *stp;
956
957   if (RtsFlags.GcFlags.generations == 1) {
958       return g0s0->n_large_blocks + g0s0->n_blocks;
959   }
960
961   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
962     for (s = 0; s < generations[g].n_steps; s++) {
963       /* approximate amount of live data (doesn't take into account slop
964        * at end of each block).
965        */
966       if (g == 0 && s == 0) { 
967           continue; 
968       }
969       stp = &generations[g].steps[s];
970       live += stp->n_large_blocks + stp->n_blocks;
971     }
972   }
973   return live;
974 }
975
976 lnat
977 countOccupied(bdescr *bd)
978 {
979     lnat words;
980
981     words = 0;
982     for (; bd != NULL; bd = bd->link) {
983         ASSERT(bd->free <= bd->start + bd->blocks * BLOCK_SIZE_W);
984         words += bd->free - bd->start;
985     }
986     return words;
987 }
988
989 // Return an accurate count of the live data in the heap, excluding
990 // generation 0.
991 lnat
992 calcLiveWords(void)
993 {
994     nat g, s;
995     lnat live;
996     step *stp;
997     
998     if (RtsFlags.GcFlags.generations == 1) {
999         return g0s0->n_words + countOccupied(g0s0->large_objects);
1000     }
1001     
1002     live = 0;
1003     for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1004         for (s = 0; s < generations[g].n_steps; s++) {
1005             if (g == 0 && s == 0) continue; 
1006             stp = &generations[g].steps[s];
1007             live += stp->n_words + countOccupied(stp->large_objects);
1008         } 
1009     }
1010     return live;
1011 }
1012
1013 /* Approximate the number of blocks that will be needed at the next
1014  * garbage collection.
1015  *
1016  * Assume: all data currently live will remain live.  Steps that will
1017  * be collected next time will therefore need twice as many blocks
1018  * since all the data will be copied.
1019  */
1020 extern lnat 
1021 calcNeeded(void)
1022 {
1023     lnat needed = 0;
1024     nat g, s;
1025     step *stp;
1026     
1027     for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1028         for (s = 0; s < generations[g].n_steps; s++) {
1029             if (g == 0 && s == 0) { continue; }
1030             stp = &generations[g].steps[s];
1031
1032             // we need at least this much space
1033             needed += stp->n_blocks + stp->n_large_blocks;
1034
1035             // any additional space needed to collect this gen next time?
1036             if (g == 0 || // always collect gen 0
1037                 (generations[g].steps[0].n_blocks +
1038                  generations[g].steps[0].n_large_blocks 
1039                  > generations[g].max_blocks)) {
1040                 // we will collect this gen next time
1041                 if (stp->mark) {
1042                     //  bitmap:
1043                     needed += stp->n_blocks / BITS_IN(W_);
1044                     //  mark stack:
1045                     needed += stp->n_blocks / 100;
1046                 }
1047                 if (stp->compact) {
1048                     continue; // no additional space needed for compaction
1049                 } else {
1050                     needed += stp->n_blocks;
1051                 }
1052             }
1053         }
1054     }
1055     return needed;
1056 }
1057
1058 /* ----------------------------------------------------------------------------
1059    Executable memory
1060
1061    Executable memory must be managed separately from non-executable
1062    memory.  Most OSs these days require you to jump through hoops to
1063    dynamically allocate executable memory, due to various security
1064    measures.
1065
1066    Here we provide a small memory allocator for executable memory.
1067    Memory is managed with a page granularity; we allocate linearly
1068    in the page, and when the page is emptied (all objects on the page
1069    are free) we free the page again, not forgetting to make it
1070    non-executable.
1071
1072    TODO: The inability to handle objects bigger than BLOCK_SIZE_W means that
1073          the linker cannot use allocateExec for loading object code files
1074          on Windows. Once allocateExec can handle larger objects, the linker
1075          should be modified to use allocateExec instead of VirtualAlloc.
1076    ------------------------------------------------------------------------- */
1077
1078 #if defined(linux_HOST_OS)
1079
1080 // On Linux we need to use libffi for allocating executable memory,
1081 // because it knows how to work around the restrictions put in place
1082 // by SELinux.
1083
1084 void *allocateExec (nat bytes, void **exec_ret)
1085 {
1086     void **ret, **exec;
1087     ACQUIRE_SM_LOCK;
1088     ret = ffi_closure_alloc (sizeof(void *) + (size_t)bytes, (void**)&exec);
1089     RELEASE_SM_LOCK;
1090     if (ret == NULL) return ret;
1091     *ret = ret; // save the address of the writable mapping, for freeExec().
1092     *exec_ret = exec + 1;
1093     return (ret + 1);
1094 }
1095
1096 // freeExec gets passed the executable address, not the writable address. 
1097 void freeExec (void *addr)
1098 {
1099     void *writable;
1100     writable = *((void**)addr - 1);
1101     ACQUIRE_SM_LOCK;
1102     ffi_closure_free (writable);
1103     RELEASE_SM_LOCK
1104 }
1105
1106 #else
1107
1108 void *allocateExec (nat bytes, void **exec_ret)
1109 {
1110     void *ret;
1111     nat n;
1112
1113     ACQUIRE_SM_LOCK;
1114
1115     // round up to words.
1116     n  = (bytes + sizeof(W_) + 1) / sizeof(W_);
1117
1118     if (n+1 > BLOCK_SIZE_W) {
1119         barf("allocateExec: can't handle large objects");
1120     }
1121
1122     if (exec_block == NULL || 
1123         exec_block->free + n + 1 > exec_block->start + BLOCK_SIZE_W) {
1124         bdescr *bd;
1125         lnat pagesize = getPageSize();
1126         bd = allocGroup(stg_max(1, pagesize / BLOCK_SIZE));
1127         debugTrace(DEBUG_gc, "allocate exec block %p", bd->start);
1128         bd->gen_no = 0;
1129         bd->flags = BF_EXEC;
1130         bd->link = exec_block;
1131         if (exec_block != NULL) {
1132             exec_block->u.back = bd;
1133         }
1134         bd->u.back = NULL;
1135         setExecutable(bd->start, bd->blocks * BLOCK_SIZE, rtsTrue);
1136         exec_block = bd;
1137     }
1138     *(exec_block->free) = n;  // store the size of this chunk
1139     exec_block->gen_no += n;  // gen_no stores the number of words allocated
1140     ret = exec_block->free + 1;
1141     exec_block->free += n + 1;
1142
1143     RELEASE_SM_LOCK
1144     *exec_ret = ret;
1145     return ret;
1146 }
1147
1148 void freeExec (void *addr)
1149 {
1150     StgPtr p = (StgPtr)addr - 1;
1151     bdescr *bd = Bdescr((StgPtr)p);
1152
1153     if ((bd->flags & BF_EXEC) == 0) {
1154         barf("freeExec: not executable");
1155     }
1156
1157     if (*(StgPtr)p == 0) {
1158         barf("freeExec: already free?");
1159     }
1160
1161     ACQUIRE_SM_LOCK;
1162
1163     bd->gen_no -= *(StgPtr)p;
1164     *(StgPtr)p = 0;
1165
1166     if (bd->gen_no == 0) {
1167         // Free the block if it is empty, but not if it is the block at
1168         // the head of the queue.
1169         if (bd != exec_block) {
1170             debugTrace(DEBUG_gc, "free exec block %p", bd->start);
1171             dbl_link_remove(bd, &exec_block);
1172             setExecutable(bd->start, bd->blocks * BLOCK_SIZE, rtsFalse);
1173             freeGroup(bd);
1174         } else {
1175             bd->free = bd->start;
1176         }
1177     }
1178
1179     RELEASE_SM_LOCK
1180 }    
1181
1182 #endif /* mingw32_HOST_OS */
1183
1184 /* -----------------------------------------------------------------------------
1185    Debugging
1186
1187    memInventory() checks for memory leaks by counting up all the
1188    blocks we know about and comparing that to the number of blocks
1189    allegedly floating around in the system.
1190    -------------------------------------------------------------------------- */
1191
1192 #ifdef DEBUG
1193
1194 // Useful for finding partially full blocks in gdb
1195 void findSlop(bdescr *bd);
1196 void findSlop(bdescr *bd)
1197 {
1198     lnat slop;
1199
1200     for (; bd != NULL; bd = bd->link) {
1201         slop = (bd->blocks * BLOCK_SIZE_W) - (bd->free - bd->start);
1202         if (slop > (1024/sizeof(W_))) {
1203             debugBelch("block at %p (bdescr %p) has %ldKB slop\n",
1204                        bd->start, bd, slop / (1024/sizeof(W_)));
1205         }
1206     }
1207 }
1208
1209 nat
1210 countBlocks(bdescr *bd)
1211 {
1212     nat n;
1213     for (n=0; bd != NULL; bd=bd->link) {
1214         n += bd->blocks;
1215     }
1216     return n;
1217 }
1218
1219 // (*1) Just like countBlocks, except that we adjust the count for a
1220 // megablock group so that it doesn't include the extra few blocks
1221 // that would be taken up by block descriptors in the second and
1222 // subsequent megablock.  This is so we can tally the count with the
1223 // number of blocks allocated in the system, for memInventory().
1224 static nat
1225 countAllocdBlocks(bdescr *bd)
1226 {
1227     nat n;
1228     for (n=0; bd != NULL; bd=bd->link) {
1229         n += bd->blocks;
1230         // hack for megablock groups: see (*1) above
1231         if (bd->blocks > BLOCKS_PER_MBLOCK) {
1232             n -= (MBLOCK_SIZE / BLOCK_SIZE - BLOCKS_PER_MBLOCK)
1233                 * (bd->blocks/(MBLOCK_SIZE/BLOCK_SIZE));
1234         }
1235     }
1236     return n;
1237 }
1238
1239 static lnat
1240 stepBlocks (step *stp)
1241 {
1242     ASSERT(countBlocks(stp->blocks) == stp->n_blocks);
1243     ASSERT(countBlocks(stp->large_objects) == stp->n_large_blocks);
1244     return stp->n_blocks + stp->n_old_blocks + 
1245             countAllocdBlocks(stp->large_objects);
1246 }
1247
1248 // If memInventory() calculates that we have a memory leak, this
1249 // function will try to find the block(s) that are leaking by marking
1250 // all the ones that we know about, and search through memory to find
1251 // blocks that are not marked.  In the debugger this can help to give
1252 // us a clue about what kind of block leaked.  In the future we might
1253 // annotate blocks with their allocation site to give more helpful
1254 // info.
1255 static void
1256 findMemoryLeak (void)
1257 {
1258   nat g, s, i;
1259   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1260       for (i = 0; i < n_capabilities; i++) {
1261           markBlocks(capabilities[i].mut_lists[g]);
1262       }
1263       markBlocks(generations[g].mut_list);
1264       for (s = 0; s < generations[g].n_steps; s++) {
1265           markBlocks(generations[g].steps[s].blocks);
1266           markBlocks(generations[g].steps[s].large_objects);
1267       }
1268   }
1269
1270   for (i = 0; i < n_nurseries; i++) {
1271       markBlocks(nurseries[i].blocks);
1272       markBlocks(nurseries[i].large_objects);
1273   }
1274
1275 #ifdef PROFILING
1276   // TODO:
1277   // if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_RETAINER) {
1278   //    markRetainerBlocks();
1279   // }
1280 #endif
1281
1282   // count the blocks allocated by the arena allocator
1283   // TODO:
1284   // markArenaBlocks();
1285
1286   // count the blocks containing executable memory
1287   markBlocks(exec_block);
1288
1289   reportUnmarkedBlocks();
1290 }
1291
1292
1293 void
1294 memInventory (rtsBool show)
1295 {
1296   nat g, s, i;
1297   step *stp;
1298   lnat gen_blocks[RtsFlags.GcFlags.generations];
1299   lnat nursery_blocks, retainer_blocks,
1300        arena_blocks, exec_blocks;
1301   lnat live_blocks = 0, free_blocks = 0;
1302   rtsBool leak;
1303
1304   // count the blocks we current have
1305
1306   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1307       gen_blocks[g] = 0;
1308       for (i = 0; i < n_capabilities; i++) {
1309           gen_blocks[g] += countBlocks(capabilities[i].mut_lists[g]);
1310       }   
1311       gen_blocks[g] += countAllocdBlocks(generations[g].mut_list);
1312       for (s = 0; s < generations[g].n_steps; s++) {
1313           stp = &generations[g].steps[s];
1314           gen_blocks[g] += stepBlocks(stp);
1315       }
1316   }
1317
1318   nursery_blocks = 0;
1319   for (i = 0; i < n_nurseries; i++) {
1320       nursery_blocks += stepBlocks(&nurseries[i]);
1321   }
1322
1323   retainer_blocks = 0;
1324 #ifdef PROFILING
1325   if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_RETAINER) {
1326       retainer_blocks = retainerStackBlocks();
1327   }
1328 #endif
1329
1330   // count the blocks allocated by the arena allocator
1331   arena_blocks = arenaBlocks();
1332
1333   // count the blocks containing executable memory
1334   exec_blocks = countAllocdBlocks(exec_block);
1335
1336   /* count the blocks on the free list */
1337   free_blocks = countFreeList();
1338
1339   live_blocks = 0;
1340   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1341       live_blocks += gen_blocks[g];
1342   }
1343   live_blocks += nursery_blocks + 
1344                + retainer_blocks + arena_blocks + exec_blocks;
1345
1346 #define MB(n) (((n) * BLOCK_SIZE_W) / ((1024*1024)/sizeof(W_)))
1347
1348   leak = live_blocks + free_blocks != mblocks_allocated * BLOCKS_PER_MBLOCK;
1349
1350   if (show || leak)
1351   {
1352       if (leak) { 
1353           debugBelch("Memory leak detected:\n");
1354       } else {
1355           debugBelch("Memory inventory:\n");
1356       }
1357       for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1358           debugBelch("  gen %d blocks : %5lu blocks (%lu MB)\n", g, 
1359                      gen_blocks[g], MB(gen_blocks[g]));
1360       }
1361       debugBelch("  nursery      : %5lu blocks (%lu MB)\n", 
1362                  nursery_blocks, MB(nursery_blocks));
1363       debugBelch("  retainer     : %5lu blocks (%lu MB)\n", 
1364                  retainer_blocks, MB(retainer_blocks));
1365       debugBelch("  arena blocks : %5lu blocks (%lu MB)\n", 
1366                  arena_blocks, MB(arena_blocks));
1367       debugBelch("  exec         : %5lu blocks (%lu MB)\n", 
1368                  exec_blocks, MB(exec_blocks));
1369       debugBelch("  free         : %5lu blocks (%lu MB)\n", 
1370                  free_blocks, MB(free_blocks));
1371       debugBelch("  total        : %5lu blocks (%lu MB)\n",
1372                  live_blocks + free_blocks, MB(live_blocks+free_blocks));
1373       if (leak) {
1374           debugBelch("\n  in system    : %5lu blocks (%lu MB)\n", 
1375                      mblocks_allocated * BLOCKS_PER_MBLOCK, mblocks_allocated);
1376       }
1377   }
1378
1379   if (leak) {
1380       debugBelch("\n");
1381       findMemoryLeak();
1382   }
1383   ASSERT(n_alloc_blocks == live_blocks);
1384   ASSERT(!leak);
1385 }
1386
1387
1388 /* Full heap sanity check. */
1389 void
1390 checkSanity( void )
1391 {
1392     nat g, s;
1393
1394     if (RtsFlags.GcFlags.generations == 1) {
1395         checkHeap(g0s0->blocks);
1396         checkLargeObjects(g0s0->large_objects);
1397     } else {
1398         
1399         for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1400             for (s = 0; s < generations[g].n_steps; s++) {
1401                 if (g == 0 && s == 0) { continue; }
1402                 ASSERT(countBlocks(generations[g].steps[s].blocks)
1403                        == generations[g].steps[s].n_blocks);
1404                 ASSERT(countBlocks(generations[g].steps[s].large_objects)
1405                        == generations[g].steps[s].n_large_blocks);
1406                 checkHeap(generations[g].steps[s].blocks);
1407                 checkLargeObjects(generations[g].steps[s].large_objects);
1408             }
1409         }
1410
1411         for (s = 0; s < n_nurseries; s++) {
1412             ASSERT(countBlocks(nurseries[s].blocks)
1413                    == nurseries[s].n_blocks);
1414             ASSERT(countBlocks(nurseries[s].large_objects)
1415                    == nurseries[s].n_large_blocks);
1416         }
1417             
1418         checkFreeListSanity();
1419     }
1420
1421 #if defined(THREADED_RTS)
1422     // check the stacks too in threaded mode, because we don't do a
1423     // full heap sanity check in this case (see checkHeap())
1424     checkMutableLists(rtsTrue);
1425 #else
1426     checkMutableLists(rtsFalse);
1427 #endif
1428 }
1429
1430 /* Nursery sanity check */
1431 void
1432 checkNurserySanity( step *stp )
1433 {
1434     bdescr *bd, *prev;
1435     nat blocks = 0;
1436
1437     prev = NULL;
1438     for (bd = stp->blocks; bd != NULL; bd = bd->link) {
1439         ASSERT(bd->u.back == prev);
1440         prev = bd;
1441         blocks += bd->blocks;
1442     }
1443     ASSERT(blocks == stp->n_blocks);
1444 }
1445
1446 // handy function for use in gdb, because Bdescr() is inlined.
1447 extern bdescr *_bdescr( StgPtr p );
1448
1449 bdescr *
1450 _bdescr( StgPtr p )
1451 {
1452     return Bdescr(p);
1453 }
1454
1455 #endif