[project @ 2006-01-17 16:13:18 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 #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 SMP 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 SMP */
53
54 /*
55  * Storage manager mutex:  protects all the above state from
56  * simultaneous access by two STG threads.
57  */
58 #ifdef SMP
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(SMP)
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 SMP
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 SMP
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 SMP
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 SMP
223   if (RtsFlags.GcFlags.generations == 1) {
224       errorBelch("-G1 is incompatible with SMP");
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 SMP
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 /* SMP */
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(StgClosure *p)
770 {
771     if (p->header.info == &stg_MUT_VAR_CLEAN_info) {
772         p->header.info = &stg_MUT_VAR_DIRTY_info;
773         recordMutable(p);
774     }
775 }
776
777 /* -----------------------------------------------------------------------------
778    Allocation functions for GMP.
779
780    These all use the allocate() interface - we can't have any garbage
781    collection going on during a gmp operation, so we use allocate()
782    which always succeeds.  The gmp operations which might need to
783    allocate will ask the storage manager (via doYouWantToGC()) whether
784    a garbage collection is required, in case we get into a loop doing
785    only allocate() style allocation.
786    -------------------------------------------------------------------------- */
787
788 static void *
789 stgAllocForGMP (size_t size_in_bytes)
790 {
791   StgArrWords* arr;
792   nat data_size_in_words, total_size_in_words;
793   
794   /* round up to a whole number of words */
795   data_size_in_words  = (size_in_bytes + sizeof(W_) + 1) / sizeof(W_);
796   total_size_in_words = sizeofW(StgArrWords) + data_size_in_words;
797   
798   /* allocate and fill it in. */
799 #if defined(SMP)
800   arr = (StgArrWords *)allocateLocal(myTask()->cap, total_size_in_words);
801 #else
802   arr = (StgArrWords *)allocateLocal(&MainCapability, total_size_in_words);
803 #endif
804   SET_ARR_HDR(arr, &stg_ARR_WORDS_info, CCCS, data_size_in_words);
805   
806   /* and return a ptr to the goods inside the array */
807   return arr->payload;
808 }
809
810 static void *
811 stgReallocForGMP (void *ptr, size_t old_size, size_t new_size)
812 {
813     void *new_stuff_ptr = stgAllocForGMP(new_size);
814     nat i = 0;
815     char *p = (char *) ptr;
816     char *q = (char *) new_stuff_ptr;
817
818     for (; i < old_size; i++, p++, q++) {
819         *q = *p;
820     }
821
822     return(new_stuff_ptr);
823 }
824
825 static void
826 stgDeallocForGMP (void *ptr STG_UNUSED, 
827                   size_t size STG_UNUSED)
828 {
829     /* easy for us: the garbage collector does the dealloc'n */
830 }
831
832 /* -----------------------------------------------------------------------------
833  * Stats and stuff
834  * -------------------------------------------------------------------------- */
835
836 /* -----------------------------------------------------------------------------
837  * calcAllocated()
838  *
839  * Approximate how much we've allocated: number of blocks in the
840  * nursery + blocks allocated via allocate() - unused nusery blocks.
841  * This leaves a little slop at the end of each block, and doesn't
842  * take into account large objects (ToDo).
843  * -------------------------------------------------------------------------- */
844
845 lnat
846 calcAllocated( void )
847 {
848   nat allocated;
849   bdescr *bd;
850
851   allocated = allocated_bytes();
852   allocated += countNurseryBlocks() * BLOCK_SIZE_W;
853   
854   {
855 #ifdef SMP
856   nat i;
857   for (i = 0; i < n_nurseries; i++) {
858       Capability *cap;
859       for ( bd = capabilities[i].r.rCurrentNursery->link; 
860             bd != NULL; bd = bd->link ) {
861           allocated -= BLOCK_SIZE_W;
862       }
863       cap = &capabilities[i];
864       if (cap->r.rCurrentNursery->free < 
865           cap->r.rCurrentNursery->start + BLOCK_SIZE_W) {
866           allocated -= (cap->r.rCurrentNursery->start + BLOCK_SIZE_W)
867               - cap->r.rCurrentNursery->free;
868       }
869   }
870 #else
871   bdescr *current_nursery = MainCapability.r.rCurrentNursery;
872
873   for ( bd = current_nursery->link; bd != NULL; bd = bd->link ) {
874       allocated -= BLOCK_SIZE_W;
875   }
876   if (current_nursery->free < current_nursery->start + BLOCK_SIZE_W) {
877       allocated -= (current_nursery->start + BLOCK_SIZE_W)
878           - current_nursery->free;
879   }
880 #endif
881   }
882
883   total_allocated += allocated;
884   return allocated;
885 }  
886
887 /* Approximate the amount of live data in the heap.  To be called just
888  * after garbage collection (see GarbageCollect()).
889  */
890 extern lnat 
891 calcLive(void)
892 {
893   nat g, s;
894   lnat live = 0;
895   step *stp;
896
897   if (RtsFlags.GcFlags.generations == 1) {
898     live = (g0s0->n_blocks - 1) * BLOCK_SIZE_W + 
899       ((lnat)g0s0->hp_bd->free - (lnat)g0s0->hp_bd->start) / sizeof(W_);
900     return live;
901   }
902
903   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
904     for (s = 0; s < generations[g].n_steps; s++) {
905       /* approximate amount of live data (doesn't take into account slop
906        * at end of each block).
907        */
908       if (g == 0 && s == 0) { 
909           continue; 
910       }
911       stp = &generations[g].steps[s];
912       live += (stp->n_large_blocks + stp->n_blocks - 1) * BLOCK_SIZE_W;
913       if (stp->hp_bd != NULL) {
914           live += ((lnat)stp->hp_bd->free - (lnat)stp->hp_bd->start) 
915               / sizeof(W_);
916       }
917       if (stp->scavd_hp != NULL) {
918           live -= (P_)(BLOCK_ROUND_UP(stp->scavd_hp)) - stp->scavd_hp;
919       }
920     }
921   }
922   return live;
923 }
924
925 /* Approximate the number of blocks that will be needed at the next
926  * garbage collection.
927  *
928  * Assume: all data currently live will remain live.  Steps that will
929  * be collected next time will therefore need twice as many blocks
930  * since all the data will be copied.
931  */
932 extern lnat 
933 calcNeeded(void)
934 {
935     lnat needed = 0;
936     nat g, s;
937     step *stp;
938     
939     for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
940         for (s = 0; s < generations[g].n_steps; s++) {
941             if (g == 0 && s == 0) { continue; }
942             stp = &generations[g].steps[s];
943             if (generations[g].steps[0].n_blocks +
944                 generations[g].steps[0].n_large_blocks 
945                 > generations[g].max_blocks
946                 && stp->is_compacted == 0) {
947                 needed += 2 * stp->n_blocks;
948             } else {
949                 needed += stp->n_blocks;
950             }
951         }
952     }
953     return needed;
954 }
955
956 /* -----------------------------------------------------------------------------
957    Debugging
958
959    memInventory() checks for memory leaks by counting up all the
960    blocks we know about and comparing that to the number of blocks
961    allegedly floating around in the system.
962    -------------------------------------------------------------------------- */
963
964 #ifdef DEBUG
965
966 static lnat
967 stepBlocks (step *stp)
968 {
969     lnat total_blocks;
970     bdescr *bd;
971
972     total_blocks = stp->n_blocks;    
973     total_blocks += stp->n_old_blocks;
974     for (bd = stp->large_objects; bd; bd = bd->link) {
975         total_blocks += bd->blocks;
976         /* hack for megablock groups: they have an extra block or two in
977            the second and subsequent megablocks where the block
978            descriptors would normally go.
979         */
980         if (bd->blocks > BLOCKS_PER_MBLOCK) {
981             total_blocks -= (MBLOCK_SIZE / BLOCK_SIZE - BLOCKS_PER_MBLOCK)
982                 * (bd->blocks/(MBLOCK_SIZE/BLOCK_SIZE));
983         }
984     }
985     return total_blocks;
986 }
987
988 void
989 memInventory(void)
990 {
991   nat g, s, i;
992   step *stp;
993   bdescr *bd;
994   lnat total_blocks = 0, free_blocks = 0;
995
996   /* count the blocks we current have */
997
998   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
999       for (i = 0; i < n_capabilities; i++) {
1000           for (bd = capabilities[i].mut_lists[g]; bd != NULL; bd = bd->link) {
1001               total_blocks += bd->blocks;
1002           }
1003       }   
1004       for (bd = generations[g].mut_list; bd != NULL; bd = bd->link) {
1005           total_blocks += bd->blocks;
1006       }
1007       for (s = 0; s < generations[g].n_steps; s++) {
1008           if (g==0 && s==0) continue;
1009           stp = &generations[g].steps[s];
1010           total_blocks += stepBlocks(stp);
1011       }
1012   }
1013
1014   for (i = 0; i < n_nurseries; i++) {
1015       total_blocks += stepBlocks(&nurseries[i]);
1016   }
1017 #ifdef SMP
1018   // We put pinned object blocks in g0s0, so better count blocks there too.
1019   total_blocks += stepBlocks(g0s0);
1020 #endif
1021
1022   /* any blocks held by allocate() */
1023   for (bd = small_alloc_list; bd; bd = bd->link) {
1024     total_blocks += bd->blocks;
1025   }
1026
1027 #ifdef PROFILING
1028   if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_RETAINER) {
1029       total_blocks += retainerStackBlocks();
1030   }
1031 #endif
1032
1033   // count the blocks allocated by the arena allocator
1034   total_blocks += arenaBlocks();
1035
1036   /* count the blocks on the free list */
1037   free_blocks = countFreeList();
1038
1039   if (total_blocks + free_blocks != mblocks_allocated *
1040       BLOCKS_PER_MBLOCK) {
1041     debugBelch("Blocks: %ld live + %ld free  = %ld total (%ld around)\n",
1042             total_blocks, free_blocks, total_blocks + free_blocks,
1043             mblocks_allocated * BLOCKS_PER_MBLOCK);
1044   }
1045
1046   ASSERT(total_blocks + free_blocks == mblocks_allocated * BLOCKS_PER_MBLOCK);
1047 }
1048
1049
1050 nat
1051 countBlocks(bdescr *bd)
1052 {
1053     nat n;
1054     for (n=0; bd != NULL; bd=bd->link) {
1055         n += bd->blocks;
1056     }
1057     return n;
1058 }
1059
1060 /* Full heap sanity check. */
1061 void
1062 checkSanity( void )
1063 {
1064     nat g, s;
1065
1066     if (RtsFlags.GcFlags.generations == 1) {
1067         checkHeap(g0s0->blocks);
1068         checkChain(g0s0->large_objects);
1069     } else {
1070         
1071         for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1072             for (s = 0; s < generations[g].n_steps; s++) {
1073                 if (g == 0 && s == 0) { continue; }
1074                 ASSERT(countBlocks(generations[g].steps[s].blocks)
1075                        == generations[g].steps[s].n_blocks);
1076                 ASSERT(countBlocks(generations[g].steps[s].large_objects)
1077                        == generations[g].steps[s].n_large_blocks);
1078                 checkHeap(generations[g].steps[s].blocks);
1079                 checkChain(generations[g].steps[s].large_objects);
1080                 if (g > 0) {
1081                     checkMutableList(generations[g].mut_list, g);
1082                 }
1083             }
1084         }
1085
1086         for (s = 0; s < n_nurseries; s++) {
1087             ASSERT(countBlocks(nurseries[s].blocks)
1088                    == nurseries[s].n_blocks);
1089             ASSERT(countBlocks(nurseries[s].large_objects)
1090                    == nurseries[s].n_large_blocks);
1091         }
1092             
1093         checkFreeListSanity();
1094     }
1095 }
1096
1097 /* Nursery sanity check */
1098 void
1099 checkNurserySanity( step *stp )
1100 {
1101     bdescr *bd, *prev;
1102     nat blocks = 0;
1103
1104     prev = NULL;
1105     for (bd = stp->blocks; bd != NULL; bd = bd->link) {
1106         ASSERT(bd->u.back == prev);
1107         prev = bd;
1108         blocks += bd->blocks;
1109     }
1110     ASSERT(blocks == stp->n_blocks);
1111 }
1112
1113 // handy function for use in gdb, because Bdescr() is inlined.
1114 extern bdescr *_bdescr( StgPtr p );
1115
1116 bdescr *
1117 _bdescr( StgPtr p )
1118 {
1119     return Bdescr(p);
1120 }
1121
1122 #endif