/* Allocate a large block of size lw words. */
/* The block is not cleared. */
/* Flags is 0 or IGNORE_OFF_PAGE. */
+/* We hold the allocation lock. */
ptr_t GC_alloc_large(lw, k, flags)
word lw;
int k;
if (h == 0) {
result = 0;
} else {
- int total_bytes = BYTES_TO_WORDS(n_blocks * HBLKSIZE);
+ int total_bytes = n_blocks * HBLKSIZE;
if (n_blocks > 1) {
- GC_large_allocd_bytes += n_blocks * HBLKSIZE;
+ GC_large_allocd_bytes += total_bytes;
if (GC_large_allocd_bytes > GC_max_large_allocd_bytes)
GC_max_large_allocd_bytes = GC_large_allocd_bytes;
}
result = (ptr_t) (h -> hb_body);
- GC_words_wasted += total_bytes - lw;
+ GC_words_wasted += BYTES_TO_WORDS(total_bytes) - lw;
}
return result;
}
/* Allocate a large block of size lb bytes. Clear if appropriate. */
+/* We hold the allocation lock. */
ptr_t GC_alloc_large_and_clear(lw, k, flags)
word lw;
int k;
ptr_t result;
DCL_LOCK_STATE;
+ if (GC_have_errors) GC_print_all_errors();
GC_INVOKE_FINALIZERS();
if (SMALL_OBJ(lb)) {
DISABLE_SIGNALS();
GC_words_allocd += lw;
UNLOCK();
ENABLE_SIGNALS();
- if (init & !GC_debugging_started && 0 != result) {
+ if (init && !GC_debugging_started && 0 != result) {
BZERO(result, n_blocks * HBLKSIZE);
}
}
return(GENERAL_MALLOC((word)lb, NORMAL));
}
/* See above comment on signals. */
+ GC_ASSERT(0 == obj_link(op)
+ || (word)obj_link(op)
+ <= (word)GC_greatest_plausible_heap_addr
+ && (word)obj_link(op)
+ >= (word)GC_least_plausible_heap_addr);
*opp = obj_link(op);
obj_link(op) = 0;
GC_words_allocd += lw;
}
# ifdef REDIRECT_MALLOC
+
+/* Avoid unnecessary nested procedure calls here, by #defining some */
+/* malloc replacements. Otherwise we end up saving a */
+/* meaningless return address in the object. It also speeds things up, */
+/* but it is admittedly quite ugly. */
+# ifdef GC_ADD_CALLER
+# define RA GC_RETURN_ADDR,
+# else
+# define RA
+# endif
+# define GC_debug_malloc_replacement(lb) \
+ GC_debug_malloc(lb, RA "unknown", 0)
+
# ifdef __STDC__
GC_PTR malloc(size_t lb)
# else
/* It might help to manually inline the GC_malloc call here. */
/* But any decent compiler should reduce the extra procedure call */
/* to at most a jump instruction in this case. */
-# if defined(I386) && defined(SOLARIS_THREADS)
+# if defined(I386) && defined(GC_SOLARIS_THREADS)
/*
* Thread initialisation can call malloc before
* we're ready for it.
* inopportune times.
*/
if (!GC_is_initialized) return sbrk(lb);
-# endif /* I386 && SOLARIS_THREADS */
+# endif /* I386 && GC_SOLARIS_THREADS */
return((GC_PTR)REDIRECT_MALLOC(lb));
}
{
return((GC_PTR)REDIRECT_MALLOC(n*lb));
}
+
+#ifndef strdup
+# include <string.h>
+# ifdef __STDC__
+ char *strdup(const char *s)
+# else
+ char *strdup(s)
+ char *s;
+# endif
+ {
+ size_t len = strlen(s) + 1;
+ char * result = ((char *)REDIRECT_MALLOC(len+1));
+ BCOPY(s, result, len+1);
+ return result;
+ }
+#endif /* !defined(strdup) */
+ /* If strdup is macro defined, we assume that it actually calls malloc, */
+ /* and thus the right thing will happen even without overriding it. */
+ /* This seems to be true on most Linux systems. */
+
+#undef GC_debug_malloc_replacement
+
# endif /* REDIRECT_MALLOC */
/* Explicitly deallocate an object p. */
/* Required by ANSI. It's not my fault ... */
h = HBLKPTR(p);
hhdr = HDR(h);
+ GC_ASSERT(GC_base(p) == p);
# if defined(REDIRECT_MALLOC) && \
- (defined(SOLARIS_THREADS) || defined(LINUX_THREADS) \
+ (defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \
|| defined(__MINGW32__)) /* Should this be MSWIN32 in general? */
/* For Solaris, we have to redirect malloc calls during */
/* initialization. For the others, this seems to happen */
}
#endif /* THREADS */
-# ifdef REDIRECT_MALLOC
+# if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE)
+# define REDIRECT_FREE GC_free
+# endif
+# ifdef REDIRECT_FREE
# ifdef __STDC__
void free(GC_PTR p)
# else
# endif
{
# ifndef IGNORE_FREE
- GC_free(p);
+ REDIRECT_FREE(p);
# endif
}
# endif /* REDIRECT_MALLOC */