source: trunk/src/gcc/boehm-gc/alloc.c@ 1392

Last change on this file since 1392 was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 29.5 KB
Line 
1/*
2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3 * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
4 * Copyright (c) 1998 by Silicon Graphics. All rights reserved.
5 * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
6 *
7 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
9 *
10 * Permission is hereby granted to use or copy this program
11 * for any purpose, provided the above notices are retained on all copies.
12 * Permission to modify the code and to distribute modified code is granted,
13 * provided the above notices are retained, and a notice that the code was
14 * modified is included with the above copyright notice.
15 *
16 */
17
18
19# include "private/gc_priv.h"
20
21# include <stdio.h>
22# if !defined(MACOS) && !defined(MSWINCE)
23# include <signal.h>
24# include <sys/types.h>
25# endif
26
27/*
28 * Separate free lists are maintained for different sized objects
29 * up to MAXOBJSZ.
30 * The call GC_allocobj(i,k) ensures that the freelist for
31 * kind k objects of size i points to a non-empty
32 * free list. It returns a pointer to the first entry on the free list.
33 * In a single-threaded world, GC_allocobj may be called to allocate
34 * an object of (small) size i as follows:
35 *
36 * opp = &(GC_objfreelist[i]);
37 * if (*opp == 0) GC_allocobj(i, NORMAL);
38 * ptr = *opp;
39 * *opp = obj_link(ptr);
40 *
41 * Note that this is very fast if the free list is non-empty; it should
42 * only involve the execution of 4 or 5 simple instructions.
43 * All composite objects on freelists are cleared, except for
44 * their first word.
45 */
46
47/*
48 * The allocator uses GC_allochblk to allocate large chunks of objects.
49 * These chunks all start on addresses which are multiples of
50 * HBLKSZ. Each allocated chunk has an associated header,
51 * which can be located quickly based on the address of the chunk.
52 * (See headers.c for details.)
53 * This makes it possible to check quickly whether an
54 * arbitrary address corresponds to an object administered by the
55 * allocator.
56 */
57
58word GC_non_gc_bytes = 0; /* Number of bytes not intended to be collected */
59
60word GC_gc_no = 0;
61
62#ifndef SMALL_CONFIG
63 int GC_incremental = 0; /* By default, stop the world. */
64#endif
65
66int GC_parallel = FALSE; /* By default, parallel GC is off. */
67
68int GC_full_freq = 19; /* Every 20th collection is a full */
69 /* collection, whether we need it */
70 /* or not. */
71
72GC_bool GC_need_full_gc = FALSE;
73 /* Need full GC do to heap growth. */
74
75word GC_used_heap_size_after_full = 0;
76
77char * GC_copyright[] =
78{"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ",
79"Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. ",
80"Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved. ",
81"Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. ",
82"THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY",
83" EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.",
84"See source code for details." };
85
86# include "version.h"
87
88/* some more variables */
89
90extern signed_word GC_mem_found; /* Number of reclaimed longwords */
91 /* after garbage collection */
92
93GC_bool GC_dont_expand = 0;
94
95word GC_free_space_divisor = 3;
96
97extern GC_bool GC_collection_in_progress();
98 /* Collection is in progress, or was abandoned. */
99
100extern GC_bool GC_print_back_height;
101
102int GC_never_stop_func GC_PROTO((void)) { return(0); }
103
104unsigned long GC_time_limit = TIME_LIMIT;
105
106CLOCK_TYPE GC_start_time; /* Time at which we stopped world. */
107 /* used only in GC_timeout_stop_func. */
108
109int GC_n_attempts = 0; /* Number of attempts at finishing */
110 /* collection within GC_time_limit. */
111
112#if defined(SMALL_CONFIG) || defined(NO_CLOCK)
113# define GC_timeout_stop_func GC_never_stop_func
114#else
115 int GC_timeout_stop_func GC_PROTO((void))
116 {
117 CLOCK_TYPE current_time;
118 static unsigned count = 0;
119 unsigned long time_diff;
120
121 if ((count++ & 3) != 0) return(0);
122#ifndef NO_CLOCK
123 GET_TIME(current_time);
124 time_diff = MS_TIME_DIFF(current_time,GC_start_time);
125 if (time_diff >= GC_time_limit) {
126# ifdef CONDPRINT
127 if (GC_print_stats) {
128 GC_printf0("Abandoning stopped marking after ");
129 GC_printf1("%lu msecs", (unsigned long)time_diff);
130 GC_printf1("(attempt %d)\n", (unsigned long) GC_n_attempts);
131 }
132# endif
133 return(1);
134 }
135#endif
136 return(0);
137 }
138#endif /* !SMALL_CONFIG */
139
140/* Return the minimum number of words that must be allocated between */
141/* collections to amortize the collection cost. */
142static word min_words_allocd()
143{
144# ifdef THREADS
145 /* We punt, for now. */
146 register signed_word stack_size = 10000;
147# else
148 int dummy;
149 register signed_word stack_size = (ptr_t)(&dummy) - GC_stackbottom;
150# endif
151 word total_root_size; /* includes double stack size, */
152 /* since the stack is expensive */
153 /* to scan. */
154 word scan_size; /* Estimate of memory to be scanned */
155 /* during normal GC. */
156
157 if (stack_size < 0) stack_size = -stack_size;
158 total_root_size = 2 * stack_size + GC_root_size;
159 scan_size = BYTES_TO_WORDS(GC_heapsize - GC_large_free_bytes
160 + (GC_large_free_bytes >> 2)
161 /* use a bit more of large empty heap */
162 + total_root_size);
163 if (GC_incremental) {
164 return scan_size / (2 * GC_free_space_divisor);
165 } else {
166 return scan_size / GC_free_space_divisor;
167 }
168}
169
170/* Return the number of words allocated, adjusted for explicit storage */
171/* management, etc.. This number is used in deciding when to trigger */
172/* collections. */
173word GC_adj_words_allocd()
174{
175 register signed_word result;
176 register signed_word expl_managed =
177 BYTES_TO_WORDS((long)GC_non_gc_bytes
178 - (long)GC_non_gc_bytes_at_gc);
179
180 /* Don't count what was explicitly freed, or newly allocated for */
181 /* explicit management. Note that deallocating an explicitly */
182 /* managed object should not alter result, assuming the client */
183 /* is playing by the rules. */
184 result = (signed_word)GC_words_allocd
185 - (signed_word)GC_mem_freed - expl_managed;
186 if (result > (signed_word)GC_words_allocd) {
187 result = GC_words_allocd;
188 /* probably client bug or unfortunate scheduling */
189 }
190 result += GC_words_finalized;
191 /* We count objects enqueued for finalization as though they */
192 /* had been reallocated this round. Finalization is user */
193 /* visible progress. And if we don't count this, we have */
194 /* stability problems for programs that finalize all objects. */
195 result += GC_words_wasted;
196 /* This doesn't reflect useful work. But if there is lots of */
197 /* new fragmentation, the same is probably true of the heap, */
198 /* and the collection will be correspondingly cheaper. */
199 if (result < (signed_word)(GC_words_allocd >> 3)) {
200 /* Always count at least 1/8 of the allocations. We don't want */
201 /* to collect too infrequently, since that would inhibit */
202 /* coalescing of free storage blocks. */
203 /* This also makes us partially robust against client bugs. */
204 return(GC_words_allocd >> 3);
205 } else {
206 return(result);
207 }
208}
209
210
211/* Clear up a few frames worth of garbage left at the top of the stack. */
212/* This is used to prevent us from accidentally treating garbade left */
213/* on the stack by other parts of the collector as roots. This */
214/* differs from the code in misc.c, which actually tries to keep the */
215/* stack clear of long-lived, client-generated garbage. */
216void GC_clear_a_few_frames()
217{
218# define NWORDS 64
219 word frames[NWORDS];
220 register int i;
221
222 for (i = 0; i < NWORDS; i++) frames[i] = 0;
223}
224
225/* Have we allocated enough to amortize a collection? */
226GC_bool GC_should_collect()
227{
228 return(GC_adj_words_allocd() >= min_words_allocd());
229}
230
231
232void GC_notify_full_gc()
233{
234 if (GC_start_call_back != (void (*) GC_PROTO((void)))0) {
235 (*GC_start_call_back)();
236 }
237}
238
239GC_bool GC_is_full_gc = FALSE;
240
241/*
242 * Initiate a garbage collection if appropriate.
243 * Choose judiciously
244 * between partial, full, and stop-world collections.
245 * Assumes lock held, signals disabled.
246 */
247void GC_maybe_gc()
248{
249 static int n_partial_gcs = 0;
250
251 if (GC_should_collect()) {
252 if (!GC_incremental) {
253 GC_notify_full_gc();
254 GC_gcollect_inner();
255 n_partial_gcs = 0;
256 return;
257 } else {
258# ifdef PARALLEL_MARK
259 GC_wait_for_reclaim();
260# endif
261 if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {
262# ifdef CONDPRINT
263 if (GC_print_stats) {
264 GC_printf2(
265 "***>Full mark for collection %lu after %ld allocd bytes\n",
266 (unsigned long) GC_gc_no+1,
267 (long)WORDS_TO_BYTES(GC_words_allocd));
268 }
269# endif
270 GC_promote_black_lists();
271 (void)GC_reclaim_all((GC_stop_func)0, TRUE);
272 GC_clear_marks();
273 n_partial_gcs = 0;
274 GC_notify_full_gc();
275 GC_is_full_gc = TRUE;
276 } else {
277 n_partial_gcs++;
278 }
279 }
280 /* We try to mark with the world stopped. */
281 /* If we run out of time, this turns into */
282 /* incremental marking. */
283# ifndef NO_CLOCK
284 if (GC_time_limit != GC_TIME_UNLIMITED) { GET_TIME(GC_start_time); }
285# endif
286 if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED?
287 GC_never_stop_func : GC_timeout_stop_func)) {
288# ifdef SAVE_CALL_CHAIN
289 GC_save_callers(GC_last_stack);
290# endif
291 GC_finish_collection();
292 } else {
293 if (!GC_is_full_gc) {
294 /* Count this as the first attempt */
295 GC_n_attempts++;
296 }
297 }
298 }
299}
300
301
302/*
303 * Stop the world garbage collection. Assumes lock held, signals disabled.
304 * If stop_func is not GC_never_stop_func, then abort if stop_func returns TRUE.
305 */
306GC_bool GC_try_to_collect_inner(stop_func)
307GC_stop_func stop_func;
308{
309 if (GC_dont_gc) return FALSE;
310 if (GC_incremental && GC_collection_in_progress()) {
311# ifdef CONDPRINT
312 if (GC_print_stats) {
313 GC_printf0(
314 "GC_try_to_collect_inner: finishing collection in progress\n");
315 }
316# endif /* CONDPRINT */
317 /* Just finish collection already in progress. */
318 while(GC_collection_in_progress()) {
319 if (stop_func()) return(FALSE);
320 GC_collect_a_little_inner(1);
321 }
322 }
323# ifdef CONDPRINT
324 if (GC_print_stats) {
325 GC_printf2(
326 "Initiating full world-stop collection %lu after %ld allocd bytes\n",
327 (unsigned long) GC_gc_no+1,
328 (long)WORDS_TO_BYTES(GC_words_allocd));
329 }
330# endif
331 GC_promote_black_lists();
332 /* Make sure all blocks have been reclaimed, so sweep routines */
333 /* don't see cleared mark bits. */
334 /* If we're guaranteed to finish, then this is unnecessary. */
335 /* In the find_leak case, we have to finish to guarantee that */
336 /* previously unmarked objects are not reported as leaks. */
337# ifdef PARALLEL_MARK
338 GC_wait_for_reclaim();
339# endif
340 if ((GC_find_leak || stop_func != GC_never_stop_func)
341 && !GC_reclaim_all(stop_func, FALSE)) {
342 /* Aborted. So far everything is still consistent. */
343 return(FALSE);
344 }
345 GC_invalidate_mark_state(); /* Flush mark stack. */
346 GC_clear_marks();
347# ifdef SAVE_CALL_CHAIN
348 GC_save_callers(GC_last_stack);
349# endif
350 GC_is_full_gc = TRUE;
351 if (!GC_stopped_mark(stop_func)) {
352 if (!GC_incremental) {
353 /* We're partially done and have no way to complete or use */
354 /* current work. Reestablish invariants as cheaply as */
355 /* possible. */
356 GC_invalidate_mark_state();
357 GC_unpromote_black_lists();
358 } /* else we claim the world is already still consistent. We'll */
359 /* finish incrementally. */
360 return(FALSE);
361 }
362 GC_finish_collection();
363 return(TRUE);
364}
365
366
367
368/*
369 * Perform n units of garbage collection work. A unit is intended to touch
370 * roughly GC_RATE pages. Every once in a while, we do more than that.
371 * This needa to be a fairly large number with our current incremental
372 * GC strategy, since otherwise we allocate too much during GC, and the
373 * cleanup gets expensive.
374 */
375# define GC_RATE 10
376# define MAX_PRIOR_ATTEMPTS 1
377 /* Maximum number of prior attempts at world stop marking */
378 /* A value of 1 means that we finish the second time, no matter */
379 /* how long it takes. Doesn't count the initial root scan */
380 /* for a full GC. */
381
382int GC_deficit = 0; /* The number of extra calls to GC_mark_some */
383 /* that we have made. */
384
385void GC_collect_a_little_inner(n)
386int n;
387{
388 register int i;
389
390 if (GC_dont_gc) return;
391 if (GC_incremental && GC_collection_in_progress()) {
392 for (i = GC_deficit; i < GC_RATE*n; i++) {
393 if (GC_mark_some((ptr_t)0)) {
394 /* Need to finish a collection */
395# ifdef SAVE_CALL_CHAIN
396 GC_save_callers(GC_last_stack);
397# endif
398# ifdef PARALLEL_MARK
399 GC_wait_for_reclaim();
400# endif
401 if (GC_n_attempts < MAX_PRIOR_ATTEMPTS
402 && GC_time_limit != GC_TIME_UNLIMITED) {
403 GET_TIME(GC_start_time);
404 if (!GC_stopped_mark(GC_timeout_stop_func)) {
405 GC_n_attempts++;
406 break;
407 }
408 } else {
409 (void)GC_stopped_mark(GC_never_stop_func);
410 }
411 GC_finish_collection();
412 break;
413 }
414 }
415 if (GC_deficit > 0) GC_deficit -= GC_RATE*n;
416 if (GC_deficit < 0) GC_deficit = 0;
417 } else {
418 GC_maybe_gc();
419 }
420}
421
422int GC_collect_a_little GC_PROTO(())
423{
424 int result;
425 DCL_LOCK_STATE;
426
427 DISABLE_SIGNALS();
428 LOCK();
429 GC_collect_a_little_inner(1);
430 result = (int)GC_collection_in_progress();
431 UNLOCK();
432 ENABLE_SIGNALS();
433 return(result);
434}
435
436/*
437 * Assumes lock is held, signals are disabled.
438 * We stop the world.
439 * If stop_func() ever returns TRUE, we may fail and return FALSE.
440 * Increment GC_gc_no if we succeed.
441 */
442GC_bool GC_stopped_mark(stop_func)
443GC_stop_func stop_func;
444{
445 register int i;
446 int dummy;
447# if defined(PRINTTIMES) || defined(CONDPRINT)
448 CLOCK_TYPE start_time, current_time;
449# endif
450
451# if defined(REGISTER_LIBRARIES_EARLY)
452 GC_cond_register_dynamic_libraries();
453# endif
454 STOP_WORLD();
455# ifdef PRINTTIMES
456 GET_TIME(start_time);
457# endif
458# if defined(CONDPRINT) && !defined(PRINTTIMES)
459 if (GC_print_stats) GET_TIME(start_time);
460# endif
461# ifdef CONDPRINT
462 if (GC_print_stats) {
463 GC_printf1("--> Marking for collection %lu ",
464 (unsigned long) GC_gc_no + 1);
465 GC_printf2("after %lu allocd bytes + %lu wasted bytes\n",
466 (unsigned long) WORDS_TO_BYTES(GC_words_allocd),
467 (unsigned long) WORDS_TO_BYTES(GC_words_wasted));
468 }
469# endif
470# ifdef MAKE_BACK_GRAPH
471 if (GC_print_back_height) {
472 GC_build_back_graph();
473 }
474# endif
475
476 /* Mark from all roots. */
477 /* Minimize junk left in my registers and on the stack */
478 GC_clear_a_few_frames();
479 GC_noop(0,0,0,0,0,0);
480 GC_initiate_gc();
481 for(i = 0;;i++) {
482 if ((*stop_func)()) {
483# ifdef CONDPRINT
484 if (GC_print_stats) {
485 GC_printf0("Abandoned stopped marking after ");
486 GC_printf1("%lu iterations\n",
487 (unsigned long)i);
488 }
489# endif
490 GC_deficit = i; /* Give the mutator a chance. */
491 START_WORLD();
492 return(FALSE);
493 }
494 if (GC_mark_some((ptr_t)(&dummy))) break;
495 }
496
497 GC_gc_no++;
498# ifdef PRINTSTATS
499 GC_printf2("Collection %lu reclaimed %ld bytes",
500 (unsigned long) GC_gc_no - 1,
501 (long)WORDS_TO_BYTES(GC_mem_found));
502# else
503# ifdef CONDPRINT
504 if (GC_print_stats) {
505 GC_printf1("Collection %lu finished", (unsigned long) GC_gc_no - 1);
506 }
507# endif
508# endif /* !PRINTSTATS */
509# ifdef CONDPRINT
510 if (GC_print_stats) {
511 GC_printf1(" ---> heapsize = %lu bytes\n",
512 (unsigned long) GC_heapsize);
513 /* Printf arguments may be pushed in funny places. Clear the */
514 /* space. */
515 GC_printf0("");
516 }
517# endif /* CONDPRINT */
518
519 /* Check all debugged objects for consistency */
520 if (GC_debugging_started) {
521 (*GC_check_heap)();
522 }
523
524# ifdef PRINTTIMES
525 GET_TIME(current_time);
526 GC_printf1("World-stopped marking took %lu msecs\n",
527 MS_TIME_DIFF(current_time,start_time));
528# else
529# ifdef CONDPRINT
530 if (GC_print_stats) {
531 GET_TIME(current_time);
532 GC_printf1("World-stopped marking took %lu msecs\n",
533 MS_TIME_DIFF(current_time,start_time));
534 }
535# endif
536# endif
537 START_WORLD();
538 return(TRUE);
539}
540
541/* Set all mark bits for the free list whose first entry is q */
542#ifdef __STDC__
543 void GC_set_fl_marks(ptr_t q)
544#else
545 void GC_set_fl_marks(q)
546 ptr_t q;
547#endif
548{
549 ptr_t p;
550 struct hblk * h, * last_h = 0;
551 hdr *hhdr;
552 int word_no;
553
554 for (p = q; p != 0; p = obj_link(p)){
555 h = HBLKPTR(p);
556 if (h != last_h) {
557 last_h = h;
558 hhdr = HDR(h);
559 }
560 word_no = (((word *)p) - ((word *)h));
561 set_mark_bit_from_hdr(hhdr, word_no);
562 }
563}
564
565/* Clear all mark bits for the free list whose first entry is q */
566/* Decrement GC_mem_found by number of words on free list. */
567#ifdef __STDC__
568 void GC_clear_fl_marks(ptr_t q)
569#else
570 void GC_clear_fl_marks(q)
571 ptr_t q;
572#endif
573{
574 ptr_t p;
575 struct hblk * h, * last_h = 0;
576 hdr *hhdr;
577 int word_no;
578
579 for (p = q; p != 0; p = obj_link(p)){
580 h = HBLKPTR(p);
581 if (h != last_h) {
582 last_h = h;
583 hhdr = HDR(h);
584 }
585 word_no = (((word *)p) - ((word *)h));
586 clear_mark_bit_from_hdr(hhdr, word_no);
587# ifdef GATHERSTATS
588 GC_mem_found -= hhdr -> hb_sz;
589# endif
590 }
591}
592
593/* Finish up a collection. Assumes lock is held, signals are disabled, */
594/* but the world is otherwise running. */
595void GC_finish_collection()
596{
597# ifdef PRINTTIMES
598 CLOCK_TYPE start_time;
599 CLOCK_TYPE finalize_time;
600 CLOCK_TYPE done_time;
601
602 GET_TIME(start_time);
603 finalize_time = start_time;
604# endif
605
606# ifdef GATHERSTATS
607 GC_mem_found = 0;
608# endif
609# if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
610 if (getenv("GC_PRINT_ADDRESS_MAP") != 0) {
611 GC_print_address_map();
612 }
613# endif
614 if (GC_find_leak) {
615 /* Mark all objects on the free list. All objects should be */
616 /* marked when we're done. */
617 {
618 register word size; /* current object size */
619 int kind;
620 ptr_t q;
621
622 for (kind = 0; kind < GC_n_kinds; kind++) {
623 for (size = 1; size <= MAXOBJSZ; size++) {
624 q = GC_obj_kinds[kind].ok_freelist[size];
625 if (q != 0) GC_set_fl_marks(q);
626 }
627 }
628 }
629 GC_start_reclaim(TRUE);
630 /* The above just checks; it doesn't really reclaim anything. */
631 }
632
633 GC_finalize();
634# ifdef STUBBORN_ALLOC
635 GC_clean_changing_list();
636# endif
637
638# ifdef PRINTTIMES
639 GET_TIME(finalize_time);
640# endif
641
642 if (GC_print_back_height) {
643# ifdef MAKE_BACK_GRAPH
644 GC_traverse_back_graph();
645# else
646# ifndef SMALL_CONFIG
647 GC_err_printf0("Back height not available: "
648 "Rebuild collector with -DMAKE_BACK_GRAPH\n");
649# endif
650# endif
651 }
652
653 /* Clear free list mark bits, in case they got accidentally marked */
654 /* (or GC_find_leak is set and they were intentionally marked). */
655 /* Also subtract memory remaining from GC_mem_found count. */
656 /* Note that composite objects on free list are cleared. */
657 /* Thus accidentally marking a free list is not a problem; only */
658 /* objects on the list itself will be marked, and that's fixed here. */
659 {
660 register word size; /* current object size */
661 register ptr_t q; /* pointer to current object */
662 int kind;
663
664 for (kind = 0; kind < GC_n_kinds; kind++) {
665 for (size = 1; size <= MAXOBJSZ; size++) {
666 q = GC_obj_kinds[kind].ok_freelist[size];
667 if (q != 0) GC_clear_fl_marks(q);
668 }
669 }
670 }
671
672
673# ifdef PRINTSTATS
674 GC_printf1("Bytes recovered before sweep - f.l. count = %ld\n",
675 (long)WORDS_TO_BYTES(GC_mem_found));
676# endif
677 /* Reconstruct free lists to contain everything not marked */
678 GC_start_reclaim(FALSE);
679 if (GC_is_full_gc) {
680 GC_used_heap_size_after_full = USED_HEAP_SIZE;
681 GC_need_full_gc = FALSE;
682 } else {
683 GC_need_full_gc =
684 BYTES_TO_WORDS(USED_HEAP_SIZE - GC_used_heap_size_after_full)
685 > min_words_allocd();
686 }
687
688# ifdef PRINTSTATS
689 GC_printf2(
690 "Immediately reclaimed %ld bytes in heap of size %lu bytes",
691 (long)WORDS_TO_BYTES(GC_mem_found),
692 (unsigned long)GC_heapsize);
693# ifdef USE_MUNMAP
694 GC_printf1("(%lu unmapped)", GC_unmapped_bytes);
695# endif
696 GC_printf2(
697 "\n%lu (atomic) + %lu (composite) collectable bytes in use\n",
698 (unsigned long)WORDS_TO_BYTES(GC_atomic_in_use),
699 (unsigned long)WORDS_TO_BYTES(GC_composite_in_use));
700# endif
701
702 GC_n_attempts = 0;
703 GC_is_full_gc = FALSE;
704 /* Reset or increment counters for next cycle */
705 GC_words_allocd_before_gc += GC_words_allocd;
706 GC_non_gc_bytes_at_gc = GC_non_gc_bytes;
707 GC_words_allocd = 0;
708 GC_words_wasted = 0;
709 GC_mem_freed = 0;
710
711# ifdef USE_MUNMAP
712 GC_unmap_old();
713# endif
714# ifdef PRINTTIMES
715 GET_TIME(done_time);
716 GC_printf2("Finalize + initiate sweep took %lu + %lu msecs\n",
717 MS_TIME_DIFF(finalize_time,start_time),
718 MS_TIME_DIFF(done_time,finalize_time));
719# endif
720}
721
722/* Externally callable routine to invoke full, stop-world collection */
723# if defined(__STDC__) || defined(__cplusplus)
724 int GC_try_to_collect(GC_stop_func stop_func)
725# else
726 int GC_try_to_collect(stop_func)
727 GC_stop_func stop_func;
728# endif
729{
730 int result;
731 DCL_LOCK_STATE;
732
733 GC_INVOKE_FINALIZERS();
734 DISABLE_SIGNALS();
735 LOCK();
736 ENTER_GC();
737 if (!GC_is_initialized) GC_init_inner();
738 /* Minimize junk left in my registers */
739 GC_noop(0,0,0,0,0,0);
740 result = (int)GC_try_to_collect_inner(stop_func);
741 EXIT_GC();
742 UNLOCK();
743 ENABLE_SIGNALS();
744 if(result) GC_INVOKE_FINALIZERS();
745 return(result);
746}
747
748void GC_gcollect GC_PROTO(())
749{
750 GC_notify_full_gc();
751 (void)GC_try_to_collect(GC_never_stop_func);
752}
753
754word GC_n_heap_sects = 0; /* Number of sections currently in heap. */
755
756/*
757 * Use the chunk of memory starting at p of size bytes as part of the heap.
758 * Assumes p is HBLKSIZE aligned, and bytes is a multiple of HBLKSIZE.
759 */
760void GC_add_to_heap(p, bytes)
761struct hblk *p;
762word bytes;
763{
764 word words;
765 hdr * phdr;
766
767 if (GC_n_heap_sects >= MAX_HEAP_SECTS) {
768 ABORT("Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS");
769 }
770 phdr = GC_install_header(p);
771 if (0 == phdr) {
772 /* This is extremely unlikely. Can't add it. This will */
773 /* almost certainly result in a 0 return from the allocator, */
774 /* which is entirely appropriate. */
775 return;
776 }
777 GC_heap_sects[GC_n_heap_sects].hs_start = (ptr_t)p;
778 GC_heap_sects[GC_n_heap_sects].hs_bytes = bytes;
779 GC_n_heap_sects++;
780 words = BYTES_TO_WORDS(bytes);
781 phdr -> hb_sz = words;
782 phdr -> hb_map = (unsigned char *)1; /* A value != GC_invalid_map */
783 phdr -> hb_flags = 0;
784 GC_freehblk(p);
785 GC_heapsize += bytes;
786 if ((ptr_t)p <= (ptr_t)GC_least_plausible_heap_addr
787 || GC_least_plausible_heap_addr == 0) {
788 GC_least_plausible_heap_addr = (GC_PTR)((ptr_t)p - sizeof(word));
789 /* Making it a little smaller than necessary prevents */
790 /* us from getting a false hit from the variable */
791 /* itself. There's some unintentional reflection */
792 /* here. */
793 }
794 if ((ptr_t)p + bytes >= (ptr_t)GC_greatest_plausible_heap_addr) {
795 GC_greatest_plausible_heap_addr = (GC_PTR)((ptr_t)p + bytes);
796 }
797}
798
799# if !defined(NO_DEBUGGING)
800void GC_print_heap_sects()
801{
802 register unsigned i;
803
804 GC_printf1("Total heap size: %lu\n", (unsigned long) GC_heapsize);
805 for (i = 0; i < GC_n_heap_sects; i++) {
806 unsigned long start = (unsigned long) GC_heap_sects[i].hs_start;
807 unsigned long len = (unsigned long) GC_heap_sects[i].hs_bytes;
808 struct hblk *h;
809 unsigned nbl = 0;
810
811 GC_printf3("Section %ld from 0x%lx to 0x%lx ", (unsigned long)i,
812 start, (unsigned long)(start + len));
813 for (h = (struct hblk *)start; h < (struct hblk *)(start + len); h++) {
814 if (GC_is_black_listed(h, HBLKSIZE)) nbl++;
815 }
816 GC_printf2("%lu/%lu blacklisted\n", (unsigned long)nbl,
817 (unsigned long)(len/HBLKSIZE));
818 }
819}
820# endif
821
822GC_PTR GC_least_plausible_heap_addr = (GC_PTR)ONES;
823GC_PTR GC_greatest_plausible_heap_addr = 0;
824
825ptr_t GC_max(x,y)
826ptr_t x, y;
827{
828 return(x > y? x : y);
829}
830
831ptr_t GC_min(x,y)
832ptr_t x, y;
833{
834 return(x < y? x : y);
835}
836
837# if defined(__STDC__) || defined(__cplusplus)
838 void GC_set_max_heap_size(GC_word n)
839# else
840 void GC_set_max_heap_size(n)
841 GC_word n;
842# endif
843{
844 GC_max_heapsize = n;
845}
846
847GC_word GC_max_retries = 0;
848
849/*
850 * this explicitly increases the size of the heap. It is used
851 * internally, but may also be invoked from GC_expand_hp by the user.
852 * The argument is in units of HBLKSIZE.
853 * Tiny values of n are rounded up.
854 * Returns FALSE on failure.
855 */
856GC_bool GC_expand_hp_inner(n)
857word n;
858{
859 word bytes;
860 struct hblk * space;
861 word expansion_slop; /* Number of bytes by which we expect the */
862 /* heap to expand soon. */
863
864 if (n < MINHINCR) n = MINHINCR;
865 bytes = n * HBLKSIZE;
866 /* Make sure bytes is a multiple of GC_page_size */
867 {
868 word mask = GC_page_size - 1;
869 bytes += mask;
870 bytes &= ~mask;
871 }
872
873 if (GC_max_heapsize != 0 && GC_heapsize + bytes > GC_max_heapsize) {
874 /* Exceeded self-imposed limit */
875 return(FALSE);
876 }
877 space = GET_MEM(bytes);
878 if( space == 0 ) {
879# ifdef CONDPRINT
880 if (GC_print_stats) {
881 GC_printf1("Failed to expand heap by %ld bytes\n",
882 (unsigned long)bytes);
883 }
884# endif
885 return(FALSE);
886 }
887# ifdef CONDPRINT
888 if (GC_print_stats) {
889 GC_printf2("Increasing heap size by %lu after %lu allocated bytes\n",
890 (unsigned long)bytes,
891 (unsigned long)WORDS_TO_BYTES(GC_words_allocd));
892# ifdef UNDEFINED
893 GC_printf1("Root size = %lu\n", GC_root_size);
894 GC_print_block_list(); GC_print_hblkfreelist();
895 GC_printf0("\n");
896# endif
897 }
898# endif
899 expansion_slop = 8 * WORDS_TO_BYTES(min_words_allocd());
900 if (5 * HBLKSIZE * MAXHINCR > expansion_slop) {
901 expansion_slop = 5 * HBLKSIZE * MAXHINCR;
902 }
903 if (GC_last_heap_addr == 0 && !((word)space & SIGNB)
904 || GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space) {
905 /* Assume the heap is growing up */
906 GC_greatest_plausible_heap_addr =
907 GC_max(GC_greatest_plausible_heap_addr,
908 (ptr_t)space + bytes + expansion_slop);
909 } else {
910 /* Heap is growing down */
911 GC_least_plausible_heap_addr =
912 GC_min(GC_least_plausible_heap_addr,
913 (ptr_t)space - expansion_slop);
914 }
915 GC_prev_heap_addr = GC_last_heap_addr;
916 GC_last_heap_addr = (ptr_t)space;
917 GC_add_to_heap(space, bytes);
918 return(TRUE);
919}
920
921/* Really returns a bool, but it's externally visible, so that's clumsy. */
922/* Arguments is in bytes. */
923# if defined(__STDC__) || defined(__cplusplus)
924 int GC_expand_hp(size_t bytes)
925# else
926 int GC_expand_hp(bytes)
927 size_t bytes;
928# endif
929{
930 int result;
931 DCL_LOCK_STATE;
932
933 DISABLE_SIGNALS();
934 LOCK();
935 if (!GC_is_initialized) GC_init_inner();
936 result = (int)GC_expand_hp_inner(divHBLKSZ((word)bytes));
937 if (result) GC_requested_heapsize += bytes;
938 UNLOCK();
939 ENABLE_SIGNALS();
940 return(result);
941}
942
943unsigned GC_fail_count = 0;
944 /* How many consecutive GC/expansion failures? */
945 /* Reset by GC_allochblk. */
946
947GC_bool GC_collect_or_expand(needed_blocks, ignore_off_page)
948word needed_blocks;
949GC_bool ignore_off_page;
950{
951 if (!GC_incremental && !GC_dont_gc &&
952 (GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) {
953 GC_notify_full_gc();
954 GC_gcollect_inner();
955 } else {
956 word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
957 + needed_blocks;
958
959 if (blocks_to_get > MAXHINCR) {
960 word slop;
961
962 if (ignore_off_page) {
963 slop = 4;
964 } else {
965 slop = 2*divHBLKSZ(BL_LIMIT);
966 if (slop > needed_blocks) slop = needed_blocks;
967 }
968 if (needed_blocks + slop > MAXHINCR) {
969 blocks_to_get = needed_blocks + slop;
970 } else {
971 blocks_to_get = MAXHINCR;
972 }
973 }
974 if (!GC_expand_hp_inner(blocks_to_get)
975 && !GC_expand_hp_inner(needed_blocks)) {
976 if (GC_fail_count++ < GC_max_retries) {
977 WARN("Out of Memory! Trying to continue ...\n", 0);
978 GC_notify_full_gc();
979 GC_gcollect_inner();
980 } else {
981# if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC)
982 WARN("Out of Memory! Returning NIL!\n", 0);
983# endif
984 return(FALSE);
985 }
986 } else {
987# ifdef CONDPRINT
988 if (GC_fail_count && GC_print_stats) {
989 GC_printf0("Memory available again ...\n");
990 }
991# endif
992 }
993 }
994 return(TRUE);
995}
996
997/*
998 * Make sure the object free list for sz is not empty.
999 * Return a pointer to the first object on the free list.
1000 * The object MUST BE REMOVED FROM THE FREE LIST BY THE CALLER.
1001 * Assumes we hold the allocator lock and signals are disabled.
1002 *
1003 */
1004ptr_t GC_allocobj(sz, kind)
1005word sz;
1006int kind;
1007{
1008 register ptr_t * flh = &(GC_obj_kinds[kind].ok_freelist[sz]);
1009
1010 if (sz == 0) return(0);
1011
1012 while (*flh == 0) {
1013 ENTER_GC();
1014 /* Do our share of marking work */
1015 if(GC_incremental && !GC_dont_gc) GC_collect_a_little_inner(1);
1016 /* Sweep blocks for objects of this size */
1017 GC_continue_reclaim(sz, kind);
1018 EXIT_GC();
1019 if (*flh == 0) {
1020 GC_new_hblk(sz, kind);
1021 }
1022 if (*flh == 0) {
1023 ENTER_GC();
1024 if (!GC_collect_or_expand((word)1,FALSE)) {
1025 EXIT_GC();
1026 return(0);
1027 }
1028 EXIT_GC();
1029 }
1030 }
1031
1032 return(*flh);
1033}
Note: See TracBrowser for help on using the repository browser.