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

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-dev/] [fsf-gcc-snapshot-1-mar-12/] [or1k-gcc/] [boehm-gc/] [malloc.c] - Diff between revs 721 and 783

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 721 Rev 783
/*
/*
 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
 * Copyright (c) 2000 by Hewlett-Packard Company.  All rights reserved.
 * Copyright (c) 2000 by Hewlett-Packard Company.  All rights reserved.
 *
 *
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 *
 *
 * Permission is hereby granted to use or copy this program
 * Permission is hereby granted to use or copy this program
 * for any purpose,  provided the above notices are retained on all copies.
 * for any purpose,  provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is granted,
 * Permission to modify the code and to distribute modified code is granted,
 * provided the above notices are retained, and a notice that the code was
 * provided the above notices are retained, and a notice that the code was
 * modified is included with the above copyright notice.
 * modified is included with the above copyright notice.
 */
 */
/* Boehm, February 7, 1996 4:32 pm PST */
/* Boehm, February 7, 1996 4:32 pm PST */
 
 
#include <stdio.h>
#include <stdio.h>
#include "private/gc_priv.h"
#include "private/gc_priv.h"
 
 
extern ptr_t GC_clear_stack();  /* in misc.c, behaves like identity */
extern ptr_t GC_clear_stack();  /* in misc.c, behaves like identity */
void GC_extend_size_map();      /* in misc.c. */
void GC_extend_size_map();      /* in misc.c. */
 
 
/* Allocate reclaim list for kind:      */
/* Allocate reclaim list for kind:      */
/* Return TRUE on success               */
/* Return TRUE on success               */
GC_bool GC_alloc_reclaim_list(kind)
GC_bool GC_alloc_reclaim_list(kind)
register struct obj_kind * kind;
register struct obj_kind * kind;
{
{
    struct hblk ** result = (struct hblk **)
    struct hblk ** result = (struct hblk **)
                GC_scratch_alloc((MAXOBJSZ+1) * sizeof(struct hblk *));
                GC_scratch_alloc((MAXOBJSZ+1) * sizeof(struct hblk *));
    if (result == 0) return(FALSE);
    if (result == 0) return(FALSE);
    BZERO(result, (MAXOBJSZ+1)*sizeof(struct hblk *));
    BZERO(result, (MAXOBJSZ+1)*sizeof(struct hblk *));
    kind -> ok_reclaim_list = result;
    kind -> ok_reclaim_list = result;
    return(TRUE);
    return(TRUE);
}
}
 
 
/* Allocate a large block of size lw words.     */
/* Allocate a large block of size lw words.     */
/* The block is not cleared.                    */
/* The block is not cleared.                    */
/* Flags is 0 or IGNORE_OFF_PAGE.               */
/* Flags is 0 or IGNORE_OFF_PAGE.               */
/* We hold the allocation lock.                 */
/* We hold the allocation lock.                 */
ptr_t GC_alloc_large(lw, k, flags)
ptr_t GC_alloc_large(lw, k, flags)
word lw;
word lw;
int k;
int k;
unsigned flags;
unsigned flags;
{
{
    struct hblk * h;
    struct hblk * h;
    word n_blocks = OBJ_SZ_TO_BLOCKS(lw);
    word n_blocks = OBJ_SZ_TO_BLOCKS(lw);
    ptr_t result;
    ptr_t result;
 
 
    if (!GC_is_initialized) GC_init_inner();
    if (!GC_is_initialized) GC_init_inner();
    /* Do our share of marking work */
    /* Do our share of marking work */
        if(GC_incremental && !GC_dont_gc)
        if(GC_incremental && !GC_dont_gc)
            GC_collect_a_little_inner((int)n_blocks);
            GC_collect_a_little_inner((int)n_blocks);
    h = GC_allochblk(lw, k, flags);
    h = GC_allochblk(lw, k, flags);
#   ifdef USE_MUNMAP
#   ifdef USE_MUNMAP
        if (0 == h) {
        if (0 == h) {
            GC_merge_unmapped();
            GC_merge_unmapped();
            h = GC_allochblk(lw, k, flags);
            h = GC_allochblk(lw, k, flags);
        }
        }
#   endif
#   endif
    while (0 == h && GC_collect_or_expand(n_blocks, (flags != 0))) {
    while (0 == h && GC_collect_or_expand(n_blocks, (flags != 0))) {
        h = GC_allochblk(lw, k, flags);
        h = GC_allochblk(lw, k, flags);
    }
    }
    if (h == 0) {
    if (h == 0) {
        result = 0;
        result = 0;
    } else {
    } else {
        int total_bytes = n_blocks * HBLKSIZE;
        int total_bytes = n_blocks * HBLKSIZE;
        if (n_blocks > 1) {
        if (n_blocks > 1) {
            GC_large_allocd_bytes += total_bytes;
            GC_large_allocd_bytes += total_bytes;
            if (GC_large_allocd_bytes > GC_max_large_allocd_bytes)
            if (GC_large_allocd_bytes > GC_max_large_allocd_bytes)
                GC_max_large_allocd_bytes = GC_large_allocd_bytes;
                GC_max_large_allocd_bytes = GC_large_allocd_bytes;
        }
        }
        result = (ptr_t) (h -> hb_body);
        result = (ptr_t) (h -> hb_body);
        GC_words_wasted += BYTES_TO_WORDS(total_bytes) - lw;
        GC_words_wasted += BYTES_TO_WORDS(total_bytes) - lw;
    }
    }
    return result;
    return result;
}
}
 
 
 
 
/* Allocate a large block of size lb bytes.  Clear if appropriate.      */
/* Allocate a large block of size lb bytes.  Clear if appropriate.      */
/* We hold the allocation lock.                                         */
/* We hold the allocation lock.                                         */
ptr_t GC_alloc_large_and_clear(lw, k, flags)
ptr_t GC_alloc_large_and_clear(lw, k, flags)
word lw;
word lw;
int k;
int k;
unsigned flags;
unsigned flags;
{
{
    ptr_t result = GC_alloc_large(lw, k, flags);
    ptr_t result = GC_alloc_large(lw, k, flags);
    word n_blocks = OBJ_SZ_TO_BLOCKS(lw);
    word n_blocks = OBJ_SZ_TO_BLOCKS(lw);
 
 
    if (0 == result) return 0;
    if (0 == result) return 0;
    if (GC_debugging_started || GC_obj_kinds[k].ok_init) {
    if (GC_debugging_started || GC_obj_kinds[k].ok_init) {
        /* Clear the whole block, in case of GC_realloc call. */
        /* Clear the whole block, in case of GC_realloc call. */
        BZERO(result, n_blocks * HBLKSIZE);
        BZERO(result, n_blocks * HBLKSIZE);
    }
    }
    return result;
    return result;
}
}
 
 
/* allocate lb bytes for an object of kind k.   */
/* allocate lb bytes for an object of kind k.   */
/* Should not be used to directly to allocate   */
/* Should not be used to directly to allocate   */
/* objects such as STUBBORN objects that        */
/* objects such as STUBBORN objects that        */
/* require special handling on allocation.      */
/* require special handling on allocation.      */
/* First a version that assumes we already      */
/* First a version that assumes we already      */
/* hold lock:                                   */
/* hold lock:                                   */
ptr_t GC_generic_malloc_inner(lb, k)
ptr_t GC_generic_malloc_inner(lb, k)
register word lb;
register word lb;
register int k;
register int k;
{
{
register word lw;
register word lw;
register ptr_t op;
register ptr_t op;
register ptr_t *opp;
register ptr_t *opp;
 
 
    if( SMALL_OBJ(lb) ) {
    if( SMALL_OBJ(lb) ) {
        register struct obj_kind * kind = GC_obj_kinds + k;
        register struct obj_kind * kind = GC_obj_kinds + k;
#       ifdef MERGE_SIZES
#       ifdef MERGE_SIZES
          lw = GC_size_map[lb];
          lw = GC_size_map[lb];
#       else
#       else
          lw = ALIGNED_WORDS(lb);
          lw = ALIGNED_WORDS(lb);
          if (lw == 0) lw = MIN_WORDS;
          if (lw == 0) lw = MIN_WORDS;
#       endif
#       endif
        opp = &(kind -> ok_freelist[lw]);
        opp = &(kind -> ok_freelist[lw]);
        if( (op = *opp) == 0 ) {
        if( (op = *opp) == 0 ) {
#           ifdef MERGE_SIZES
#           ifdef MERGE_SIZES
              if (GC_size_map[lb] == 0) {
              if (GC_size_map[lb] == 0) {
                if (!GC_is_initialized)  GC_init_inner();
                if (!GC_is_initialized)  GC_init_inner();
                if (GC_size_map[lb] == 0) GC_extend_size_map(lb);
                if (GC_size_map[lb] == 0) GC_extend_size_map(lb);
                return(GC_generic_malloc_inner(lb, k));
                return(GC_generic_malloc_inner(lb, k));
              }
              }
#           else
#           else
              if (!GC_is_initialized) {
              if (!GC_is_initialized) {
                GC_init_inner();
                GC_init_inner();
                return(GC_generic_malloc_inner(lb, k));
                return(GC_generic_malloc_inner(lb, k));
              }
              }
#           endif
#           endif
            if (kind -> ok_reclaim_list == 0) {
            if (kind -> ok_reclaim_list == 0) {
                if (!GC_alloc_reclaim_list(kind)) goto out;
                if (!GC_alloc_reclaim_list(kind)) goto out;
            }
            }
            op = GC_allocobj(lw, k);
            op = GC_allocobj(lw, k);
            if (op == 0) goto out;
            if (op == 0) goto out;
        }
        }
        /* Here everything is in a consistent state.    */
        /* Here everything is in a consistent state.    */
        /* We assume the following assignment is        */
        /* We assume the following assignment is        */
        /* atomic.  If we get aborted                   */
        /* atomic.  If we get aborted                   */
        /* after the assignment, we lose an object,     */
        /* after the assignment, we lose an object,     */
        /* but that's benign.                           */
        /* but that's benign.                           */
        /* Volatile declarations may need to be added   */
        /* Volatile declarations may need to be added   */
        /* to prevent the compiler from breaking things.*/
        /* to prevent the compiler from breaking things.*/
        /* If we only execute the second of the         */
        /* If we only execute the second of the         */
        /* following assignments, we lose the free      */
        /* following assignments, we lose the free      */
        /* list, but that should still be OK, at least  */
        /* list, but that should still be OK, at least  */
        /* for garbage collected memory.                */
        /* for garbage collected memory.                */
        *opp = obj_link(op);
        *opp = obj_link(op);
        obj_link(op) = 0;
        obj_link(op) = 0;
    } else {
    } else {
        lw = ROUNDED_UP_WORDS(lb);
        lw = ROUNDED_UP_WORDS(lb);
        op = (ptr_t)GC_alloc_large_and_clear(lw, k, 0);
        op = (ptr_t)GC_alloc_large_and_clear(lw, k, 0);
    }
    }
    GC_words_allocd += lw;
    GC_words_allocd += lw;
 
 
out:
out:
    return op;
    return op;
}
}
 
 
/* Allocate a composite object of size n bytes.  The caller guarantees  */
/* Allocate a composite object of size n bytes.  The caller guarantees  */
/* that pointers past the first page are not relevant.  Caller holds    */
/* that pointers past the first page are not relevant.  Caller holds    */
/* allocation lock.                                                     */
/* allocation lock.                                                     */
ptr_t GC_generic_malloc_inner_ignore_off_page(lb, k)
ptr_t GC_generic_malloc_inner_ignore_off_page(lb, k)
register size_t lb;
register size_t lb;
register int k;
register int k;
{
{
    register word lw;
    register word lw;
    ptr_t op;
    ptr_t op;
 
 
    if (lb <= HBLKSIZE)
    if (lb <= HBLKSIZE)
        return(GC_generic_malloc_inner((word)lb, k));
        return(GC_generic_malloc_inner((word)lb, k));
    lw = ROUNDED_UP_WORDS(lb);
    lw = ROUNDED_UP_WORDS(lb);
    op = (ptr_t)GC_alloc_large_and_clear(lw, k, IGNORE_OFF_PAGE);
    op = (ptr_t)GC_alloc_large_and_clear(lw, k, IGNORE_OFF_PAGE);
    GC_words_allocd += lw;
    GC_words_allocd += lw;
    return op;
    return op;
}
}
 
 
ptr_t GC_generic_malloc(lb, k)
ptr_t GC_generic_malloc(lb, k)
register word lb;
register word lb;
register int k;
register int k;
{
{
    ptr_t result;
    ptr_t result;
    DCL_LOCK_STATE;
    DCL_LOCK_STATE;
 
 
    if (GC_have_errors) GC_print_all_errors();
    if (GC_have_errors) GC_print_all_errors();
    GC_INVOKE_FINALIZERS();
    GC_INVOKE_FINALIZERS();
    if (SMALL_OBJ(lb)) {
    if (SMALL_OBJ(lb)) {
        DISABLE_SIGNALS();
        DISABLE_SIGNALS();
        LOCK();
        LOCK();
        result = GC_generic_malloc_inner((word)lb, k);
        result = GC_generic_malloc_inner((word)lb, k);
        UNLOCK();
        UNLOCK();
        ENABLE_SIGNALS();
        ENABLE_SIGNALS();
    } else {
    } else {
        word lw;
        word lw;
        word n_blocks;
        word n_blocks;
        GC_bool init;
        GC_bool init;
        lw = ROUNDED_UP_WORDS(lb);
        lw = ROUNDED_UP_WORDS(lb);
        n_blocks = OBJ_SZ_TO_BLOCKS(lw);
        n_blocks = OBJ_SZ_TO_BLOCKS(lw);
        init = GC_obj_kinds[k].ok_init;
        init = GC_obj_kinds[k].ok_init;
        DISABLE_SIGNALS();
        DISABLE_SIGNALS();
        LOCK();
        LOCK();
        result = (ptr_t)GC_alloc_large(lw, k, 0);
        result = (ptr_t)GC_alloc_large(lw, k, 0);
        if (0 != result) {
        if (0 != result) {
          if (GC_debugging_started) {
          if (GC_debugging_started) {
            BZERO(result, n_blocks * HBLKSIZE);
            BZERO(result, n_blocks * HBLKSIZE);
          } else {
          } else {
#           ifdef THREADS
#           ifdef THREADS
              /* Clear any memory that might be used for GC descriptors */
              /* Clear any memory that might be used for GC descriptors */
              /* before we release the lock.                          */
              /* before we release the lock.                          */
                ((word *)result)[0] = 0;
                ((word *)result)[0] = 0;
                ((word *)result)[1] = 0;
                ((word *)result)[1] = 0;
                ((word *)result)[lw-1] = 0;
                ((word *)result)[lw-1] = 0;
                ((word *)result)[lw-2] = 0;
                ((word *)result)[lw-2] = 0;
#           endif
#           endif
          }
          }
        }
        }
        GC_words_allocd += lw;
        GC_words_allocd += lw;
        UNLOCK();
        UNLOCK();
        ENABLE_SIGNALS();
        ENABLE_SIGNALS();
        if (init && !GC_debugging_started && 0 != result) {
        if (init && !GC_debugging_started && 0 != result) {
            BZERO(result, n_blocks * HBLKSIZE);
            BZERO(result, n_blocks * HBLKSIZE);
        }
        }
    }
    }
    if (0 == result) {
    if (0 == result) {
        return((*GC_oom_fn)(lb));
        return((*GC_oom_fn)(lb));
    } else {
    } else {
        return(result);
        return(result);
    }
    }
}
}
 
 
 
 
#define GENERAL_MALLOC(lb,k) \
#define GENERAL_MALLOC(lb,k) \
    (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
    (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
/* We make the GC_clear_stack_call a tail call, hoping to get more of   */
/* We make the GC_clear_stack_call a tail call, hoping to get more of   */
/* the stack.                                                           */
/* the stack.                                                           */
 
 
/* Allocate lb bytes of atomic (pointerfree) data */
/* Allocate lb bytes of atomic (pointerfree) data */
# ifdef __STDC__
# ifdef __STDC__
    GC_PTR GC_malloc_atomic(size_t lb)
    GC_PTR GC_malloc_atomic(size_t lb)
# else
# else
    GC_PTR GC_malloc_atomic(lb)
    GC_PTR GC_malloc_atomic(lb)
    size_t lb;
    size_t lb;
# endif
# endif
{
{
register ptr_t op;
register ptr_t op;
register ptr_t * opp;
register ptr_t * opp;
register word lw;
register word lw;
DCL_LOCK_STATE;
DCL_LOCK_STATE;
 
 
    if( EXPECT(SMALL_OBJ(lb), 1) ) {
    if( EXPECT(SMALL_OBJ(lb), 1) ) {
#       ifdef MERGE_SIZES
#       ifdef MERGE_SIZES
          lw = GC_size_map[lb];
          lw = GC_size_map[lb];
#       else
#       else
          lw = ALIGNED_WORDS(lb);
          lw = ALIGNED_WORDS(lb);
#       endif
#       endif
        opp = &(GC_aobjfreelist[lw]);
        opp = &(GC_aobjfreelist[lw]);
        FASTLOCK();
        FASTLOCK();
        if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) {
        if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) {
            FASTUNLOCK();
            FASTUNLOCK();
            return(GENERAL_MALLOC((word)lb, PTRFREE));
            return(GENERAL_MALLOC((word)lb, PTRFREE));
        }
        }
        /* See above comment on signals.        */
        /* See above comment on signals.        */
        *opp = obj_link(op);
        *opp = obj_link(op);
        GC_words_allocd += lw;
        GC_words_allocd += lw;
        FASTUNLOCK();
        FASTUNLOCK();
        return((GC_PTR) op);
        return((GC_PTR) op);
   } else {
   } else {
       return(GENERAL_MALLOC((word)lb, PTRFREE));
       return(GENERAL_MALLOC((word)lb, PTRFREE));
   }
   }
}
}
 
 
/* Allocate lb bytes of composite (pointerful) data */
/* Allocate lb bytes of composite (pointerful) data */
# ifdef __STDC__
# ifdef __STDC__
    GC_PTR GC_malloc(size_t lb)
    GC_PTR GC_malloc(size_t lb)
# else
# else
    GC_PTR GC_malloc(lb)
    GC_PTR GC_malloc(lb)
    size_t lb;
    size_t lb;
# endif
# endif
{
{
register ptr_t op;
register ptr_t op;
register ptr_t *opp;
register ptr_t *opp;
register word lw;
register word lw;
DCL_LOCK_STATE;
DCL_LOCK_STATE;
 
 
    if( EXPECT(SMALL_OBJ(lb), 1) ) {
    if( EXPECT(SMALL_OBJ(lb), 1) ) {
#       ifdef MERGE_SIZES
#       ifdef MERGE_SIZES
          lw = GC_size_map[lb];
          lw = GC_size_map[lb];
#       else
#       else
          lw = ALIGNED_WORDS(lb);
          lw = ALIGNED_WORDS(lb);
#       endif
#       endif
        opp = &(GC_objfreelist[lw]);
        opp = &(GC_objfreelist[lw]);
        FASTLOCK();
        FASTLOCK();
        if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) {
        if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) {
            FASTUNLOCK();
            FASTUNLOCK();
            return(GENERAL_MALLOC((word)lb, NORMAL));
            return(GENERAL_MALLOC((word)lb, NORMAL));
        }
        }
        /* See above comment on signals.        */
        /* See above comment on signals.        */
        GC_ASSERT(0 == obj_link(op)
        GC_ASSERT(0 == obj_link(op)
                  || (word)obj_link(op)
                  || (word)obj_link(op)
                        <= (word)GC_greatest_plausible_heap_addr
                        <= (word)GC_greatest_plausible_heap_addr
                     && (word)obj_link(op)
                     && (word)obj_link(op)
                        >= (word)GC_least_plausible_heap_addr);
                        >= (word)GC_least_plausible_heap_addr);
        *opp = obj_link(op);
        *opp = obj_link(op);
        obj_link(op) = 0;
        obj_link(op) = 0;
        GC_words_allocd += lw;
        GC_words_allocd += lw;
        FASTUNLOCK();
        FASTUNLOCK();
        return((GC_PTR) op);
        return((GC_PTR) op);
   } else {
   } else {
       return(GENERAL_MALLOC((word)lb, NORMAL));
       return(GENERAL_MALLOC((word)lb, NORMAL));
   }
   }
}
}
 
 
# ifdef REDIRECT_MALLOC
# ifdef REDIRECT_MALLOC
 
 
/* Avoid unnecessary nested procedure calls here, by #defining some     */
/* Avoid unnecessary nested procedure calls here, by #defining some     */
/* malloc replacements.  Otherwise we end up saving a                   */
/* malloc replacements.  Otherwise we end up saving a                   */
/* meaningless return address in the object.  It also speeds things up, */
/* meaningless return address in the object.  It also speeds things up, */
/* but it is admittedly quite ugly.                                     */
/* but it is admittedly quite ugly.                                     */
# ifdef GC_ADD_CALLER
# ifdef GC_ADD_CALLER
#   define RA GC_RETURN_ADDR,
#   define RA GC_RETURN_ADDR,
# else
# else
#   define RA
#   define RA
# endif
# endif
# define GC_debug_malloc_replacement(lb) \
# define GC_debug_malloc_replacement(lb) \
        GC_debug_malloc(lb, RA "unknown", 0)
        GC_debug_malloc(lb, RA "unknown", 0)
 
 
# ifdef __STDC__
# ifdef __STDC__
    GC_PTR malloc(size_t lb)
    GC_PTR malloc(size_t lb)
# else
# else
    GC_PTR malloc(lb)
    GC_PTR malloc(lb)
    size_t lb;
    size_t lb;
# endif
# endif
  {
  {
    /* It might help to manually inline the GC_malloc call here.        */
    /* It might help to manually inline the GC_malloc call here.        */
    /* But any decent compiler should reduce the extra procedure call   */
    /* But any decent compiler should reduce the extra procedure call   */
    /* to at most a jump instruction in this case.                      */
    /* to at most a jump instruction in this case.                      */
#   if defined(I386) && defined(GC_SOLARIS_THREADS)
#   if defined(I386) && defined(GC_SOLARIS_THREADS)
      /*
      /*
       * Thread initialisation can call malloc before
       * Thread initialisation can call malloc before
       * we're ready for it.
       * we're ready for it.
       * It's not clear that this is enough to help matters.
       * It's not clear that this is enough to help matters.
       * The thread implementation may well call malloc at other
       * The thread implementation may well call malloc at other
       * inopportune times.
       * inopportune times.
       */
       */
      if (!GC_is_initialized) return sbrk(lb);
      if (!GC_is_initialized) return sbrk(lb);
#   endif /* I386 && GC_SOLARIS_THREADS */
#   endif /* I386 && GC_SOLARIS_THREADS */
    return((GC_PTR)REDIRECT_MALLOC(lb));
    return((GC_PTR)REDIRECT_MALLOC(lb));
  }
  }
 
 
# ifdef __STDC__
# ifdef __STDC__
    GC_PTR calloc(size_t n, size_t lb)
    GC_PTR calloc(size_t n, size_t lb)
# else
# else
    GC_PTR calloc(n, lb)
    GC_PTR calloc(n, lb)
    size_t n, lb;
    size_t n, lb;
# endif
# endif
  {
  {
    return((GC_PTR)REDIRECT_MALLOC(n*lb));
    return((GC_PTR)REDIRECT_MALLOC(n*lb));
  }
  }
 
 
#ifndef strdup
#ifndef strdup
# include <string.h>
# include <string.h>
# ifdef __STDC__
# ifdef __STDC__
    char *strdup(const char *s)
    char *strdup(const char *s)
# else
# else
    char *strdup(s)
    char *strdup(s)
    char *s;
    char *s;
# endif
# endif
  {
  {
    size_t len = strlen(s) + 1;
    size_t len = strlen(s) + 1;
    char * result = ((char *)REDIRECT_MALLOC(len+1));
    char * result = ((char *)REDIRECT_MALLOC(len+1));
    BCOPY(s, result, len+1);
    BCOPY(s, result, len+1);
    return result;
    return result;
  }
  }
#endif /* !defined(strdup) */
#endif /* !defined(strdup) */
 /* If strdup is macro defined, we assume that it actually calls malloc, */
 /* If strdup is macro defined, we assume that it actually calls malloc, */
 /* and thus the right thing will happen even without overriding it.     */
 /* and thus the right thing will happen even without overriding it.     */
 /* This seems to be true on most Linux systems.                         */
 /* This seems to be true on most Linux systems.                         */
 
 
#undef GC_debug_malloc_replacement
#undef GC_debug_malloc_replacement
 
 
# endif /* REDIRECT_MALLOC */
# endif /* REDIRECT_MALLOC */
 
 
/* Explicitly deallocate an object p.                           */
/* Explicitly deallocate an object p.                           */
# ifdef __STDC__
# ifdef __STDC__
    void GC_free(GC_PTR p)
    void GC_free(GC_PTR p)
# else
# else
    void GC_free(p)
    void GC_free(p)
    GC_PTR p;
    GC_PTR p;
# endif
# endif
{
{
    register struct hblk *h;
    register struct hblk *h;
    register hdr *hhdr;
    register hdr *hhdr;
    register signed_word sz;
    register signed_word sz;
    register ptr_t * flh;
    register ptr_t * flh;
    register int knd;
    register int knd;
    register struct obj_kind * ok;
    register struct obj_kind * ok;
    DCL_LOCK_STATE;
    DCL_LOCK_STATE;
 
 
    if (p == 0) return;
    if (p == 0) return;
        /* Required by ANSI.  It's not my fault ...     */
        /* Required by ANSI.  It's not my fault ...     */
    h = HBLKPTR(p);
    h = HBLKPTR(p);
    hhdr = HDR(h);
    hhdr = HDR(h);
    GC_ASSERT(GC_base(p) == p);
    GC_ASSERT(GC_base(p) == p);
#   if defined(REDIRECT_MALLOC) && \
#   if defined(REDIRECT_MALLOC) && \
        (defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \
        (defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \
         || defined(__MINGW32__)) /* Should this be MSWIN32 in general? */
         || defined(__MINGW32__)) /* Should this be MSWIN32 in general? */
        /* For Solaris, we have to redirect malloc calls during         */
        /* For Solaris, we have to redirect malloc calls during         */
        /* initialization.  For the others, this seems to happen        */
        /* initialization.  For the others, this seems to happen        */
        /* implicitly.                                                  */
        /* implicitly.                                                  */
        /* Don't try to deallocate that memory.                         */
        /* Don't try to deallocate that memory.                         */
        if (0 == hhdr) return;
        if (0 == hhdr) return;
#   endif
#   endif
    knd = hhdr -> hb_obj_kind;
    knd = hhdr -> hb_obj_kind;
    sz = hhdr -> hb_sz;
    sz = hhdr -> hb_sz;
    ok = &GC_obj_kinds[knd];
    ok = &GC_obj_kinds[knd];
    if (EXPECT((sz <= MAXOBJSZ), 1)) {
    if (EXPECT((sz <= MAXOBJSZ), 1)) {
#       ifdef THREADS
#       ifdef THREADS
            DISABLE_SIGNALS();
            DISABLE_SIGNALS();
            LOCK();
            LOCK();
#       endif
#       endif
        GC_mem_freed += sz;
        GC_mem_freed += sz;
        /* A signal here can make GC_mem_freed and GC_non_gc_bytes      */
        /* A signal here can make GC_mem_freed and GC_non_gc_bytes      */
        /* inconsistent.  We claim this is benign.                      */
        /* inconsistent.  We claim this is benign.                      */
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
                /* Its unnecessary to clear the mark bit.  If the       */
                /* Its unnecessary to clear the mark bit.  If the       */
                /* object is reallocated, it doesn't matter.  O.w. the  */
                /* object is reallocated, it doesn't matter.  O.w. the  */
                /* collector will do it, since it's on a free list.     */
                /* collector will do it, since it's on a free list.     */
        if (ok -> ok_init) {
        if (ok -> ok_init) {
            BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
            BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
        }
        }
        flh = &(ok -> ok_freelist[sz]);
        flh = &(ok -> ok_freelist[sz]);
        obj_link(p) = *flh;
        obj_link(p) = *flh;
        *flh = (ptr_t)p;
        *flh = (ptr_t)p;
#       ifdef THREADS
#       ifdef THREADS
            UNLOCK();
            UNLOCK();
            ENABLE_SIGNALS();
            ENABLE_SIGNALS();
#       endif
#       endif
    } else {
    } else {
        DISABLE_SIGNALS();
        DISABLE_SIGNALS();
        LOCK();
        LOCK();
        GC_mem_freed += sz;
        GC_mem_freed += sz;
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
        GC_freehblk(h);
        GC_freehblk(h);
        UNLOCK();
        UNLOCK();
        ENABLE_SIGNALS();
        ENABLE_SIGNALS();
    }
    }
}
}
 
 
/* Explicitly deallocate an object p when we already hold lock.         */
/* Explicitly deallocate an object p when we already hold lock.         */
/* Only used for internally allocated objects, so we can take some      */
/* Only used for internally allocated objects, so we can take some      */
/* shortcuts.                                                           */
/* shortcuts.                                                           */
#ifdef THREADS
#ifdef THREADS
void GC_free_inner(GC_PTR p)
void GC_free_inner(GC_PTR p)
{
{
    register struct hblk *h;
    register struct hblk *h;
    register hdr *hhdr;
    register hdr *hhdr;
    register signed_word sz;
    register signed_word sz;
    register ptr_t * flh;
    register ptr_t * flh;
    register int knd;
    register int knd;
    register struct obj_kind * ok;
    register struct obj_kind * ok;
    DCL_LOCK_STATE;
    DCL_LOCK_STATE;
 
 
    h = HBLKPTR(p);
    h = HBLKPTR(p);
    hhdr = HDR(h);
    hhdr = HDR(h);
    knd = hhdr -> hb_obj_kind;
    knd = hhdr -> hb_obj_kind;
    sz = hhdr -> hb_sz;
    sz = hhdr -> hb_sz;
    ok = &GC_obj_kinds[knd];
    ok = &GC_obj_kinds[knd];
    if (sz <= MAXOBJSZ) {
    if (sz <= MAXOBJSZ) {
        GC_mem_freed += sz;
        GC_mem_freed += sz;
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
        if (ok -> ok_init) {
        if (ok -> ok_init) {
            BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
            BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
        }
        }
        flh = &(ok -> ok_freelist[sz]);
        flh = &(ok -> ok_freelist[sz]);
        obj_link(p) = *flh;
        obj_link(p) = *flh;
        *flh = (ptr_t)p;
        *flh = (ptr_t)p;
    } else {
    } else {
        GC_mem_freed += sz;
        GC_mem_freed += sz;
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
        GC_freehblk(h);
        GC_freehblk(h);
    }
    }
}
}
#endif /* THREADS */
#endif /* THREADS */
 
 
# if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE)
# if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE)
#   define REDIRECT_FREE GC_free
#   define REDIRECT_FREE GC_free
# endif
# endif
# ifdef REDIRECT_FREE
# ifdef REDIRECT_FREE
#   ifdef __STDC__
#   ifdef __STDC__
      void free(GC_PTR p)
      void free(GC_PTR p)
#   else
#   else
      void free(p)
      void free(p)
      GC_PTR p;
      GC_PTR p;
#   endif
#   endif
  {
  {
#   ifndef IGNORE_FREE
#   ifndef IGNORE_FREE
      REDIRECT_FREE(p);
      REDIRECT_FREE(p);
#   endif
#   endif
  }
  }
# endif  /* REDIRECT_MALLOC */
# endif  /* REDIRECT_MALLOC */
 
 

powered by: WebSVN 2.1.0

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