OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [boehm-gc/] [malloc.c] - Blame information for rev 721

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 721 jeremybenn
/*
2
 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3
 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
4
 * Copyright (c) 2000 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, February 7, 1996 4:32 pm PST */
16
 
17
#include <stdio.h>
18
#include "private/gc_priv.h"
19
 
20
extern ptr_t GC_clear_stack();  /* in misc.c, behaves like identity */
21
void GC_extend_size_map();      /* in misc.c. */
22
 
23
/* Allocate reclaim list for kind:      */
24
/* Return TRUE on success               */
25
GC_bool GC_alloc_reclaim_list(kind)
26
register struct obj_kind * kind;
27
{
28
    struct hblk ** result = (struct hblk **)
29
                GC_scratch_alloc((MAXOBJSZ+1) * sizeof(struct hblk *));
30
    if (result == 0) return(FALSE);
31
    BZERO(result, (MAXOBJSZ+1)*sizeof(struct hblk *));
32
    kind -> ok_reclaim_list = result;
33
    return(TRUE);
34
}
35
 
36
/* Allocate a large block of size lw words.     */
37
/* The block is not cleared.                    */
38
/* Flags is 0 or IGNORE_OFF_PAGE.               */
39
/* We hold the allocation lock.                 */
40
ptr_t GC_alloc_large(lw, k, flags)
41
word lw;
42
int k;
43
unsigned flags;
44
{
45
    struct hblk * h;
46
    word n_blocks = OBJ_SZ_TO_BLOCKS(lw);
47
    ptr_t result;
48
 
49
    if (!GC_is_initialized) GC_init_inner();
50
    /* Do our share of marking work */
51
        if(GC_incremental && !GC_dont_gc)
52
            GC_collect_a_little_inner((int)n_blocks);
53
    h = GC_allochblk(lw, k, flags);
54
#   ifdef USE_MUNMAP
55
        if (0 == h) {
56
            GC_merge_unmapped();
57
            h = GC_allochblk(lw, k, flags);
58
        }
59
#   endif
60
    while (0 == h && GC_collect_or_expand(n_blocks, (flags != 0))) {
61
        h = GC_allochblk(lw, k, flags);
62
    }
63
    if (h == 0) {
64
        result = 0;
65
    } else {
66
        int total_bytes = n_blocks * HBLKSIZE;
67
        if (n_blocks > 1) {
68
            GC_large_allocd_bytes += total_bytes;
69
            if (GC_large_allocd_bytes > GC_max_large_allocd_bytes)
70
                GC_max_large_allocd_bytes = GC_large_allocd_bytes;
71
        }
72
        result = (ptr_t) (h -> hb_body);
73
        GC_words_wasted += BYTES_TO_WORDS(total_bytes) - lw;
74
    }
75
    return result;
76
}
77
 
78
 
79
/* Allocate a large block of size lb bytes.  Clear if appropriate.      */
80
/* We hold the allocation lock.                                         */
81
ptr_t GC_alloc_large_and_clear(lw, k, flags)
82
word lw;
83
int k;
84
unsigned flags;
85
{
86
    ptr_t result = GC_alloc_large(lw, k, flags);
87
    word n_blocks = OBJ_SZ_TO_BLOCKS(lw);
88
 
89
    if (0 == result) return 0;
90
    if (GC_debugging_started || GC_obj_kinds[k].ok_init) {
91
        /* Clear the whole block, in case of GC_realloc call. */
92
        BZERO(result, n_blocks * HBLKSIZE);
93
    }
94
    return result;
95
}
96
 
97
/* allocate lb bytes for an object of kind k.   */
98
/* Should not be used to directly to allocate   */
99
/* objects such as STUBBORN objects that        */
100
/* require special handling on allocation.      */
101
/* First a version that assumes we already      */
102
/* hold lock:                                   */
103
ptr_t GC_generic_malloc_inner(lb, k)
104
register word lb;
105
register int k;
106
{
107
register word lw;
108
register ptr_t op;
109
register ptr_t *opp;
110
 
111
    if( SMALL_OBJ(lb) ) {
112
        register struct obj_kind * kind = GC_obj_kinds + k;
113
#       ifdef MERGE_SIZES
114
          lw = GC_size_map[lb];
115
#       else
116
          lw = ALIGNED_WORDS(lb);
117
          if (lw == 0) lw = MIN_WORDS;
118
#       endif
119
        opp = &(kind -> ok_freelist[lw]);
120
        if( (op = *opp) == 0 ) {
121
#           ifdef MERGE_SIZES
122
              if (GC_size_map[lb] == 0) {
123
                if (!GC_is_initialized)  GC_init_inner();
124
                if (GC_size_map[lb] == 0) GC_extend_size_map(lb);
125
                return(GC_generic_malloc_inner(lb, k));
126
              }
127
#           else
128
              if (!GC_is_initialized) {
129
                GC_init_inner();
130
                return(GC_generic_malloc_inner(lb, k));
131
              }
132
#           endif
133
            if (kind -> ok_reclaim_list == 0) {
134
                if (!GC_alloc_reclaim_list(kind)) goto out;
135
            }
136
            op = GC_allocobj(lw, k);
137
            if (op == 0) goto out;
138
        }
139
        /* Here everything is in a consistent state.    */
140
        /* We assume the following assignment is        */
141
        /* atomic.  If we get aborted                   */
142
        /* after the assignment, we lose an object,     */
143
        /* but that's benign.                           */
144
        /* Volatile declarations may need to be added   */
145
        /* to prevent the compiler from breaking things.*/
146
        /* If we only execute the second of the         */
147
        /* following assignments, we lose the free      */
148
        /* list, but that should still be OK, at least  */
149
        /* for garbage collected memory.                */
150
        *opp = obj_link(op);
151
        obj_link(op) = 0;
152
    } else {
153
        lw = ROUNDED_UP_WORDS(lb);
154
        op = (ptr_t)GC_alloc_large_and_clear(lw, k, 0);
155
    }
156
    GC_words_allocd += lw;
157
 
158
out:
159
    return op;
160
}
161
 
162
/* Allocate a composite object of size n bytes.  The caller guarantees  */
163
/* that pointers past the first page are not relevant.  Caller holds    */
164
/* allocation lock.                                                     */
165
ptr_t GC_generic_malloc_inner_ignore_off_page(lb, k)
166
register size_t lb;
167
register int k;
168
{
169
    register word lw;
170
    ptr_t op;
171
 
172
    if (lb <= HBLKSIZE)
173
        return(GC_generic_malloc_inner((word)lb, k));
174
    lw = ROUNDED_UP_WORDS(lb);
175
    op = (ptr_t)GC_alloc_large_and_clear(lw, k, IGNORE_OFF_PAGE);
176
    GC_words_allocd += lw;
177
    return op;
178
}
179
 
180
ptr_t GC_generic_malloc(lb, k)
181
register word lb;
182
register int k;
183
{
184
    ptr_t result;
185
    DCL_LOCK_STATE;
186
 
187
    if (GC_have_errors) GC_print_all_errors();
188
    GC_INVOKE_FINALIZERS();
189
    if (SMALL_OBJ(lb)) {
190
        DISABLE_SIGNALS();
191
        LOCK();
192
        result = GC_generic_malloc_inner((word)lb, k);
193
        UNLOCK();
194
        ENABLE_SIGNALS();
195
    } else {
196
        word lw;
197
        word n_blocks;
198
        GC_bool init;
199
        lw = ROUNDED_UP_WORDS(lb);
200
        n_blocks = OBJ_SZ_TO_BLOCKS(lw);
201
        init = GC_obj_kinds[k].ok_init;
202
        DISABLE_SIGNALS();
203
        LOCK();
204
        result = (ptr_t)GC_alloc_large(lw, k, 0);
205
        if (0 != result) {
206
          if (GC_debugging_started) {
207
            BZERO(result, n_blocks * HBLKSIZE);
208
          } else {
209
#           ifdef THREADS
210
              /* Clear any memory that might be used for GC descriptors */
211
              /* before we release the lock.                          */
212
                ((word *)result)[0] = 0;
213
                ((word *)result)[1] = 0;
214
                ((word *)result)[lw-1] = 0;
215
                ((word *)result)[lw-2] = 0;
216
#           endif
217
          }
218
        }
219
        GC_words_allocd += lw;
220
        UNLOCK();
221
        ENABLE_SIGNALS();
222
        if (init && !GC_debugging_started && 0 != result) {
223
            BZERO(result, n_blocks * HBLKSIZE);
224
        }
225
    }
226
    if (0 == result) {
227
        return((*GC_oom_fn)(lb));
228
    } else {
229
        return(result);
230
    }
231
}
232
 
233
 
234
#define GENERAL_MALLOC(lb,k) \
235
    (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
236
/* We make the GC_clear_stack_call a tail call, hoping to get more of   */
237
/* the stack.                                                           */
238
 
239
/* Allocate lb bytes of atomic (pointerfree) data */
240
# ifdef __STDC__
241
    GC_PTR GC_malloc_atomic(size_t lb)
242
# else
243
    GC_PTR GC_malloc_atomic(lb)
244
    size_t lb;
245
# endif
246
{
247
register ptr_t op;
248
register ptr_t * opp;
249
register word lw;
250
DCL_LOCK_STATE;
251
 
252
    if( EXPECT(SMALL_OBJ(lb), 1) ) {
253
#       ifdef MERGE_SIZES
254
          lw = GC_size_map[lb];
255
#       else
256
          lw = ALIGNED_WORDS(lb);
257
#       endif
258
        opp = &(GC_aobjfreelist[lw]);
259
        FASTLOCK();
260
        if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) {
261
            FASTUNLOCK();
262
            return(GENERAL_MALLOC((word)lb, PTRFREE));
263
        }
264
        /* See above comment on signals.        */
265
        *opp = obj_link(op);
266
        GC_words_allocd += lw;
267
        FASTUNLOCK();
268
        return((GC_PTR) op);
269
   } else {
270
       return(GENERAL_MALLOC((word)lb, PTRFREE));
271
   }
272
}
273
 
274
/* Allocate lb bytes of composite (pointerful) data */
275
# ifdef __STDC__
276
    GC_PTR GC_malloc(size_t lb)
277
# else
278
    GC_PTR GC_malloc(lb)
279
    size_t lb;
280
# endif
281
{
282
register ptr_t op;
283
register ptr_t *opp;
284
register word lw;
285
DCL_LOCK_STATE;
286
 
287
    if( EXPECT(SMALL_OBJ(lb), 1) ) {
288
#       ifdef MERGE_SIZES
289
          lw = GC_size_map[lb];
290
#       else
291
          lw = ALIGNED_WORDS(lb);
292
#       endif
293
        opp = &(GC_objfreelist[lw]);
294
        FASTLOCK();
295
        if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) {
296
            FASTUNLOCK();
297
            return(GENERAL_MALLOC((word)lb, NORMAL));
298
        }
299
        /* See above comment on signals.        */
300
        GC_ASSERT(0 == obj_link(op)
301
                  || (word)obj_link(op)
302
                        <= (word)GC_greatest_plausible_heap_addr
303
                     && (word)obj_link(op)
304
                        >= (word)GC_least_plausible_heap_addr);
305
        *opp = obj_link(op);
306
        obj_link(op) = 0;
307
        GC_words_allocd += lw;
308
        FASTUNLOCK();
309
        return((GC_PTR) op);
310
   } else {
311
       return(GENERAL_MALLOC((word)lb, NORMAL));
312
   }
313
}
314
 
315
# ifdef REDIRECT_MALLOC
316
 
317
/* Avoid unnecessary nested procedure calls here, by #defining some     */
318
/* malloc replacements.  Otherwise we end up saving a                   */
319
/* meaningless return address in the object.  It also speeds things up, */
320
/* but it is admittedly quite ugly.                                     */
321
# ifdef GC_ADD_CALLER
322
#   define RA GC_RETURN_ADDR,
323
# else
324
#   define RA
325
# endif
326
# define GC_debug_malloc_replacement(lb) \
327
        GC_debug_malloc(lb, RA "unknown", 0)
328
 
329
# ifdef __STDC__
330
    GC_PTR malloc(size_t lb)
331
# else
332
    GC_PTR malloc(lb)
333
    size_t lb;
334
# endif
335
  {
336
    /* It might help to manually inline the GC_malloc call here.        */
337
    /* But any decent compiler should reduce the extra procedure call   */
338
    /* to at most a jump instruction in this case.                      */
339
#   if defined(I386) && defined(GC_SOLARIS_THREADS)
340
      /*
341
       * Thread initialisation can call malloc before
342
       * we're ready for it.
343
       * It's not clear that this is enough to help matters.
344
       * The thread implementation may well call malloc at other
345
       * inopportune times.
346
       */
347
      if (!GC_is_initialized) return sbrk(lb);
348
#   endif /* I386 && GC_SOLARIS_THREADS */
349
    return((GC_PTR)REDIRECT_MALLOC(lb));
350
  }
351
 
352
# ifdef __STDC__
353
    GC_PTR calloc(size_t n, size_t lb)
354
# else
355
    GC_PTR calloc(n, lb)
356
    size_t n, lb;
357
# endif
358
  {
359
    return((GC_PTR)REDIRECT_MALLOC(n*lb));
360
  }
361
 
362
#ifndef strdup
363
# include <string.h>
364
# ifdef __STDC__
365
    char *strdup(const char *s)
366
# else
367
    char *strdup(s)
368
    char *s;
369
# endif
370
  {
371
    size_t len = strlen(s) + 1;
372
    char * result = ((char *)REDIRECT_MALLOC(len+1));
373
    BCOPY(s, result, len+1);
374
    return result;
375
  }
376
#endif /* !defined(strdup) */
377
 /* If strdup is macro defined, we assume that it actually calls malloc, */
378
 /* and thus the right thing will happen even without overriding it.     */
379
 /* This seems to be true on most Linux systems.                         */
380
 
381
#undef GC_debug_malloc_replacement
382
 
383
# endif /* REDIRECT_MALLOC */
384
 
385
/* Explicitly deallocate an object p.                           */
386
# ifdef __STDC__
387
    void GC_free(GC_PTR p)
388
# else
389
    void GC_free(p)
390
    GC_PTR p;
391
# endif
392
{
393
    register struct hblk *h;
394
    register hdr *hhdr;
395
    register signed_word sz;
396
    register ptr_t * flh;
397
    register int knd;
398
    register struct obj_kind * ok;
399
    DCL_LOCK_STATE;
400
 
401
    if (p == 0) return;
402
        /* Required by ANSI.  It's not my fault ...     */
403
    h = HBLKPTR(p);
404
    hhdr = HDR(h);
405
    GC_ASSERT(GC_base(p) == p);
406
#   if defined(REDIRECT_MALLOC) && \
407
        (defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \
408
         || defined(__MINGW32__)) /* Should this be MSWIN32 in general? */
409
        /* For Solaris, we have to redirect malloc calls during         */
410
        /* initialization.  For the others, this seems to happen        */
411
        /* implicitly.                                                  */
412
        /* Don't try to deallocate that memory.                         */
413
        if (0 == hhdr) return;
414
#   endif
415
    knd = hhdr -> hb_obj_kind;
416
    sz = hhdr -> hb_sz;
417
    ok = &GC_obj_kinds[knd];
418
    if (EXPECT((sz <= MAXOBJSZ), 1)) {
419
#       ifdef THREADS
420
            DISABLE_SIGNALS();
421
            LOCK();
422
#       endif
423
        GC_mem_freed += sz;
424
        /* A signal here can make GC_mem_freed and GC_non_gc_bytes      */
425
        /* inconsistent.  We claim this is benign.                      */
426
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
427
                /* Its unnecessary to clear the mark bit.  If the       */
428
                /* object is reallocated, it doesn't matter.  O.w. the  */
429
                /* collector will do it, since it's on a free list.     */
430
        if (ok -> ok_init) {
431
            BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
432
        }
433
        flh = &(ok -> ok_freelist[sz]);
434
        obj_link(p) = *flh;
435
        *flh = (ptr_t)p;
436
#       ifdef THREADS
437
            UNLOCK();
438
            ENABLE_SIGNALS();
439
#       endif
440
    } else {
441
        DISABLE_SIGNALS();
442
        LOCK();
443
        GC_mem_freed += sz;
444
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
445
        GC_freehblk(h);
446
        UNLOCK();
447
        ENABLE_SIGNALS();
448
    }
449
}
450
 
451
/* Explicitly deallocate an object p when we already hold lock.         */
452
/* Only used for internally allocated objects, so we can take some      */
453
/* shortcuts.                                                           */
454
#ifdef THREADS
455
void GC_free_inner(GC_PTR p)
456
{
457
    register struct hblk *h;
458
    register hdr *hhdr;
459
    register signed_word sz;
460
    register ptr_t * flh;
461
    register int knd;
462
    register struct obj_kind * ok;
463
    DCL_LOCK_STATE;
464
 
465
    h = HBLKPTR(p);
466
    hhdr = HDR(h);
467
    knd = hhdr -> hb_obj_kind;
468
    sz = hhdr -> hb_sz;
469
    ok = &GC_obj_kinds[knd];
470
    if (sz <= MAXOBJSZ) {
471
        GC_mem_freed += sz;
472
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
473
        if (ok -> ok_init) {
474
            BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
475
        }
476
        flh = &(ok -> ok_freelist[sz]);
477
        obj_link(p) = *flh;
478
        *flh = (ptr_t)p;
479
    } else {
480
        GC_mem_freed += sz;
481
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
482
        GC_freehblk(h);
483
    }
484
}
485
#endif /* THREADS */
486
 
487
# if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE)
488
#   define REDIRECT_FREE GC_free
489
# endif
490
# ifdef REDIRECT_FREE
491
#   ifdef __STDC__
492
      void free(GC_PTR p)
493
#   else
494
      void free(p)
495
      GC_PTR p;
496
#   endif
497
  {
498
#   ifndef IGNORE_FREE
499
      REDIRECT_FREE(p);
500
#   endif
501
  }
502
# endif  /* REDIRECT_MALLOC */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.