source: trunk/third/gcc/boehm-gc/misc.c @ 18474

Revision 18474, 29.6 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18473, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
4 * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.
5 *
6 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
7 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
8 *
9 * Permission is hereby granted to use or copy this program
10 * for any purpose,  provided the above notices are retained on all copies.
11 * Permission to modify the code and to distribute modified code is granted,
12 * provided the above notices are retained, and a notice that the code was
13 * modified is included with the above copyright notice.
14 */
15/* Boehm, July 31, 1995 5:02 pm PDT */
16
17
18#include <stdio.h>
19#include <limits.h>
20#ifndef _WIN32_WCE
21#include <signal.h>
22#endif
23
24#define I_HIDE_POINTERS /* To make GC_call_with_alloc_lock visible */
25#include "private/gc_pmark.h"
26
27#ifdef GC_SOLARIS_THREADS
28# include <sys/syscall.h>
29#endif
30#if defined(MSWIN32) || defined(MSWINCE)
31# define WIN32_LEAN_AND_MEAN
32# define NOSERVICE
33# include <windows.h>
34# include <tchar.h>
35#endif
36
37# ifdef THREADS
38#   ifdef PCR
39#     include "il/PCR_IL.h"
40      PCR_Th_ML GC_allocate_ml;
41#   else
42#     ifdef SRC_M3
43        /* Critical section counter is defined in the M3 runtime        */
44        /* That's all we use.                                           */
45#     else
46#       ifdef GC_SOLARIS_THREADS
47          mutex_t GC_allocate_ml;       /* Implicitly initialized.      */
48#       else
49#          ifdef GC_WIN32_THREADS
50#             if !defined(GC_NOT_DLL) && (defined(_DLL) || defined(GC_DLL))
51                 __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
52#             else
53                 CRITICAL_SECTION GC_allocate_ml;
54#             endif
55#          else
56#             if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS)
57#               if defined(USE_SPIN_LOCK)
58                  pthread_t GC_lock_holder = NO_THREAD;
59#               else
60                  pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
61                  pthread_t GC_lock_holder = NO_THREAD;
62                        /* Used only for assertions, and to prevent      */
63                        /* recursive reentry in the system call wrapper. */
64#               endif
65#             else
66                  --> declare allocator lock here
67#             endif
68#          endif
69#       endif
70#     endif
71#   endif
72# endif
73
74#if defined(NOSYS) || defined(ECOS)
75#undef STACKBASE
76#endif
77
78GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */;
79
80
81GC_bool GC_debugging_started = FALSE;
82        /* defined here so we don't have to load debug_malloc.o */
83
84void (*GC_check_heap) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
85
86void (*GC_start_call_back) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
87
88ptr_t GC_stackbottom = 0;
89
90#ifdef IA64
91  ptr_t GC_register_stackbottom = 0;
92#endif
93
94GC_bool GC_dont_gc = 0;
95
96GC_bool GC_dont_precollect = 0;
97
98GC_bool GC_quiet = 0;
99
100GC_bool GC_print_stats = 0;
101
102GC_bool GC_print_back_height = 0;
103
104#ifdef FIND_LEAK
105  int GC_find_leak = 1;
106#else
107  int GC_find_leak = 0;
108#endif
109
110#ifdef ALL_INTERIOR_POINTERS
111  int GC_all_interior_pointers = 1;
112#else
113  int GC_all_interior_pointers = 0;
114#endif
115
116long GC_large_alloc_warn_interval = 5;
117        /* Interval between unsuppressed warnings.      */
118
119long GC_large_alloc_warn_suppressed = 0;
120        /* Number of warnings suppressed so far.        */
121
122/*ARGSUSED*/
123GC_PTR GC_default_oom_fn GC_PROTO((size_t bytes_requested))
124{
125    return(0);
126}
127
128GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested)) = GC_default_oom_fn;
129
130extern signed_word GC_mem_found;
131
132# ifdef MERGE_SIZES
133    /* Set things up so that GC_size_map[i] >= words(i),                */
134    /* but not too much bigger                                          */
135    /* and so that size_map contains relatively few distinct entries    */
136    /* This is stolen from Russ Atkinson's Cedar quantization           */
137    /* alogrithm (but we precompute it).                                */
138
139
140    void GC_init_size_map()
141    {
142        register unsigned i;
143
144        /* Map size 0 to something bigger.                      */
145        /* This avoids problems at lower levels.                */
146        /* One word objects don't have to be 2 word aligned,    */
147        /* unless we're using mark bytes.                       */
148          for (i = 0; i < sizeof(word); i++) {
149              GC_size_map[i] = MIN_WORDS;
150          }
151#         if MIN_WORDS > 1
152            GC_size_map[sizeof(word)] = MIN_WORDS;
153#         else
154            GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word));
155#         endif
156        for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) {
157            GC_size_map[i] = ALIGNED_WORDS(i);
158        }
159        for (i = 8*sizeof(word) + 1; i <= 16 * sizeof(word); i++) {
160              GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
161        }
162#       ifdef GC_GCJ_SUPPORT
163           /* Make all sizes up to 32 words predictable, so that a      */
164           /* compiler can statically perform the same computation,     */
165           /* or at least a computation that results in similar size    */
166           /* classes.                                                  */
167           for (i = 16*sizeof(word) + 1; i <= 32 * sizeof(word); i++) {
168              GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 3) & (~3);
169           }
170#       endif
171        /* We leave the rest of the array to be filled in on demand. */
172    }
173   
174    /* Fill in additional entries in GC_size_map, including the ith one */
175    /* We assume the ith entry is currently 0.                          */
176    /* Note that a filled in section of the array ending at n always    */
177    /* has length at least n/4.                                         */
178    void GC_extend_size_map(i)
179    word i;
180    {
181        word orig_word_sz = ROUNDED_UP_WORDS(i);
182        word word_sz = orig_word_sz;
183        register word byte_sz = WORDS_TO_BYTES(word_sz);
184                                /* The size we try to preserve.         */
185                                /* Close to to i, unless this would     */
186                                /* introduce too many distinct sizes.   */
187        word smaller_than_i = byte_sz - (byte_sz >> 3);
188        word much_smaller_than_i = byte_sz - (byte_sz >> 2);
189        register word low_limit;        /* The lowest indexed entry we  */
190                                        /* initialize.                  */
191        register word j;
192       
193        if (GC_size_map[smaller_than_i] == 0) {
194            low_limit = much_smaller_than_i;
195            while (GC_size_map[low_limit] != 0) low_limit++;
196        } else {
197            low_limit = smaller_than_i + 1;
198            while (GC_size_map[low_limit] != 0) low_limit++;
199            word_sz = ROUNDED_UP_WORDS(low_limit);
200            word_sz += word_sz >> 3;
201            if (word_sz < orig_word_sz) word_sz = orig_word_sz;
202        }
203#       ifdef ALIGN_DOUBLE
204            word_sz += 1;
205            word_sz &= ~1;
206#       endif
207        if (word_sz > MAXOBJSZ) {
208            word_sz = MAXOBJSZ;
209        }
210        /* If we can fit the same number of larger objects in a block,  */
211        /* do so.                                                       */
212        {
213            size_t number_of_objs = BODY_SZ/word_sz;
214            word_sz = BODY_SZ/number_of_objs;
215#           ifdef ALIGN_DOUBLE
216                word_sz &= ~1;
217#           endif
218        }
219        byte_sz = WORDS_TO_BYTES(word_sz);
220        if (GC_all_interior_pointers) {
221            /* We need one extra byte; don't fill in GC_size_map[byte_sz] */
222            byte_sz--;
223        }
224
225        for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz; 
226    }
227# endif
228
229
230/*
231 * The following is a gross hack to deal with a problem that can occur
232 * on machines that are sloppy about stack frame sizes, notably SPARC.
233 * Bogus pointers may be written to the stack and not cleared for
234 * a LONG time, because they always fall into holes in stack frames
235 * that are not written.  We partially address this by clearing
236 * sections of the stack whenever we get control.
237 */
238word GC_stack_last_cleared = 0; /* GC_no when we last did this */
239# ifdef THREADS
240#   define BIG_CLEAR_SIZE 2048  /* Clear this much now and then.        */
241#   define SMALL_CLEAR_SIZE 256 /* Clear this much every time.          */
242# endif
243# define CLEAR_SIZE 213  /* Granularity for GC_clear_stack_inner */
244# define DEGRADE_RATE 50
245
246word GC_min_sp;         /* Coolest stack pointer value from which we've */
247                        /* already cleared the stack.                   */
248                       
249word GC_high_water;
250                        /* "hottest" stack pointer value we have seen   */
251                        /* recently.  Degrades over time.               */
252
253word GC_words_allocd_at_reset;
254
255#if defined(ASM_CLEAR_CODE)
256  extern ptr_t GC_clear_stack_inner();
257#else 
258/* Clear the stack up to about limit.  Return arg. */
259/*ARGSUSED*/
260ptr_t GC_clear_stack_inner(arg, limit)
261ptr_t arg;
262word limit;
263{
264    word dummy[CLEAR_SIZE];
265   
266    BZERO(dummy, CLEAR_SIZE*sizeof(word));
267    if ((word)(dummy) COOLER_THAN limit) {
268        (void) GC_clear_stack_inner(arg, limit);
269    }
270    /* Make sure the recursive call is not a tail call, and the bzero   */
271    /* call is not recognized as dead code.                             */
272    GC_noop1((word)dummy);
273    return(arg);
274}
275#endif
276
277/* Clear some of the inaccessible part of the stack.  Returns its       */
278/* argument, so it can be used in a tail call position, hence clearing  */
279/* another frame.                                                       */
280ptr_t GC_clear_stack(arg)
281ptr_t arg;
282{
283    register word sp = (word)GC_approx_sp();  /* Hotter than actual sp */
284#   ifdef THREADS
285        word dummy[SMALL_CLEAR_SIZE];
286        static unsigned random_no = 0;
287                                 /* Should be more random than it is ... */
288                                 /* Used to occasionally clear a bigger  */
289                                 /* chunk.                               */
290#   endif
291    register word limit;
292   
293#   define SLOP 400
294        /* Extra bytes we clear every time.  This clears our own        */
295        /* activation record, and should cause more frequent            */
296        /* clearing near the cold end of the stack, a good thing.       */
297#   define GC_SLOP 4000
298        /* We make GC_high_water this much hotter than we really saw    */
299        /* saw it, to cover for GC noise etc. above our current frame.  */
300#   define CLEAR_THRESHOLD 100000
301        /* We restart the clearing process after this many bytes of     */
302        /* allocation.  Otherwise very heavily recursive programs       */
303        /* with sparse stacks may result in heaps that grow almost      */
304        /* without bounds.  As the heap gets larger, collection         */
305        /* frequency decreases, thus clearing frequency would decrease, */
306        /* thus more junk remains accessible, thus the heap gets        */
307        /* larger ...                                                   */
308# ifdef THREADS
309    if (++random_no % 13 == 0) {
310        limit = sp;
311        MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word));
312        limit &= ~0xf;  /* Make it sufficiently aligned for assembly    */
313                        /* implementations of GC_clear_stack_inner.     */
314        return GC_clear_stack_inner(arg, limit);
315    } else {
316        BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word));
317        return arg;
318    }
319# else
320    if (GC_gc_no > GC_stack_last_cleared) {
321        /* Start things over, so we clear the entire stack again */
322        if (GC_stack_last_cleared == 0) GC_high_water = (word) GC_stackbottom;
323        GC_min_sp = GC_high_water;
324        GC_stack_last_cleared = GC_gc_no;
325        GC_words_allocd_at_reset = GC_words_allocd;
326    }
327    /* Adjust GC_high_water */
328        MAKE_COOLER(GC_high_water, WORDS_TO_BYTES(DEGRADE_RATE) + GC_SLOP);
329        if (sp HOTTER_THAN GC_high_water) {
330            GC_high_water = sp;
331        }
332        MAKE_HOTTER(GC_high_water, GC_SLOP);
333    limit = GC_min_sp;
334    MAKE_HOTTER(limit, SLOP);
335    if (sp COOLER_THAN limit) {
336        limit &= ~0xf;  /* Make it sufficiently aligned for assembly    */
337                        /* implementations of GC_clear_stack_inner.     */
338        GC_min_sp = sp;
339        return(GC_clear_stack_inner(arg, limit));
340    } else if (WORDS_TO_BYTES(GC_words_allocd - GC_words_allocd_at_reset)
341               > CLEAR_THRESHOLD) {
342        /* Restart clearing process, but limit how much clearing we do. */
343        GC_min_sp = sp;
344        MAKE_HOTTER(GC_min_sp, CLEAR_THRESHOLD/4);
345        if (GC_min_sp HOTTER_THAN GC_high_water) GC_min_sp = GC_high_water;
346        GC_words_allocd_at_reset = GC_words_allocd;
347    } 
348    return(arg);
349# endif
350}
351
352
353/* Return a pointer to the base address of p, given a pointer to a      */
354/* an address within an object.  Return 0 o.w.                          */
355# ifdef __STDC__
356    GC_PTR GC_base(GC_PTR p)
357# else
358    GC_PTR GC_base(p)
359    GC_PTR p;
360# endif
361{
362    register word r;
363    register struct hblk *h;
364    register bottom_index *bi;
365    register hdr *candidate_hdr;
366    register word limit;
367   
368    r = (word)p;
369    if (!GC_is_initialized) return 0;
370    h = HBLKPTR(r);
371    GET_BI(r, bi);
372    candidate_hdr = HDR_FROM_BI(bi, r);
373    if (candidate_hdr == 0) return(0);
374    /* If it's a pointer to the middle of a large object, move it       */
375    /* to the beginning.                                                */
376        while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {
377           h = FORWARDED_ADDR(h,candidate_hdr);
378           r = (word)h;
379           candidate_hdr = HDR(h);
380        }
381    if (candidate_hdr -> hb_map == GC_invalid_map) return(0);
382    /* Make sure r points to the beginning of the object */
383        r &= ~(WORDS_TO_BYTES(1) - 1);
384        {
385            register int offset = HBLKDISPL(r);
386            register signed_word sz = candidate_hdr -> hb_sz;
387            register signed_word map_entry;
388             
389            map_entry = MAP_ENTRY((candidate_hdr -> hb_map), offset);
390            if (map_entry > CPP_MAX_OFFSET) {
391                map_entry = (signed_word)(BYTES_TO_WORDS(offset)) % sz;
392            }
393            r -= WORDS_TO_BYTES(map_entry);
394            limit = r + WORDS_TO_BYTES(sz);
395            if (limit > (word)(h + 1)
396                && sz <= BYTES_TO_WORDS(HBLKSIZE)) {
397                return(0);
398            }
399            if ((word)p >= limit) return(0);
400        }
401    return((GC_PTR)r);
402}
403
404
405/* Return the size of an object, given a pointer to its base.           */
406/* (For small obects this also happens to work from interior pointers,  */
407/* but that shouldn't be relied upon.)                                  */
408# ifdef __STDC__
409    size_t GC_size(GC_PTR p)
410# else
411    size_t GC_size(p)
412    GC_PTR p;
413# endif
414{
415    register int sz;
416    register hdr * hhdr = HDR(p);
417   
418    sz = WORDS_TO_BYTES(hhdr -> hb_sz);
419    return(sz);
420}
421
422size_t GC_get_heap_size GC_PROTO(())
423{
424    return ((size_t) GC_heapsize);
425}
426
427size_t GC_get_free_bytes GC_PROTO(())
428{
429    return ((size_t) GC_large_free_bytes);
430}
431
432size_t GC_get_bytes_since_gc GC_PROTO(())
433{
434    return ((size_t) WORDS_TO_BYTES(GC_words_allocd));
435}
436
437size_t GC_get_total_bytes GC_PROTO(())
438{
439    return ((size_t) WORDS_TO_BYTES(GC_words_allocd+GC_words_allocd_before_gc));
440}
441
442GC_bool GC_is_initialized = FALSE;
443
444void GC_init()
445{
446    DCL_LOCK_STATE;
447   
448    DISABLE_SIGNALS();
449
450#ifdef MSWIN32
451    if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml);
452#endif /* MSWIN32 */
453
454    LOCK();
455    GC_init_inner();
456    UNLOCK();
457    ENABLE_SIGNALS();
458
459#   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
460        /* Make sure marker threads and started and thread local */
461        /* allocation is initialized, in case we didn't get      */
462        /* called from GC_init_parallel();                       */
463        {
464          extern void GC_init_parallel(void);
465          GC_init_parallel();
466        }
467#   endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
468}
469
470#if defined(MSWIN32) || defined(MSWINCE)
471    CRITICAL_SECTION GC_write_cs;
472#endif
473
474#ifdef MSWIN32
475    extern void GC_init_win32 GC_PROTO((void));
476#endif
477
478extern void GC_setpagesize();
479
480#ifdef UNIX_LIKE
481
482extern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int)));
483
484static void looping_handler(sig)
485int sig;
486{
487    GC_err_printf1("Caught signal %d: looping in handler\n", sig);
488    for(;;);
489}
490#endif
491
492#ifdef MSWIN32
493extern GC_bool GC_no_win32_dlls;
494#else
495# define GC_no_win32_dlls FALSE
496#endif
497
498void GC_init_inner()
499{
500#   if !defined(THREADS) && defined(GC_ASSERTIONS)
501        word dummy;
502#   endif
503    word initial_heap_sz = (word)MINHINCR;
504   
505    if (GC_is_initialized) return;
506#   ifdef PRINTSTATS
507      GC_print_stats = 1;
508#   endif
509#   if defined(MSWIN32) || defined(MSWINCE)
510        InitializeCriticalSection(&GC_write_cs);
511#   endif
512
513    if (0 != GETENV("GC_PRINT_STATS")) {
514      GC_print_stats = 1;
515    }
516    if (0 != GETENV("GC_FIND_LEAK")) {
517      GC_find_leak = 1;
518    }
519    if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) {
520      GC_all_interior_pointers = 1;
521    }
522    if (0 != GETENV("GC_DONT_GC")) {
523      GC_dont_gc = 1;
524    }
525    if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) {
526      GC_print_back_height = 1;
527    }
528    if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) {
529      GC_large_alloc_warn_interval = LONG_MAX;
530    }
531    {
532      char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET");
533      if (0 != time_limit_string) {
534        long time_limit = atol(time_limit_string);
535        if (time_limit < 5) {
536          WARN("GC_PAUSE_TIME_TARGET environment variable value too small "
537               "or bad syntax: Ignoring\n", 0);
538        } else {
539          GC_time_limit = time_limit;
540        }
541      }
542    }
543    {
544      char * interval_string = GETENV("GC_LARGE_ALLOC_WARN_INTERVAL");
545      if (0 != interval_string) {
546        long interval = atol(interval_string);
547        if (interval <= 0) {
548          WARN("GC_LARGE_ALLOC_WARN_INTERVAL environment variable has "
549               "bad value: Ignoring\n", 0);
550        } else {
551          GC_large_alloc_warn_interval = interval;
552        }
553      }
554    }
555#   ifdef UNIX_LIKE
556      if (0 != GETENV("GC_LOOP_ON_ABORT")) {
557        GC_set_and_save_fault_handler(looping_handler);
558      }
559#   endif
560    /* Adjust normal object descriptor for extra allocation.    */
561    if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) {
562      GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH);
563    }
564    GC_setpagesize();
565    GC_exclude_static_roots(beginGC_arrays, endGC_arrays);
566    GC_exclude_static_roots(beginGC_obj_kinds, endGC_obj_kinds);
567#   ifdef SEPARATE_GLOBALS
568      GC_exclude_static_roots(beginGC_objfreelist, endGC_objfreelist);
569      GC_exclude_static_roots(beginGC_aobjfreelist, endGC_aobjfreelist);
570#   endif
571#   ifdef MSWIN32
572        GC_init_win32();
573#   endif
574#   if defined(SEARCH_FOR_DATA_START)
575        GC_init_linux_data_start();
576#   endif
577#   if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
578        GC_init_netbsd_elf();
579#   endif
580#   if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS)
581        GC_thr_init();
582#   endif
583#   ifdef GC_SOLARIS_THREADS
584        /* We need dirty bits in order to find live stack sections.     */
585        GC_dirty_init();
586#   endif
587#   if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \
588        || defined(GC_SOLARIS_THREADS)
589      if (GC_stackbottom == 0) {
590        GC_stackbottom = GC_get_stack_base();
591#       if defined(LINUX) && defined(IA64)
592          GC_register_stackbottom = GC_get_register_stack_base();
593#       endif
594      }
595#   endif
596    GC_ASSERT(sizeof (ptr_t) == sizeof(word));
597    GC_ASSERT(sizeof (signed_word) == sizeof(word));
598    GC_ASSERT(sizeof (struct hblk) == HBLKSIZE);
599#   ifndef THREADS
600#     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
601        ABORT(
602          "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
603#     endif
604#     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
605        ABORT(
606          "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
607#     endif
608#     ifdef STACK_GROWS_DOWN
609        GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom);
610#     else
611        GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom);
612#     endif
613#   endif
614#   if !defined(_AUX_SOURCE) || defined(__GNUC__)
615      GC_ASSERT((word)(-1) > (word)0);
616      /* word should be unsigned */
617#   endif
618    GC_ASSERT((signed_word)(-1) < (signed_word)0);
619   
620    /* Add initial guess of root sets.  Do this first, since sbrk(0)    */
621    /* might be used.                                                   */
622      GC_register_data_segments();
623    GC_init_headers();
624    GC_bl_init();
625    GC_mark_init();
626    {
627        char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE");
628        if (sz_str != NULL) {
629          initial_heap_sz = atoi(sz_str);
630          if (initial_heap_sz <= MINHINCR * HBLKSIZE) {
631            WARN("Bad initial heap size %s - ignoring it.\n",
632                 sz_str);
633          }
634          initial_heap_sz = divHBLKSZ(initial_heap_sz);
635        }
636    }
637    if (!GC_expand_hp_inner(initial_heap_sz)) {
638        GC_err_printf0("Can't start up: not enough memory\n");
639        EXIT();
640    }
641    /* Preallocate large object map.  It's otherwise inconvenient to    */
642    /* deal with failure.                                               */
643      if (!GC_add_map_entry((word)0)) {
644        GC_err_printf0("Can't start up: not enough memory\n");
645        EXIT();
646      }
647    GC_register_displacement_inner(0L);
648#   ifdef MERGE_SIZES
649      GC_init_size_map();
650#   endif
651#   ifdef PCR
652      if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever)
653          != PCR_ERes_okay) {
654          ABORT("Can't lock load state\n");
655      } else if (PCR_IL_Unlock() != PCR_ERes_okay) {
656          ABORT("Can't unlock load state\n");
657      }
658      PCR_IL_Unlock();
659      GC_pcr_install();
660#   endif
661#   if !defined(SMALL_CONFIG)
662      if (!GC_no_win32_dlls && 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
663        GC_ASSERT(!GC_incremental);
664        GC_setpagesize();
665#       ifndef GC_SOLARIS_THREADS
666          GC_dirty_init();
667#       endif
668        GC_ASSERT(GC_words_allocd == 0)
669        GC_incremental = TRUE;
670      }
671#   endif /* !SMALL_CONFIG */
672    /* Get black list set up and/or incrmental GC started */
673      if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();
674    GC_is_initialized = TRUE;
675#   ifdef STUBBORN_ALLOC
676        GC_stubborn_init();
677#   endif
678    /* Convince lint that some things are used */
679#   ifdef LINT
680      {
681          extern char * GC_copyright[];
682          extern int GC_read();
683          extern void GC_register_finalizer_no_order();
684         
685          GC_noop(GC_copyright, GC_find_header,
686                  GC_push_one, GC_call_with_alloc_lock, GC_read,
687                  GC_dont_expand,
688#                 ifndef NO_DEBUGGING
689                    GC_dump,
690#                 endif
691                  GC_register_finalizer_no_order);
692      }
693#   endif
694}
695
696void GC_enable_incremental GC_PROTO(())
697{
698# if !defined(SMALL_CONFIG)
699  if (!GC_find_leak) {
700    DCL_LOCK_STATE;
701   
702    DISABLE_SIGNALS();
703    LOCK();
704    if (GC_incremental) goto out;
705    GC_setpagesize();
706    if (GC_no_win32_dlls) goto out;
707#   ifndef GC_SOLARIS_THREADS
708        GC_dirty_init();
709#   endif
710    if (!GC_is_initialized) {
711        GC_init_inner();
712    }
713    if (GC_incremental) goto out;
714    if (GC_dont_gc) {
715        /* Can't easily do it. */
716        UNLOCK();
717        ENABLE_SIGNALS();
718        return;
719    }
720    if (GC_words_allocd > 0) {
721        /* There may be unmarked reachable objects      */
722        GC_gcollect_inner();
723    }   /* else we're OK in assuming everything's       */
724        /* clean since nothing can point to an          */
725        /* unmarked object.                             */
726    GC_read_dirty();
727    GC_incremental = TRUE;
728out:
729    UNLOCK();
730    ENABLE_SIGNALS();
731  }
732# endif
733}
734
735
736#if defined(MSWIN32) || defined(MSWINCE)
737# define LOG_FILE _T("gc.log")
738
739  HANDLE GC_stdout = 0;
740
741  void GC_deinit()
742  {
743      if (GC_is_initialized) {
744        DeleteCriticalSection(&GC_write_cs);
745      }
746  }
747
748  int GC_write(buf, len)
749  GC_CONST char * buf;
750  size_t len;
751  {
752      BOOL tmp;
753      DWORD written;
754      if (len == 0)
755          return 0;
756      EnterCriticalSection(&GC_write_cs);
757      if (GC_stdout == INVALID_HANDLE_VALUE) {
758          return -1;
759      } else if (GC_stdout == 0) {
760          GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE,
761                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
762                                 NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
763                                 NULL);
764          if (GC_stdout == INVALID_HANDLE_VALUE) ABORT("Open of log file failed");
765      }
766      tmp = WriteFile(GC_stdout, buf, len, &written, NULL);
767      if (!tmp)
768          DebugBreak();
769      LeaveCriticalSection(&GC_write_cs);
770      return tmp ? (int)written : -1;
771  }
772
773#endif
774
775#if defined(OS2) || defined(MACOS)
776FILE * GC_stdout = NULL;
777FILE * GC_stderr = NULL;
778int GC_tmp;  /* Should really be local ... */
779
780  void GC_set_files()
781  {
782      if (GC_stdout == NULL) {
783        GC_stdout = stdout;
784    }
785    if (GC_stderr == NULL) {
786        GC_stderr = stderr;
787    }
788  }
789#endif
790
791#if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE)
792  int GC_stdout = 1;
793  int GC_stderr = 2;
794# if !defined(AMIGA)
795#   include <unistd.h>
796# endif
797#endif
798
799#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \
800    && !defined(MACOS)  && !defined(ECOS) && !defined(NOSYS)
801int GC_write(fd, buf, len)
802int fd;
803GC_CONST char *buf;
804size_t len;
805{
806     register int bytes_written = 0;
807     register int result;
808     
809     while (bytes_written < len) {
810#       ifdef GC_SOLARIS_THREADS
811            result = syscall(SYS_write, fd, buf + bytes_written,
812                                            len - bytes_written);
813#       else
814            result = write(fd, buf + bytes_written, len - bytes_written);
815#       endif
816        if (-1 == result) return(result);
817        bytes_written += result;
818    }
819    return(bytes_written);
820}
821#endif /* UN*X */
822
823#ifdef ECOS
824int GC_write(fd, buf, len)
825{
826  _Jv_diag_write (buf, len);
827  return len;
828}
829#endif
830
831#ifdef NOSYS
832int GC_write(fd, buf, len)
833{
834  /* No writing.  */
835  return len;
836}
837#endif
838
839
840#if defined(MSWIN32) || defined(MSWINCE)
841#   define WRITE(f, buf, len) GC_write(buf, len)
842#else
843#   if defined(OS2) || defined(MACOS)
844#   define WRITE(f, buf, len) (GC_set_files(), \
845                               GC_tmp = fwrite((buf), 1, (len), (f)), \
846                               fflush(f), GC_tmp)
847#   else
848#     define WRITE(f, buf, len) GC_write((f), (buf), (len))
849#   endif
850#endif
851
852/* A version of printf that is unlikely to call malloc, and is thus safer */
853/* to call from the collector in case malloc has been bound to GC_malloc. */
854/* Assumes that no more than 1023 characters are written at once.         */
855/* Assumes that all arguments have been converted to something of the     */
856/* same size as long, and that the format conversions expect something    */
857/* of that size.                                                          */
858void GC_printf(format, a, b, c, d, e, f)
859GC_CONST char * format;
860long a, b, c, d, e, f;
861{
862    char buf[1025];
863   
864    if (GC_quiet) return;
865    buf[1024] = 0x15;
866    (void) sprintf(buf, format, a, b, c, d, e, f);
867    if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack");
868    if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
869}
870
871void GC_err_printf(format, a, b, c, d, e, f)
872GC_CONST char * format;
873long a, b, c, d, e, f;
874{
875    char buf[1025];
876   
877    buf[1024] = 0x15;
878    (void) sprintf(buf, format, a, b, c, d, e, f);
879    if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack");
880    if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
881}
882
883void GC_err_puts(s)
884GC_CONST char *s;
885{
886    if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
887}
888
889#if defined(LINUX) && !defined(SMALL_CONFIG)
890void GC_err_write(buf, len)
891GC_CONST char *buf;
892size_t len;
893{
894    if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed");
895}
896#endif
897
898# if defined(__STDC__) || defined(__cplusplus)
899    void GC_default_warn_proc(char *msg, GC_word arg)
900# else
901    void GC_default_warn_proc(msg, arg)
902    char *msg;
903    GC_word arg;
904# endif
905{
906    GC_err_printf1(msg, (unsigned long)arg);
907}
908
909GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;
910
911# if defined(__STDC__) || defined(__cplusplus)
912    GC_warn_proc GC_set_warn_proc(GC_warn_proc p)
913# else
914    GC_warn_proc GC_set_warn_proc(p)
915    GC_warn_proc p;
916# endif
917{
918    GC_warn_proc result;
919
920    LOCK();
921    result = GC_current_warn_proc;
922    GC_current_warn_proc = p;
923    UNLOCK();
924    return(result);
925}
926
927
928#ifndef PCR
929void GC_abort(msg)
930GC_CONST char * msg;
931{
932#   if defined(MSWIN32)
933      (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
934      DebugBreak();
935#   else
936      GC_err_printf1("%s\n", msg);
937#   endif
938    if (GETENV("GC_LOOP_ON_ABORT") != NULL) {
939            /* In many cases it's easier to debug a running process.    */
940            /* It's arguably nicer to sleep, but that makes it harder   */
941            /* to look at the thread if the debugger doesn't know much  */
942            /* about threads.                                           */
943            for(;;) {}
944    }
945#   ifdef MSWIN32
946        DebugBreak();
947#   else
948        (void) abort();
949#   endif
950}
951#endif
952
953#ifdef NEED_CALLINFO
954
955#ifdef HAVE_BUILTIN_BACKTRACE
956# include <execinfo.h>
957# ifdef LINUX
958#   include <unistd.h>
959# endif
960#endif
961
962void GC_print_callers (info)
963struct callinfo info[NFRAMES];
964{
965    register int i;
966   
967#   if NFRAMES == 1
968      GC_err_printf0("\tCaller at allocation:\n");
969#   else
970      GC_err_printf0("\tCall chain at allocation:\n");
971#   endif
972    for (i = 0; i < NFRAMES; i++) {
973        if (info[i].ci_pc == 0) break;
974#       if NARGS > 0
975        {
976          int j;
977
978          GC_err_printf0("\t\targs: ");
979          for (j = 0; j < NARGS; j++) {
980            if (j != 0) GC_err_printf0(", ");
981            GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]),
982                                        ~(info[i].ci_arg[j]));
983          }
984          GC_err_printf0("\n");
985        }
986#       endif
987#       if defined(HAVE_BUILTIN_BACKTRACE) && !defined(REDIRECT_MALLOC)
988          /* Unfortunately backtrace_symbols calls malloc, which makes  */
989          /* it dangersous if that has been redirected.                 */
990          {
991            char **sym_name =
992              backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
993            char *name = sym_name[0];
994            GC_bool found_it = (strchr(name, '(') != 0);
995            FILE *pipe;
996#           ifdef LINUX
997              if (!found_it) {
998#               define EXE_SZ 100
999                static char exe_name[EXE_SZ];
1000#               define CMD_SZ 200
1001                char cmd_buf[CMD_SZ];
1002#               define RESULT_SZ 200
1003                static char result_buf[RESULT_SZ];
1004                size_t result_len;
1005                static GC_bool found_exe_name = FALSE;
1006                static GC_bool will_fail = FALSE;
1007                int ret_code;
1008                /* Unfortunately, this is the common case for the       */
1009                /* main executable.                                     */
1010                /* Try to get it via a hairy and expensive scheme.      */
1011                /* First we get the name of the executable:             */
1012                if (will_fail) goto out;
1013                if (!found_exe_name) {
1014                  ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
1015                  if (ret_code < 0 || ret_code >= EXE_SZ || exe_name[0] != '/') {
1016                    will_fail = TRUE;   /* Dont try again. */
1017                    goto out;
1018                  }
1019                  exe_name[ret_code] = '\0';
1020                  found_exe_name = TRUE;
1021                }
1022                /* Then we use popen to start addr2line -e <exe> <addr> */
1023                /* There are faster ways to do this, but hopefully this */
1024                /* isn't time critical.                                 */
1025                sprintf(cmd_buf, "/usr/bin/addr2line -e %s 0x%lx", exe_name,
1026                                 (unsigned long)info[i].ci_pc);
1027                pipe = popen(cmd_buf, "r");
1028                if (pipe < 0 || fgets(result_buf, RESULT_SZ, pipe) == 0) {
1029                  will_fail = TRUE;
1030                  goto out;
1031                }
1032                result_len = strlen(result_buf);
1033                if (result_buf[result_len - 1] == '\n') --result_len;
1034                if (result_buf[0] == '?'
1035                    || result_buf[result_len-2] == ':'
1036                       && result_buf[result_len-1] == '0')
1037                    goto out;
1038                if (result_len < RESULT_SZ - 25) {
1039                  /* Add in hex address */
1040                    sprintf(result_buf + result_len, " [0x%lx]",
1041                          (unsigned long)info[i].ci_pc);
1042                }
1043                name = result_buf;
1044                pclose(pipe);
1045                out:
1046              }
1047#           endif
1048            GC_err_printf1("\t\t%s\n", name);
1049            free(sym_name);
1050          }
1051#       else
1052          GC_err_printf1("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
1053#       endif
1054    }
1055}
1056
1057#endif /* SAVE_CALL_CHAIN */
1058
1059/* Needed by SRC_M3, gcj, and should perhaps be the official interface  */
1060/* to GC_dont_gc.                                                       */
1061void GC_enable()
1062{
1063    GC_dont_gc--;
1064}
1065
1066void GC_disable()
1067{
1068    GC_dont_gc++;
1069}
1070
1071#if !defined(NO_DEBUGGING)
1072
1073void GC_dump()
1074{
1075    GC_printf0("***Static roots:\n");
1076    GC_print_static_roots();
1077    GC_printf0("\n***Heap sections:\n");
1078    GC_print_heap_sects();
1079    GC_printf0("\n***Free blocks:\n");
1080    GC_print_hblkfreelist();
1081    GC_printf0("\n***Blocks in use:\n");
1082    GC_print_block_list();
1083}
1084
1085#endif /* NO_DEBUGGING */
Note: See TracBrowser for help on using the repository browser.