3#include <M2/gc-include.h>
18 if (
in_getmem) fatal(
"internal error: getmem called while getmem active");
58 const char *msg =
"\n\n *** out of memory, exiting ***\n";
59 int r = write(
STDERR,msg,strlen(msg));
60 if (r ==
ERROR) exit(1);
65 const char *msg =
"\n\n *** out of memory trying to allocate %ld bytes, exiting ***\n";
66 static char buf[
sizeof(msg) + 100];
67 snprintf(buf,
sizeof(msg) + 100,
69 int r = write(
STDERR,buf,strlen(buf));
70 if (r ==
ERROR) exit(1);
80 p = M2_debug_malloc(n);
82 p =
reinterpret_cast<char*
>(GC_MALLOC(n));
117 p = M2_debug_malloc(n);
119 p =
reinterpret_cast<char*
>(GC_MALLOC(n));
140 p = M2_debug_malloc_atomic(n);
142 p =
reinterpret_cast<char*
>(GC_MALLOC_ATOMIC(n));
172 p = M2_debug_malloc_atomic(n);
174 p =
reinterpret_cast<char*
>(GC_MALLOC_ATOMIC(n));
370#include <M2/config.h>
371#include <M2/gc-include.h>
379#define FRONT_FENCE 0xaaaaaaaa
380#define FRONT_FENCE_GONE 0xa0a0a0a0
381#define BODY_PART 0xbbbbbbbb
382#define BODY_PART_GONE 0xb0b0b0b0
383#define REAR_FENCE 0xcccccccc
384#define REAR_FENCE_GONE 0xc0c0c0c0
389 unsigned int fence[FENCE_INTS];
393 unsigned int fence[FENCE_INTS];
401void *delay_chain[FREE_DELAY];
402int delay_chain_index;
404size_t M2_debug_size(
void *
p) {
406 if (
p == NULL)
return 0;
407 f = (
struct FRONT *)(
p -
sizeof(
struct FRONT));
411void *M2_debug_malloc(
size_t size) {
416 int INTS_BODY = (size +
sizeof(
int) - 1)/
sizeof(
int);
417 f = (
struct FRONT *)GC_MALLOC(
sizeof(
struct FRONT) +
sizeof(
int)*INTS_BODY +
sizeof(
struct REAR) );
419 p = (
char *)f +
sizeof(
struct FRONT);
420 r = (
struct REAR *)(
p +
sizeof(
int)*INTS_BODY);
421 f->size = r->size = size;
422 for (i=0; i<FENCE_INTS; i++) f->fence[i] = FRONT_FENCE;
423 for (i=0; i<INTS_BODY; i++) ((
int *)
p)[i] = BODY_PART;
424 for (i=0; i<FENCE_INTS; i++) r->fence[i] = REAR_FENCE;
425 f->trapcount = r->trapcount =
trapcount+1;
430void* M2_debug_malloc_uncollectable(
size_t size) {
435 int INTS_BODY = (size +
sizeof(
int) - 1)/
sizeof(
int);
436 f = (
struct FRONT *)GC_MALLOC_UNCOLLECTABLE(
437 sizeof(
struct FRONT) +
sizeof(
int)*INTS_BODY +
sizeof(
struct REAR)
440 p = (
char *)f +
sizeof(
struct FRONT);
441 r = (
struct REAR *)(
p +
sizeof(
int)*INTS_BODY);
442 f->size = r->size = size;
443 for (i=0; i<FENCE_INTS; i++) f->fence[i] = FRONT_FENCE;
444 for (i=0; i<INTS_BODY; i++) ((
int *)
p)[i] = BODY_PART;
445 for (i=0; i<FENCE_INTS; i++) r->fence[i] = REAR_FENCE;
446 f->trapcount = r->trapcount =
trapcount+1;
451void* M2_debug_malloc_atomic(
size_t size) {
456 int INTS_BODY = (size +
sizeof(
int) - 1)/
sizeof(
int);
457 f = (
struct FRONT *)GC_MALLOC_ATOMIC(
sizeof(
struct FRONT) +
sizeof(
int)*INTS_BODY +
sizeof(
struct REAR) );
459 p = (
void *)f +
sizeof(
struct FRONT);
460 r = (
struct REAR *)(
p +
sizeof(
int)*INTS_BODY);
461 f->size = r->size = size;
462 for (i=0; i<FENCE_INTS; i++) f->fence[i] = FRONT_FENCE;
463 for (i=0; i<INTS_BODY; i++) ((
int *)
p)[i] = BODY_PART;
464 for (i=0; i<FENCE_INTS; i++) r->fence[i] = REAR_FENCE;
465 f->trapcount = r->trapcount =
trapcount+1;
470void* M2_debug_malloc_atomic_uncollectable(
size_t size) {
475 int INTS_BODY = (size +
sizeof(
int) - 1)/
sizeof(
int);
476 f = (
struct FRONT *)GC_MALLOC_ATOMIC_UNCOLLECTABLE(
sizeof(
struct FRONT) +
sizeof(
int)*INTS_BODY +
sizeof(
struct REAR) );
478 p = (
void *)f +
sizeof(
struct FRONT);
479 r = (
struct REAR *)(
p +
sizeof(
int)*INTS_BODY);
480 f->size = r->size = size;
481 for (i=0; i<FENCE_INTS; i++) f->fence[i] = FRONT_FENCE;
482 for (i=0; i<INTS_BODY; i++) ((
int *)
p)[i] = BODY_PART;
483 for (i=0; i<FENCE_INTS; i++) r->fence[i] = REAR_FENCE;
484 f->trapcount = r->trapcount =
trapcount+1;
489static void volatile smashed(
void *
p) {
490 if (0 == GC_base(
p)) {
491 fprintf(stderr,
"-- *** memdebug -- non-heap object encountered, %p, aborting\n",
p);
494 fprintf(stderr,
"-- *** memdebug -- smashed object found, %p, aborting\n",
p);
500void *M2_debug_to_outer(
void *
p) {
501 struct FRONT *f =
p -
sizeof(
struct FRONT);
502 if (f->fence[0] != FRONT_FENCE) smashed(
p);
507void *M2_debug_to_inner(
void *q) {
509 if (f->fence[0] != FRONT_FENCE) smashed(q);
510 return (
void *)f +
sizeof(
struct FRONT);
513void M2_debug_info(
void *
p) {
516 int INTS_BODY, i, smashed = 0;
518 if (
p == NULL)
return;
519 f =
p -
sizeof(
struct FRONT);
521 INTS_BODY = (size +
sizeof(
int) - 1)/
sizeof(
int);
522 r = (
struct REAR *)(
p +
sizeof(
int)*INTS_BODY);
523 for (i=0; i<FENCE_INTS; i++)
if (f->fence[i] != FRONT_FENCE) smashed = 1;
524 for (i=0; i<FENCE_INTS; i++)
if (r->fence[i] != REAR_FENCE ) smashed = 1;
525 fprintf(stderr,
"addr %p, base %p, GC_base %p, trapcount %d, length %lu%s\n",
p,f,GC_base(
p),f->trapcount,size,smashed ?
", smashed" :
"");
528void M2_debug_free(
void *
p) {
531 int INTS_BODY, i, _trapcount;
533 if (
p == NULL)
return;
534 f = (
struct FRONT *)(
p -
sizeof(
struct FRONT));
536 INTS_BODY = (size +
sizeof(
int) - 1)/
sizeof(
int);
537 r =
p +
sizeof(
int)*INTS_BODY;
538 _trapcount = f->trapcount;
539 if (r->trapcount != _trapcount || r->size != size) smashed(
p);
540 for (i=0; i<FENCE_INTS; i++)
if (f->fence[i] != FRONT_FENCE) smashed(
p);
541 for (i=0; i<FENCE_INTS; i++)
if (r->fence[i] != REAR_FENCE ) smashed(
p);
544 for (i=0; i<FENCE_INTS; i++) f->fence[i] = FRONT_FENCE_GONE;
545 for (i=0; i<INTS_BODY; i++) ((
int *)
p)[i] = BODY_PART_GONE;
546 for (i=0; i<FENCE_INTS; i++) r->fence[i] = REAR_FENCE_GONE;
548 if (delay_chain[delay_chain_index] != NULL) {
549 GC_FREE(delay_chain[delay_chain_index]);
551 delay_chain[delay_chain_index] = (
void *)f;
552 delay_chain_index ++;
553 if (delay_chain_index == FREE_DELAY) delay_chain_index = 0;
559void* M2_debug_realloc(
void *old,
size_t size) {
560 void *newsize = M2_debug_malloc(size);
561 size_t oldsize = M2_debug_size(old);
563 memcpy(newsize,old,size < oldsize ? size : oldsize);
void * I_WRAP_SONAME_FNNAME_ZU(libgcZdsoZd1, GC_malloc)(size_t s)
char * getmem_atomic_clear(size_t n)
void trapchk_size(size_t n)
CALL_FN_W_WW(result, fn,(long) p, s)
static __thread bool in_getmem
char * getmem_clear(size_t n)
void freememlen(void *s, size_t old)
static void exit_getmem()
static void enter_getmem()
void outofmem2(size_t newsize)
char * getmem_atomic(size_t n)
VALGRIND_MAKE_MEM_DEFINED & result(result)
Engine-wide GC allocator surface (getmem / getmem_atomic) and debug-allocation trap.