Merge the smp and threaded RTS ways
[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 #include "OSThreads.h"
21 #include "Capability.h"
22 #include "Storage.h"
23 #include "Schedule.h"
24 #include "RetainerProfile.h"    // for counting memory blocks (memInventory)
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 /* 
30  * All these globals require sm_mutex to access in THREADED_RTS mode.
31  */
32 StgClosure    *caf_list         = NULL;
33 StgClosure    *revertible_caf_list = NULL;
34 rtsBool       keepCAFs;
35
36 bdescr *small_alloc_list;       /* allocate()d small objects */
37 bdescr *pinned_object_block;    /* allocate pinned objects into this block */
38 nat alloc_blocks;               /* number of allocate()d blocks since GC */
39 nat alloc_blocks_lim;           /* approximate limit on alloc_blocks */
40
41 StgPtr alloc_Hp    = NULL;      /* next free byte in small_alloc_list */
42 StgPtr alloc_HpLim = NULL;      /* end of block at small_alloc_list   */
43
44 generation *generations = NULL; /* all the generations */
45 generation *g0          = NULL; /* generation 0, for convenience */
46 generation *oldest_gen  = NULL; /* oldest generation, for convenience */
47 step *g0s0              = NULL; /* generation 0, step 0, for convenience */
48
49 ullong total_allocated = 0;     /* total memory allocated during run */
50
51 nat n_nurseries         = 0;    /* == RtsFlags.ParFlags.nNodes, convenience */
52 step *nurseries         = NULL; /* array of nurseries, >1 only if THREADED_RTS */
53
54 /*
55  * Storage manager mutex:  protects all the above state from
56  * simultaneous access by two STG threads.
57  */
58 #ifdef THREADED_RTS
59 Mutex sm_mutex;
60 #endif
61
62 /*
63  * Forward references
64  */
65 static void *stgAllocForGMP   (size_t size_in_bytes);
66 static void *stgReallocForGMP (void *ptr, size_t old_size, size_t new_size);
67 static void  stgDeallocForGMP (void *ptr, size_t size);
68
69 static void
70 initStep (step *stp, int g, int s)
71 {
72     stp->no = s;
73     stp->blocks = NULL;
74     stp->n_blocks = 0;
75     stp->old_blocks = NULL;
76     stp->n_old_blocks = 0;
77     stp->gen = &generations[g];
78     stp->gen_no = g;
79     stp->hp = NULL;
80     stp->hpLim = NULL;
81     stp->hp_bd = NULL;
82     stp->scavd_hp = NULL;
83     stp->scavd_hpLim = NULL;
84     stp->scan = NULL;
85     stp->scan_bd = NULL;
86     stp->large_objects = NULL;
87     stp->n_large_blocks = 0;
88     stp->new_large_objects = NULL;
89     stp->scavenged_large_objects = NULL;
90     stp->n_scavenged_large_blocks = 0;
91     stp->is_compacted = 0;
92     stp->bitmap = NULL;
93 }
94
95 void
96 initStorage( void )
97 {
98   nat g, s;
99   generation *gen;
100
101   if (generations != NULL) {
102       // multi-init protection
103       return;
104   }
105
106   /* Sanity check to make sure the LOOKS_LIKE_ macros appear to be
107    * doing something reasonable.
108    */
109   ASSERT(LOOKS_LIKE_INFO_PTR(&stg_BLACKHOLE_info));
110   ASSERT(LOOKS_LIKE_CLOSURE_PTR(&stg_dummy_ret_closure));
111   ASSERT(!HEAP_ALLOCED(&stg_dummy_ret_closure));
112   
113   if (RtsFlags.GcFlags.maxHeapSize != 0 &&
114       RtsFlags.GcFlags.heapSizeSuggestion > 
115       RtsFlags.GcFlags.maxHeapSize) {
116     RtsFlags.GcFlags.maxHeapSize = RtsFlags.GcFlags.heapSizeSuggestion;
117   }
118
119   if (RtsFlags.GcFlags.maxHeapSize != 0 &&
120       RtsFlags.GcFlags.minAllocAreaSize > 
121       RtsFlags.GcFlags.maxHeapSize) {
122       errorBelch("maximum heap size (-M) is smaller than minimum alloc area size (-A)");
123       exit(1);
124   }
125
126   initBlockAllocator();
127   
128 #if defined(THREADED_RTS)
129   initMutex(&sm_mutex);
130 #endif
131
132   ACQUIRE_SM_LOCK;
133
134   /* allocate generation info array */
135   generations = (generation *)stgMallocBytes(RtsFlags.GcFlags.generations 
136                                              * sizeof(struct generation_),
137                                              "initStorage: gens");
138
139   /* Initialise all generations */
140   for(g = 0; g < RtsFlags.GcFlags.generations; g++) {
141     gen = &generations[g];
142     gen->no = g;
143     gen->mut_list = allocBlock();
144     gen->collections = 0;
145     gen->failed_promotions = 0;
146     gen->max_blocks = 0;
147   }
148
149   /* A couple of convenience pointers */
150   g0 = &generations[0];
151   oldest_gen = &generations[RtsFlags.GcFlags.generations-1];
152
153   /* Allocate step structures in each generation */
154   if (RtsFlags.GcFlags.generations > 1) {
155     /* Only for multiple-generations */
156
157     /* Oldest generation: one step */
158     oldest_gen->n_steps = 1;
159     oldest_gen->steps = 
160       stgMallocBytes(1 * sizeof(struct step_), "initStorage: last step");
161
162     /* set up all except the oldest generation with 2 steps */
163     for(g = 0; g < RtsFlags.GcFlags.generations-1; g++) {
164       generations[g].n_steps = RtsFlags.GcFlags.steps;
165       generations[g].steps  = 
166         stgMallocBytes (RtsFlags.GcFlags.steps * sizeof(struct step_),
167                         "initStorage: steps");
168     }
169     
170   } else {
171     /* single generation, i.e. a two-space collector */
172     g0->n_steps = 1;
173     g0->steps = stgMallocBytes (sizeof(struct step_), "initStorage: steps");
174   }
175
176 #ifdef THREADED_RTS
177   n_nurseries = n_capabilities;
178   nurseries = stgMallocBytes (n_nurseries * sizeof(struct step_),
179                               "initStorage: nurseries");
180 #else
181   n_nurseries = 1;
182   nurseries = g0->steps; // just share nurseries[0] with g0s0
183 #endif  
184
185   /* Initialise all steps */
186   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
187     for (s = 0; s < generations[g].n_steps; s++) {
188         initStep(&generations[g].steps[s], g, s);
189     }
190   }
191   
192 #ifdef THREADED_RTS
193   for (s = 0; s < n_nurseries; s++) {
194       initStep(&nurseries[s], 0, s);
195   }
196 #endif
197   
198   /* Set up the destination pointers in each younger gen. step */
199   for (g = 0; g < RtsFlags.GcFlags.generations-1; g++) {
200     for (s = 0; s < generations[g].n_steps-1; s++) {
201       generations[g].steps[s].to = &generations[g].steps[s+1];
202     }
203     generations[g].steps[s].to = &generations[g+1].steps[0];
204   }
205   oldest_gen->steps[0].to = &oldest_gen->steps[0];
206   
207 #ifdef THREADED_RTS
208   for (s = 0; s < n_nurseries; s++) {
209       nurseries[s].to = generations[0].steps[0].to;
210   }
211 #endif
212   
213   /* The oldest generation has one step. */
214   if (RtsFlags.GcFlags.compact) {
215       if (RtsFlags.GcFlags.generations == 1) {
216           errorBelch("WARNING: compaction is incompatible with -G1; disabled");
217       } else {
218           oldest_gen->steps[0].is_compacted = 1;
219       }
220   }
221
222 #ifdef THREADED_RTS
223   if (RtsFlags.GcFlags.generations == 1) {
224       errorBelch("-G1 is incompatible with -threaded");
225       stg_exit(EXIT_FAILURE);
226   }
227 #endif
228
229   /* generation 0 is special: that's the nursery */
230   generations[0].max_blocks = 0;
231
232   /* G0S0: the allocation area.  Policy: keep the allocation area
233    * small to begin with, even if we have a large suggested heap
234    * size.  Reason: we're going to do a major collection first, and we
235    * don't want it to be a big one.  This vague idea is borne out by 
236    * rigorous experimental evidence.
237    */
238   g0s0 = &generations[0].steps[0];
239
240   allocNurseries();
241
242   weak_ptr_list = NULL;
243   caf_list = NULL;
244   revertible_caf_list = NULL;
245    
246   /* initialise the allocate() interface */
247   small_alloc_list = NULL;
248   alloc_blocks = 0;
249   alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize;
250
251   /* Tell GNU multi-precision pkg about our custom alloc functions */
252   mp_set_memory_functions(stgAllocForGMP, stgReallocForGMP, stgDeallocForGMP);
253
254   IF_DEBUG(gc, statDescribeGens());
255
256   RELEASE_SM_LOCK;
257 }
258
259 void
260 exitStorage (void)
261 {
262     stat_exit(calcAllocated());
263 }
264
265 /* -----------------------------------------------------------------------------
266    CAF management.
267
268    The entry code for every CAF does the following:
269      
270       - builds a CAF_BLACKHOLE in the heap
271       - pushes an update frame pointing to the CAF_BLACKHOLE
272       - invokes UPD_CAF(), which:
273           - calls newCaf, below
274           - updates the CAF with a static indirection to the CAF_BLACKHOLE
275       
276    Why do we build a BLACKHOLE in the heap rather than just updating
277    the thunk directly?  It's so that we only need one kind of update
278    frame - otherwise we'd need a static version of the update frame too.
279
280    newCaf() does the following:
281        
282       - it puts the CAF on the oldest generation's mut-once list.
283         This is so that we can treat the CAF as a root when collecting
284         younger generations.
285
286    For GHCI, we have additional requirements when dealing with CAFs:
287
288       - we must *retain* all dynamically-loaded CAFs ever entered,
289         just in case we need them again.
290       - we must be able to *revert* CAFs that have been evaluated, to
291         their pre-evaluated form.
292
293       To do this, we use an additional CAF list.  When newCaf() is
294       called on a dynamically-loaded CAF, we add it to the CAF list
295       instead of the old-generation mutable list, and save away its
296       old info pointer (in caf->saved_info) for later reversion.
297
298       To revert all the CAFs, we traverse the CAF list and reset the
299       info pointer to caf->saved_info, then throw away the CAF list.
300       (see GC.c:revertCAFs()).
301
302       -- SDM 29/1/01
303
304    -------------------------------------------------------------------------- */
305
306 void
307 newCAF(StgClosure* caf)
308 {
309   ACQUIRE_SM_LOCK;
310
311   if(keepCAFs)
312   {
313     // HACK:
314     // If we are in GHCi _and_ we are using dynamic libraries,
315     // then we can't redirect newCAF calls to newDynCAF (see below),
316     // so we make newCAF behave almost like newDynCAF.
317     // The dynamic libraries might be used by both the interpreted
318     // program and GHCi itself, so they must not be reverted.
319     // This also means that in GHCi with dynamic libraries, CAFs are not
320     // garbage collected. If this turns out to be a problem, we could
321     // do another hack here and do an address range test on caf to figure
322     // out whether it is from a dynamic library.
323     ((StgIndStatic *)caf)->saved_info  = (StgInfoTable *)caf->header.info;
324     ((StgIndStatic *)caf)->static_link = caf_list;
325     caf_list = caf;
326   }
327   else
328   {
329     /* Put this CAF on the mutable list for the old generation.
330     * This is a HACK - the IND_STATIC closure doesn't really have
331     * a mut_link field, but we pretend it has - in fact we re-use
332     * the STATIC_LINK field for the time being, because when we
333     * come to do a major GC we won't need the mut_link field
334     * any more and can use it as a STATIC_LINK.
335     */
336     ((StgIndStatic *)caf)->saved_info = NULL;
337     recordMutableGen(caf, oldest_gen);
338   }
339   
340   RELEASE_SM_LOCK;
341
342 #ifdef PAR
343   /* If we are PAR or DIST then  we never forget a CAF */
344   { globalAddr *newGA;
345     //debugBelch("<##> Globalising CAF %08x %s",caf,info_type(caf));
346     newGA=makeGlobal(caf,rtsTrue); /*given full weight*/
347     ASSERT(newGA);
348   } 
349 #endif /* PAR */
350 }
351
352 // An alternate version of newCaf which is used for dynamically loaded
353 // object code in GHCi.  In this case we want to retain *all* CAFs in
354 // the object code, because they might be demanded at any time from an
355 // expression evaluated on the command line.
356 // Also, GHCi might want to revert CAFs, so we add these to the
357 // revertible_caf_list.
358 //
359 // The linker hackily arranges that references to newCaf from dynamic
360 // code end up pointing to newDynCAF.
361 void
362 newDynCAF(StgClosure *caf)
363 {
364     ACQUIRE_SM_LOCK;
365
366     ((StgIndStatic *)caf)->saved_info  = (StgInfoTable *)caf->header.info;
367     ((StgIndStatic *)caf)->static_link = revertible_caf_list;
368     revertible_caf_list = caf;
369
370     RELEASE_SM_LOCK;
371 }
372
373 /* -----------------------------------------------------------------------------
374    Nursery management.
375    -------------------------------------------------------------------------- */
376
377 static bdescr *
378 allocNursery (step *stp, bdescr *tail, nat blocks)
379 {
380     bdescr *bd;
381     nat i;
382
383     // Allocate a nursery: we allocate fresh blocks one at a time and
384     // cons them on to the front of the list, not forgetting to update
385     // the back pointer on the tail of the list to point to the new block.
386     for (i=0; i < blocks; i++) {
387         // @LDV profiling
388         /*
389           processNursery() in LdvProfile.c assumes that every block group in
390           the nursery contains only a single block. So, if a block group is
391           given multiple blocks, change processNursery() accordingly.
392         */
393         bd = allocBlock();
394         bd->link = tail;
395         // double-link the nursery: we might need to insert blocks
396         if (tail != NULL) {
397             tail->u.back = bd;
398         }
399         bd->step = stp;
400         bd->gen_no = 0;
401         bd->flags = 0;
402         bd->free = bd->start;
403         tail = bd;
404     }
405     tail->u.back = NULL;
406     return tail;
407 }
408
409 static void
410 assignNurseriesToCapabilities (void)
411 {
412 #ifdef THREADED_RTS
413     nat i;
414
415     for (i = 0; i < n_nurseries; i++) {
416         capabilities[i].r.rNursery        = &nurseries[i];
417         capabilities[i].r.rCurrentNursery = nurseries[i].blocks;
418         capabilities[i].r.rCurrentAlloc   = NULL;
419     }
420 #else /* THREADED_RTS */
421     MainCapability.r.rNursery        = &nurseries[0];
422     MainCapability.r.rCurrentNursery = nurseries[0].blocks;
423     MainCapability.r.rCurrentAlloc   = NULL;
424 #endif
425 }
426
427 void
428 allocNurseries( void )
429
430     nat i;
431
432     for (i = 0; i < n_nurseries; i++) {
433         nurseries[i].blocks = 
434             allocNursery(&nurseries[i], NULL, 
435                          RtsFlags.GcFlags.minAllocAreaSize);
436         nurseries[i].n_blocks    = RtsFlags.GcFlags.minAllocAreaSize;
437         nurseries[i].old_blocks   = NULL;
438         nurseries[i].n_old_blocks = 0;
439         /* hp, hpLim, hp_bd, to_space etc. aren't used in the nursery */
440     }
441     assignNurseriesToCapabilities();
442 }
443       
444 void
445 resetNurseries( void )
446 {
447     nat i;
448     bdescr *bd;
449     step *stp;
450
451     for (i = 0; i < n_nurseries; i++) {
452         stp = &nurseries[i];
453         for (bd = stp->blocks; bd; bd = bd->link) {
454             bd->free = bd->start;
455             ASSERT(bd->gen_no == 0);
456             ASSERT(bd->step == stp);
457             IF_DEBUG(sanity,memset(bd->start, 0xaa, BLOCK_SIZE));
458         }
459     }
460     assignNurseriesToCapabilities();
461 }
462
463 lnat
464 countNurseryBlocks (void)
465 {
466     nat i;
467     lnat blocks = 0;
468
469     for (i = 0; i < n_nurseries; i++) {
470         blocks += nurseries[i].n_blocks;
471     }
472     return blocks;
473 }
474
475 static void
476 resizeNursery ( step *stp, nat blocks )
477 {
478   bdescr *bd;
479   nat nursery_blocks;
480
481   nursery_blocks = stp->n_blocks;
482   if (nursery_blocks == blocks) return;
483
484   if (nursery_blocks < blocks) {
485     IF_DEBUG(gc, debugBelch("Increasing size of nursery to %d blocks\n", 
486                          blocks));
487     stp->blocks = allocNursery(stp, stp->blocks, blocks-nursery_blocks);
488   } 
489   else {
490     bdescr *next_bd;
491     
492     IF_DEBUG(gc, debugBelch("Decreasing size of nursery to %d blocks\n", 
493                          blocks));
494
495     bd = stp->blocks;
496     while (nursery_blocks > blocks) {
497         next_bd = bd->link;
498         next_bd->u.back = NULL;
499         nursery_blocks -= bd->blocks; // might be a large block
500         freeGroup(bd);
501         bd = next_bd;
502     }
503     stp->blocks = bd;
504     // might have gone just under, by freeing a large block, so make
505     // up the difference.
506     if (nursery_blocks < blocks) {
507         stp->blocks = allocNursery(stp, stp->blocks, blocks-nursery_blocks);
508     }
509   }
510   
511   stp->n_blocks = blocks;
512   ASSERT(countBlocks(stp->blocks) == stp->n_blocks);
513 }
514
515 // 
516 // Resize each of the nurseries to the specified size.
517 //
518 void
519 resizeNurseriesFixed (nat blocks)
520 {
521     nat i;
522     for (i = 0; i < n_nurseries; i++) {
523         resizeNursery(&nurseries[i], blocks);
524     }
525 }
526
527 // 
528 // Resize the nurseries to the total specified size.
529 //
530 void
531 resizeNurseries (nat blocks)
532 {
533     // If there are multiple nurseries, then we just divide the number
534     // of available blocks between them.
535     resizeNurseriesFixed(blocks / n_nurseries);
536 }
537
538 /* -----------------------------------------------------------------------------
539    The allocate() interface
540
541    allocate(n) always succeeds, and returns a chunk of memory n words
542    long.  n can be larger than the size of a block if necessary, in
543    which case a contiguous block group will be allocated.
544    -------------------------------------------------------------------------- */
545
546 StgPtr
547 allocate( nat n )
548 {
549     bdescr *bd;
550     StgPtr p;
551
552     ACQUIRE_SM_LOCK;
553
554     TICK_ALLOC_HEAP_NOCTR(n);
555     CCS_ALLOC(CCCS,n);
556
557     /* big allocation (>LARGE_OBJECT_THRESHOLD) */
558     /* ToDo: allocate directly into generation 1 */
559     if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
560         nat req_blocks =  (lnat)BLOCK_ROUND_UP(n*sizeof(W_)) / BLOCK_SIZE;
561         bd = allocGroup(req_blocks);
562         dbl_link_onto(bd, &g0s0->large_objects);
563         g0s0->n_large_blocks += req_blocks;
564         bd->gen_no  = 0;
565         bd->step = g0s0;
566         bd->flags = BF_LARGE;
567         bd->free = bd->start + n;
568         alloc_blocks += req_blocks;
569         RELEASE_SM_LOCK;
570         return bd->start;
571         
572         /* small allocation (<LARGE_OBJECT_THRESHOLD) */
573     } else if (small_alloc_list == NULL || alloc_Hp + n > alloc_HpLim) {
574         if (small_alloc_list) {
575             small_alloc_list->free = alloc_Hp;
576         }
577         bd = allocBlock();
578         bd->link = small_alloc_list;
579         small_alloc_list = bd;
580         bd->gen_no = 0;
581         bd->step = g0s0;
582         bd->flags = 0;
583         alloc_Hp = bd->start;
584         alloc_HpLim = bd->start + BLOCK_SIZE_W;
585         alloc_blocks++;
586     }
587     
588     p = alloc_Hp;
589     alloc_Hp += n;
590     RELEASE_SM_LOCK;
591     return p;
592 }
593
594 lnat
595 allocated_bytes( void )
596 {
597     lnat allocated;
598
599     allocated = alloc_blocks * BLOCK_SIZE_W - (alloc_HpLim - alloc_Hp);
600     if (pinned_object_block != NULL) {
601         allocated -= (pinned_object_block->start + BLOCK_SIZE_W) - 
602             pinned_object_block->free;
603     }
604         
605     return allocated;
606 }
607
608 void
609 tidyAllocateLists (void)
610 {
611     if (small_alloc_list != NULL) {
612         ASSERT(alloc_Hp >= small_alloc_list->start && 
613                alloc_Hp <= small_alloc_list->start + BLOCK_SIZE);
614         small_alloc_list->free = alloc_Hp;
615     }
616 }
617
618 /* -----------------------------------------------------------------------------
619    allocateLocal()
620
621    This allocates memory in the current thread - it is intended for
622    use primarily from STG-land where we have a Capability.  It is
623    better than allocate() because it doesn't require taking the
624    sm_mutex lock in the common case.
625
626    Memory is allocated directly from the nursery if possible (but not
627    from the current nursery block, so as not to interfere with
628    Hp/HpLim).
629    -------------------------------------------------------------------------- */
630
631 StgPtr
632 allocateLocal (Capability *cap, nat n)
633 {
634     bdescr *bd;
635     StgPtr p;
636
637     TICK_ALLOC_HEAP_NOCTR(n);
638     CCS_ALLOC(CCCS,n);
639     
640     /* big allocation (>LARGE_OBJECT_THRESHOLD) */
641     /* ToDo: allocate directly into generation 1 */
642     if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
643         nat req_blocks =  (lnat)BLOCK_ROUND_UP(n*sizeof(W_)) / BLOCK_SIZE;
644         ACQUIRE_SM_LOCK;
645         bd = allocGroup(req_blocks);
646         dbl_link_onto(bd, &g0s0->large_objects);
647         g0s0->n_large_blocks += req_blocks;
648         bd->gen_no  = 0;
649         bd->step = g0s0;
650         bd->flags = BF_LARGE;
651         bd->free = bd->start + n;
652         alloc_blocks += req_blocks;
653         RELEASE_SM_LOCK;
654         return bd->start;
655         
656         /* small allocation (<LARGE_OBJECT_THRESHOLD) */
657     } else {
658
659         bd = cap->r.rCurrentAlloc;
660         if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) {
661
662             // The CurrentAlloc block is full, we need to find another
663             // one.  First, we try taking the next block from the
664             // nursery:
665             bd = cap->r.rCurrentNursery->link;
666
667             if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) {
668                 // The nursery is empty, or the next block is already
669                 // full: allocate a fresh block (we can't fail here).
670                 ACQUIRE_SM_LOCK;
671                 bd = allocBlock();
672                 cap->r.rNursery->n_blocks++;
673                 RELEASE_SM_LOCK;
674                 bd->gen_no = 0;
675                 bd->step = cap->r.rNursery;
676                 bd->flags = 0;
677             } else {
678                 // we have a block in the nursery: take it and put
679                 // it at the *front* of the nursery list, and use it
680                 // to allocate() from.
681                 cap->r.rCurrentNursery->link = bd->link;
682                 if (bd->link != NULL) {
683                     bd->link->u.back = cap->r.rCurrentNursery;
684                 }
685             }
686             dbl_link_onto(bd, &cap->r.rNursery->blocks);
687             cap->r.rCurrentAlloc = bd;
688             IF_DEBUG(sanity, checkNurserySanity(cap->r.rNursery));
689         }
690     }
691     p = bd->free;
692     bd->free += n;
693     return p;
694 }
695
696 /* ---------------------------------------------------------------------------
697    Allocate a fixed/pinned object.
698
699    We allocate small pinned objects into a single block, allocating a
700    new block when the current one overflows.  The block is chained
701    onto the large_object_list of generation 0 step 0.
702
703    NOTE: The GC can't in general handle pinned objects.  This
704    interface is only safe to use for ByteArrays, which have no
705    pointers and don't require scavenging.  It works because the
706    block's descriptor has the BF_LARGE flag set, so the block is
707    treated as a large object and chained onto various lists, rather
708    than the individual objects being copied.  However, when it comes
709    to scavenge the block, the GC will only scavenge the first object.
710    The reason is that the GC can't linearly scan a block of pinned
711    objects at the moment (doing so would require using the
712    mostly-copying techniques).  But since we're restricting ourselves
713    to pinned ByteArrays, not scavenging is ok.
714
715    This function is called by newPinnedByteArray# which immediately
716    fills the allocated memory with a MutableByteArray#.
717    ------------------------------------------------------------------------- */
718
719 StgPtr
720 allocatePinned( nat n )
721 {
722     StgPtr p;
723     bdescr *bd = pinned_object_block;
724
725     // If the request is for a large object, then allocate()
726     // will give us a pinned object anyway.
727     if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
728         return allocate(n);
729     }
730
731     ACQUIRE_SM_LOCK;
732     
733     TICK_ALLOC_HEAP_NOCTR(n);
734     CCS_ALLOC(CCCS,n);
735
736     // we always return 8-byte aligned memory.  bd->free must be
737     // 8-byte aligned to begin with, so we just round up n to
738     // the nearest multiple of 8 bytes.
739     if (sizeof(StgWord) == 4) {
740         n = (n+1) & ~1;
741     }
742
743     // If we don't have a block of pinned objects yet, or the current
744     // one isn't large enough to hold the new object, allocate a new one.
745     if (bd == NULL || (bd->free + n) > (bd->start + BLOCK_SIZE_W)) {
746         pinned_object_block = bd = allocBlock();
747         dbl_link_onto(bd, &g0s0->large_objects);
748         bd->gen_no = 0;
749         bd->step   = g0s0;
750         bd->flags  = BF_PINNED | BF_LARGE;
751         bd->free   = bd->start;
752         alloc_blocks++;
753     }
754
755     p = bd->free;
756     bd->free += n;
757     RELEASE_SM_LOCK;
758     return p;
759 }
760
761 /* -----------------------------------------------------------------------------
762    This is the write barrier for MUT_VARs, a.k.a. IORefs.  A
763    MUT_VAR_CLEAN object is not on the mutable list; a MUT_VAR_DIRTY
764    is.  When written to, a MUT_VAR_CLEAN turns into a MUT_VAR_DIRTY
765    and is put on the mutable list.
766    -------------------------------------------------------------------------- */
767
768 void
769 dirty_MUT_VAR(StgRegTable *reg, StgClosure *p)
770 {
771     Capability *cap = regTableToCapability(reg);
772     if (p->header.info == &stg_MUT_VAR_CLEAN_info) {
773         p->header.info = &stg_MUT_VAR_DIRTY_info;
774         recordMutableCap(p,cap,Bdescr(p)->gen_no);
775     }
776 }
777
778 /* -----------------------------------------------------------------------------
779    Allocation functions for GMP.
780
781    These all use the allocate() interface - we can't have any garbage
782    collection going on during a gmp operation, so we use allocate()
783    which always succeeds.  The gmp operations which might need to
784    allocate will ask the storage manager (via doYouWantToGC()) whether
785    a garbage collection is required, in case we get into a loop doing
786    only allocate() style allocation.
787    -------------------------------------------------------------------------- */
788
789 static void *
790 stgAllocForGMP (size_t size_in_bytes)
791 {
792   StgArrWords* arr;
793   nat data_size_in_words, total_size_in_words;
794   
795   /* round up to a whole number of words */
796   data_size_in_words  = (size_in_bytes + sizeof(W_) + 1) / sizeof(W_);
797   total_size_in_words = sizeofW(StgArrWords) + data_size_in_words;
798   
799   /* allocate and fill it in. */
800 #if defined(THREADED_RTS)
801   arr = (StgArrWords *)allocateLocal(myTask()->cap, total_size_in_words);
802 #else
803   arr = (StgArrWords *)allocateLocal(&MainCapability, total_size_in_words);
804 #endif
805   SET_ARR_HDR(arr, &stg_ARR_WORDS_info, CCCS, data_size_in_words);
806   
807   /* and return a ptr to the goods inside the array */
808   return arr->payload;
809 }
810
811 static void *
812 stgReallocForGMP (void *ptr, size_t old_size, size_t new_size)
813 {
814     void *new_stuff_ptr = stgAllocForGMP(new_size);
815     nat i = 0;
816     char *p = (char *) ptr;
817     char *q = (char *) new_stuff_ptr;
818
819     for (; i < old_size; i++, p++, q++) {
820         *q = *p;
821     }
822
823     return(new_stuff_ptr);
824 }
825
826 static void
827 stgDeallocForGMP (void *ptr STG_UNUSED, 
828                   size_t size STG_UNUSED)
829 {
830     /* easy for us: the garbage collector does the dealloc'n */
831 }
832
833 /* -----------------------------------------------------------------------------
834  * Stats and stuff
835  * -------------------------------------------------------------------------- */
836
837 /* -----------------------------------------------------------------------------
838  * calcAllocated()
839  *
840  * Approximate how much we've allocated: number of blocks in the
841  * nursery + blocks allocated via allocate() - unused nusery blocks.
842  * This leaves a little slop at the end of each block, and doesn't
843  * take into account large objects (ToDo).
844  * -------------------------------------------------------------------------- */
845
846 lnat
847 calcAllocated( void )
848 {
849   nat allocated;
850   bdescr *bd;
851
852   allocated = allocated_bytes();
853   allocated += countNurseryBlocks() * BLOCK_SIZE_W;
854   
855   {
856 #ifdef THREADED_RTS
857   nat i;
858   for (i = 0; i < n_nurseries; i++) {
859       Capability *cap;
860       for ( bd = capabilities[i].r.rCurrentNursery->link; 
861             bd != NULL; bd = bd->link ) {
862           allocated -= BLOCK_SIZE_W;
863       }
864       cap = &capabilities[i];
865       if (cap->r.rCurrentNursery->free < 
866           cap->r.rCurrentNursery->start + BLOCK_SIZE_W) {
867           allocated -= (cap->r.rCurrentNursery->start + BLOCK_SIZE_W)
868               - cap->r.rCurrentNursery->free;
869       }
870   }
871 #else
872   bdescr *current_nursery = MainCapability.r.rCurrentNursery;
873
874   for ( bd = current_nursery->link; bd != NULL; bd = bd->link ) {
875       allocated -= BLOCK_SIZE_W;
876   }
877   if (current_nursery->free < current_nursery->start + BLOCK_SIZE_W) {
878       allocated -= (current_nursery->start + BLOCK_SIZE_W)
879           - current_nursery->free;
880   }
881 #endif
882   }
883
884   total_allocated += allocated;
885   return allocated;
886 }  
887
888 /* Approximate the amount of live data in the heap.  To be called just
889  * after garbage collection (see GarbageCollect()).
890  */
891 extern lnat 
892 calcLive(void)
893 {
894   nat g, s;
895   lnat live = 0;
896   step *stp;
897
898   if (RtsFlags.GcFlags.generations == 1) {
899     live = (g0s0->n_blocks - 1) * BLOCK_SIZE_W + 
900       ((lnat)g0s0->hp_bd->free - (lnat)g0s0->hp_bd->start) / sizeof(W_);
901     return live;
902   }
903
904   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
905     for (s = 0; s < generations[g].n_steps; s++) {
906       /* approximate amount of live data (doesn't take into account slop
907        * at end of each block).
908        */
909       if (g == 0 && s == 0) { 
910           continue; 
911       }
912       stp = &generations[g].steps[s];
913       live += (stp->n_large_blocks + stp->n_blocks - 1) * BLOCK_SIZE_W;
914       if (stp->hp_bd != NULL) {
915           live += ((lnat)stp->hp_bd->free - (lnat)stp->hp_bd->start) 
916               / sizeof(W_);
917       }
918       if (stp->scavd_hp != NULL) {
919           live -= (P_)(BLOCK_ROUND_UP(stp->scavd_hp)) - stp->scavd_hp;
920       }
921     }
922   }
923   return live;
924 }
925
926 /* Approximate the number of blocks that will be needed at the next
927  * garbage collection.
928  *
929  * Assume: all data currently live will remain live.  Steps that will
930  * be collected next time will therefore need twice as many blocks
931  * since all the data will be copied.
932  */
933 extern lnat 
934 calcNeeded(void)
935 {
936     lnat needed = 0;
937     nat g, s;
938     step *stp;
939     
940     for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
941         for (s = 0; s < generations[g].n_steps; s++) {
942             if (g == 0 && s == 0) { continue; }
943             stp = &generations[g].steps[s];
944             if (generations[g].steps[0].n_blocks +
945                 generations[g].steps[0].n_large_blocks 
946                 > generations[g].max_blocks
947                 && stp->is_compacted == 0) {
948                 needed += 2 * stp->n_blocks;
949             } else {
950                 needed += stp->n_blocks;
951             }
952         }
953     }
954     return needed;
955 }
956
957 /* -----------------------------------------------------------------------------
958    Debugging
959
960    memInventory() checks for memory leaks by counting up all the
961    blocks we know about and comparing that to the number of blocks
962    allegedly floating around in the system.
963    -------------------------------------------------------------------------- */
964
965 #ifdef DEBUG
966
967 static lnat
968 stepBlocks (step *stp)
969 {
970     lnat total_blocks;
971     bdescr *bd;
972
973     total_blocks = stp->n_blocks;    
974     total_blocks += stp->n_old_blocks;
975     for (bd = stp->large_objects; bd; bd = bd->link) {
976         total_blocks += bd->blocks;
977         /* hack for megablock groups: they have an extra block or two in
978            the second and subsequent megablocks where the block
979            descriptors would normally go.
980         */
981         if (bd->blocks > BLOCKS_PER_MBLOCK) {
982             total_blocks -= (MBLOCK_SIZE / BLOCK_SIZE - BLOCKS_PER_MBLOCK)
983                 * (bd->blocks/(MBLOCK_SIZE/BLOCK_SIZE));
984         }
985     }
986     return total_blocks;
987 }
988
989 void
990 memInventory(void)
991 {
992   nat g, s, i;
993   step *stp;
994   bdescr *bd;
995   lnat total_blocks = 0, free_blocks = 0;
996
997   /* count the blocks we current have */
998
999   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1000       for (i = 0; i < n_capabilities; i++) {
1001           for (bd = capabilities[i].mut_lists[g]; bd != NULL; bd = bd->link) {
1002               total_blocks += bd->blocks;
1003           }
1004       }   
1005       for (bd = generations[g].mut_list; bd != NULL; bd = bd->link) {
1006           total_blocks += bd->blocks;
1007       }
1008       for (s = 0; s < generations[g].n_steps; s++) {
1009           if (g==0 && s==0) continue;
1010           stp = &generations[g].steps[s];
1011           total_blocks += stepBlocks(stp);
1012       }
1013   }
1014
1015   for (i = 0; i < n_nurseries; i++) {
1016       total_blocks += stepBlocks(&nurseries[i]);
1017   }
1018 #ifdef THREADED_RTS
1019   // We put pinned object blocks in g0s0, so better count blocks there too.
1020   total_blocks += stepBlocks(g0s0);
1021 #endif
1022
1023   /* any blocks held by allocate() */
1024   for (bd = small_alloc_list; bd; bd = bd->link) {
1025     total_blocks += bd->blocks;
1026   }
1027
1028 #ifdef PROFILING
1029   if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_RETAINER) {
1030       total_blocks += retainerStackBlocks();
1031   }
1032 #endif
1033
1034   // count the blocks allocated by the arena allocator
1035   total_blocks += arenaBlocks();
1036
1037   /* count the blocks on the free list */
1038   free_blocks = countFreeList();
1039
1040   if (total_blocks + free_blocks != mblocks_allocated *
1041       BLOCKS_PER_MBLOCK) {
1042     debugBelch("Blocks: %ld live + %ld free  = %ld total (%ld around)\n",
1043             total_blocks, free_blocks, total_blocks + free_blocks,
1044             mblocks_allocated * BLOCKS_PER_MBLOCK);
1045   }
1046
1047   ASSERT(total_blocks + free_blocks == mblocks_allocated * BLOCKS_PER_MBLOCK);
1048 }
1049
1050
1051 nat
1052 countBlocks(bdescr *bd)
1053 {
1054     nat n;
1055     for (n=0; bd != NULL; bd=bd->link) {
1056         n += bd->blocks;
1057     }
1058     return n;
1059 }
1060
1061 /* Full heap sanity check. */
1062 void
1063 checkSanity( void )
1064 {
1065     nat g, s;
1066
1067     if (RtsFlags.GcFlags.generations == 1) {
1068         checkHeap(g0s0->blocks);
1069         checkChain(g0s0->large_objects);
1070     } else {
1071         
1072         for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1073             for (s = 0; s < generations[g].n_steps; s++) {
1074                 if (g == 0 && s == 0) { continue; }
1075                 ASSERT(countBlocks(generations[g].steps[s].blocks)
1076                        == generations[g].steps[s].n_blocks);
1077                 ASSERT(countBlocks(generations[g].steps[s].large_objects)
1078                        == generations[g].steps[s].n_large_blocks);
1079                 checkHeap(generations[g].steps[s].blocks);
1080                 checkChain(generations[g].steps[s].large_objects);
1081                 if (g > 0) {
1082                     checkMutableList(generations[g].mut_list, g);
1083                 }
1084             }
1085         }
1086
1087         for (s = 0; s < n_nurseries; s++) {
1088             ASSERT(countBlocks(nurseries[s].blocks)
1089                    == nurseries[s].n_blocks);
1090             ASSERT(countBlocks(nurseries[s].large_objects)
1091                    == nurseries[s].n_large_blocks);
1092         }
1093             
1094         checkFreeListSanity();
1095     }
1096 }
1097
1098 /* Nursery sanity check */
1099 void
1100 checkNurserySanity( step *stp )
1101 {
1102     bdescr *bd, *prev;
1103     nat blocks = 0;
1104
1105     prev = NULL;
1106     for (bd = stp->blocks; bd != NULL; bd = bd->link) {
1107         ASSERT(bd->u.back == prev);
1108         prev = bd;
1109         blocks += bd->blocks;
1110     }
1111     ASSERT(blocks == stp->n_blocks);
1112 }
1113
1114 // handy function for use in gdb, because Bdescr() is inlined.
1115 extern bdescr *_bdescr( StgPtr p );
1116
1117 bdescr *
1118 _bdescr( StgPtr p )
1119 {
1120     return Bdescr(p);
1121 }
1122
1123 #endif