This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/C/alloc.c

1602 lines
41 KiB
C
Raw Normal View History

2017-01-09 14:58:01 +00:00
/*************************************************************************
* *
* YAP Prolog *
* *
* Yap Prolog was developed at NCCUP - Universidade do Porto *
* *
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
* *
**************************************************************************
* *
* File: alloc.c *
* Last rev: *
* mods: *
* comments: allocating space *
* version:$Id: alloc.c,v 1.95 2008-05-10 23:24:11 vsc Exp $ *
*************************************************************************/
#ifdef SCCS
static char SccsId[] = "%W% %G%";
#endif
#include "Yap.h"
2016-08-02 01:14:01 +01:00
#include "YapHeap.h"
2016-08-01 23:48:25 +01:00
#include "Yatom.h"
2016-09-09 04:33:55 +01:00
#include "alloc.h"
#include "yapio.h"
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_MALLOC_H
#include <malloc.h>
#endif
#if USE_DL_MALLOC
#include "dlmalloc.h"
#endif
#if HAVE_MEMORY_H
#include <memory.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
2008-11-26 09:56:18 +00:00
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include <stdio.h>
2016-08-01 23:48:25 +01:00
#include <stdlib.h>
#if __simplescalar__
2014-03-07 23:07:46 +00:00
#ifdef USE_SYSTEM_MMAP
#undef USE_SYSTEM_MMAP
#endif
#ifdef USE_SBRK
#undef USE_SBRK
#endif
#endif
/************************************************************************/
/* Yap workspace management */
#define MASK 0x968e00
#if USE_SYSTEM_MALLOC
2016-07-31 05:07:06 +01:00
#if 1
#undef free
#undef malloc
#undef realloc
2016-08-01 23:48:25 +01:00
int write_malloc = 0;
2016-07-31 05:07:06 +01:00
2016-08-01 23:48:25 +01:00
void *my_malloc(size_t sz) {
void *p;
2016-07-31 05:07:06 +01:00
2016-08-01 23:48:25 +01:00
p = malloc(sz);
// Yap_DebugPuts(stderr,"gof\n");
if (Yap_do_low_level_trace)
2017-02-20 14:38:38 +00:00
fprintf(stderr, "+ %p: %" Sizet_F "\n", p, sz);
2016-08-01 23:48:25 +01:00
if (sz > 500 && write_malloc++ > 0)
__android_log_print(ANDROID_LOG_ERROR, "YAPDroid ", "+ %d %p", write_malloc,
p);
return p;
}
2016-07-31 05:07:06 +01:00
2016-08-01 23:48:25 +01:00
void *my_realloc(void *ptr, size_t sz) {
2016-07-31 05:07:06 +01:00
void *p;
2016-08-01 23:48:25 +01:00
p = realloc(ptr, sz);
if (Yap_do_low_level_trace)
2017-02-20 14:38:38 +00:00
// fprintf(stderr, "+ %p -> %p : " Sizet_F "\n", ptr, p, sz);
// Yap_DebugPuts(stderr,"gof\n");
2016-08-01 23:48:25 +01:00
if (sz > 500 && write_malloc++ > 0)
__android_log_print(ANDROID_LOG_ERROR, "YAPDroid ", "* %d %p", write_malloc,
p);
2016-07-31 05:07:06 +01:00
return p;
}
2016-08-01 23:48:25 +01:00
void my_free(void *p) {
// printf("f %p\n",p);
if (Yap_do_low_level_trace)
2016-09-09 04:33:55 +01:00
fprintf(stderr, "+ %p\n", p);
2016-08-01 23:48:25 +01:00
if (write_malloc && write_malloc++ > 0)
__android_log_print(ANDROID_LOG_ERROR, "YAPDroid ", "- %d %p", write_malloc,
p);
2016-07-31 05:07:06 +01:00
free(p);
// Yap_DebugPuts(stderr,"gof\n");
}
#endif
2016-07-31 05:07:06 +01:00
#else // USE_SYSTEM_MALLOC
#define my_malloc(sz) Yap_dlmalloc(sz)
2016-07-31 05:07:06 +01:00
#define my_realloc(ptr, sz) Yap_dlrealloc(ptr, sz)
#define my_free(sz) Yap_dlfree(sz)
2016-07-31 05:07:06 +01:00
static char *my_reallocl(char *ptr, UInt sz, UInt osz, int safe) {
char *nptr;
2015-09-25 10:57:26 +01:00
restart:
/* simple case */
if (ptr < Yap_HeapBase || ptr > HeapTop) {
/* we have enough room */
nptr = Yap_dlmalloc(sz);
if (nptr) {
memmove(nptr, ptr, osz);
free(ptr);
}
} else {
nptr = Yap_dlrealloc(ptr, sz);
}
if (nptr) {
return nptr;
}
/* we do not have enough room */
if (safe) {
if (Yap_growheap(FALSE, sz, NULL)) {
/* now, we have room */
goto restart;
}
}
/* no room in Heap, gosh */
if (ptr < Yap_HeapBase || ptr > HeapTop) {
/* try expanding outside the heap */
nptr = realloc(ptr, sz);
if (nptr) {
memmove(nptr, ptr, osz);
}
} else {
/* try calling the outside world for help */
nptr = malloc(sz);
if (!nptr)
return NULL;
memmove(nptr, ptr, osz);
Yap_dlfree(ptr);
}
/* did we suceed? at this point we could not care less */
return nptr;
}
#endif
2015-09-25 10:57:26 +01:00
#if USE_SYSTEM_MALLOC || USE_DL_MALLOC
long long unsigned int mallocs, reallocs, frees;
long long unsigned int tmalloc;
#undef INSTRUMENT_MALLOC
2015-09-25 10:57:26 +01:00
static inline char *call_malloc(size_t size) {
CACHE_REGS
char *out;
#if USE_DL_MALLOC
LOCK(DLMallocLock);
#endif
#if INSTRUMENT_MALLOC
mallocs++;
tmalloc += size;
2010-04-15 11:37:15 +01:00
size += sizeof(CELL);
#endif
LOCAL_PrologMode |= MallocMode;
2015-09-25 10:57:26 +01:00
out = (char *)my_malloc(size);
2010-04-15 11:37:15 +01:00
#if INSTRUMENT_MALLOC
2015-09-25 10:57:26 +01:00
*(CELL *)out = size - sizeof(CELL);
2010-04-15 11:37:15 +01:00
out += sizeof(CELL);
#endif
LOCAL_PrologMode &= ~MallocMode;
#if USE_DL_MALLOC
UNLOCK(DLMallocLock);
#endif
return out;
}
2015-09-25 10:57:26 +01:00
void *Yap_AllocCodeSpace(size_t size) {
size = AdjustSize(size);
2015-09-25 10:57:26 +01:00
return call_malloc(size);
}
2015-09-25 10:57:26 +01:00
static inline char *call_realloc(char *p, size_t size) {
CACHE_REGS
char *out;
#if USE_DL_MALLOC
LOCK(DLMallocLock);
#endif
#if INSTRUMENT_MALLOC
2010-04-15 11:37:15 +01:00
reallocs++;
tmalloc += size;
2010-04-15 11:37:15 +01:00
size += sizeof(CELL);
p -= sizeof(CELL);
2015-09-25 10:57:26 +01:00
tmalloc -= *(CELL *)p;
#endif
LOCAL_PrologMode |= MallocMode;
2016-07-31 05:07:06 +01:00
out = (char *)my_realloc(p, size);
2010-04-15 11:37:15 +01:00
#if INSTRUMENT_MALLOC
2015-09-25 10:57:26 +01:00
*(CELL *)out = size - sizeof(CELL);
2010-04-15 11:37:15 +01:00
out += sizeof(CELL);
#endif
LOCAL_PrologMode &= ~MallocMode;
#if USE_DL_MALLOC
UNLOCK(DLMallocLock);
#endif
return out;
}
2015-09-25 10:57:26 +01:00
void *Yap_ReallocCodeSpace(void *p, size_t size) {
size = AdjustSize(size);
2015-09-25 10:57:26 +01:00
return call_realloc(p, size);
}
2015-09-25 10:57:26 +01:00
void Yap_FreeCodeSpace(void *p) {
CACHE_REGS
#if USE_DL_MALLOC
LOCK(DLMallocLock);
#endif
LOCAL_PrologMode |= MallocMode;
#if INSTRUMENT_MALLOC
2010-04-15 11:37:15 +01:00
p -= sizeof(CELL);
2015-09-25 10:57:26 +01:00
tmalloc -= *(CELL *)p;
frees++;
#endif
2015-09-25 10:57:26 +01:00
my_free(p);
LOCAL_PrologMode &= ~MallocMode;
#if USE_DL_MALLOC
UNLOCK(DLMallocLock);
#endif
}
2015-09-25 10:57:26 +01:00
void *Yap_AllocAtomSpace(size_t size) {
size = AdjustSize(size);
return call_malloc(size);
}
2015-09-25 10:57:26 +01:00
void Yap_FreeAtomSpace(void *p) {
CACHE_REGS
#if USE_DL_MALLOC
LOCK(DLMallocLock);
#endif
LOCAL_PrologMode |= MallocMode;
#if INSTRUMENT_MALLOC
2010-04-15 11:37:15 +01:00
p -= sizeof(CELL);
2015-09-25 10:57:26 +01:00
tmalloc -= *(CELL *)p;
frees++;
#endif
2015-09-25 10:57:26 +01:00
my_free(p);
LOCAL_PrologMode &= ~MallocMode;
#if USE_DL_MALLOC
UNLOCK(DLMallocLock);
#endif
}
#endif
/* If you need to dinamically allocate space from the heap, this is
* the macro you should use */
2015-09-25 10:57:26 +01:00
ADDR Yap_InitPreAllocCodeSpace(int wid) {
CACHE_REGS
char *ptr;
2012-12-13 18:12:50 +00:00
UInt sz = REMOTE_ScratchPad(wid).msz;
if (REMOTE_ScratchPad(wid).ptr == NULL) {
#if USE_DL_MALLOC
LOCK(DLMallocLock);
#endif
2012-12-13 18:12:50 +00:00
REMOTE_PrologMode(wid) |= MallocMode;
2010-04-15 11:37:15 +01:00
#if INSTRUMENT_MALLOC
mallocs++;
tmalloc += sz;
sz += sizeof(CELL);
#endif
2015-09-25 10:57:26 +01:00
while (!(ptr =
2013-10-16 09:44:34 +01:00
#ifdef YAPOR_COPY
2015-09-25 10:57:26 +01:00
malloc(sz)
2013-10-16 09:44:34 +01:00
#else
2015-09-25 10:57:26 +01:00
my_malloc(sz)
2013-10-16 09:44:34 +01:00
#endif
2015-09-25 10:57:26 +01:00
)) {
2012-12-13 18:12:50 +00:00
REMOTE_PrologMode(wid) &= ~MallocMode;
#if USE_DL_MALLOC
UNLOCK(DLMallocLock);
#endif
if (!Yap_growheap(FALSE, LOCAL_Error_Size, NULL)) {
2015-09-25 10:57:26 +01:00
Yap_Error(RESOURCE_ERROR_HEAP, TermNil, LOCAL_ErrorMessage);
return (NULL);
}
2010-04-15 11:37:15 +01:00
#if INSTRUMENT_MALLOC
sz -= sizeof(CELL);
2015-09-25 10:57:26 +01:00
*(CELL *)ptr = sz;
2010-04-15 11:37:15 +01:00
ptr += sizeof(CELL);
#endif
#if USE_DL_MALLOC
LOCK(DLMallocLock);
#endif
2012-12-13 18:12:50 +00:00
REMOTE_PrologMode(wid) |= MallocMode;
}
2012-12-13 18:12:50 +00:00
REMOTE_PrologMode(wid) &= ~MallocMode;
#if USE_DL_MALLOC
UNLOCK(DLMallocLock);
#endif
2012-12-13 18:12:50 +00:00
REMOTE_ScratchPad(wid).ptr = ptr;
} else {
2012-12-13 18:12:50 +00:00
ptr = REMOTE_ScratchPad(wid).ptr;
}
AuxBase = (ADDR)(ptr);
2015-09-25 10:57:26 +01:00
AuxSp = (CELL *)(AuxTop = AuxBase + REMOTE_ScratchPad(wid).sz);
return ptr;
}
2015-09-25 10:57:26 +01:00
ADDR Yap_ExpandPreAllocCodeSpace(UInt sz0, void *cip, int safe) {
CACHE_REGS
char *ptr;
2015-11-05 15:24:03 +00:00
UInt sz;
if (sz0 < SCRATCH_INC_SIZE)
sz0 = SCRATCH_INC_SIZE;
2011-05-04 10:11:41 +01:00
if (sz0 < LOCAL_ScratchPad.sz)
2015-09-25 10:57:26 +01:00
sz = LOCAL_ScratchPad.sz + sz0;
else
sz = sz0;
2015-09-25 10:57:26 +01:00
sz = AdjustLargePageSize(sz + sz / 4);
#if USE_DL_MALLOC
LOCK(DLMallocLock);
#endif
LOCAL_PrologMode |= MallocMode;
#if INSTRUMENT_MALLOC
reallocs++;
2011-05-04 10:11:41 +01:00
tmalloc -= LOCAL_ScratchPad.sz;
2010-04-15 11:37:15 +01:00
tmalloc += sz;
#endif
2016-08-01 23:48:25 +01:00
if (!(ptr = my_realloc(LOCAL_ScratchPad.ptr, sz))) {
LOCAL_PrologMode &= ~MallocMode;
#if USE_DL_MALLOC
UNLOCK(DLMallocLock);
#endif
return NULL;
}
LOCAL_PrologMode &= ~MallocMode;
#if USE_DL_MALLOC
UNLOCK(DLMallocLock);
#endif
2011-05-04 10:11:41 +01:00
LOCAL_ScratchPad.sz = LOCAL_ScratchPad.msz = sz;
LOCAL_ScratchPad.ptr = ptr;
AuxBase = ptr;
2015-09-25 10:57:26 +01:00
AuxSp = (CELL *)(AuxTop = ptr + sz);
return ptr;
}
#if USE_SYSTEM_MALLOC
struct various_codes *Yap_heap_regs;
2015-09-25 10:57:26 +01:00
static void InitHeap(void) {
Yap_heap_regs =
(struct various_codes *)calloc(1, sizeof(struct various_codes));
}
2015-09-25 10:57:26 +01:00
void Yap_InitHeap(void *heap_addr) {
InitHeap();
Yap_HoleSize = 0;
HeapMax = 0;
}
2015-09-25 10:57:26 +01:00
static void InitExStacks(int wid, int Trail, int Stack) {
CACHE_REGS
UInt pm, sa;
/* sanity checking for data areas */
if (Trail < MinTrailSpace)
Trail = MinTrailSpace;
if (Stack < MinStackSpace)
Stack = MinStackSpace;
2015-09-25 10:57:26 +01:00
pm = (Trail + Stack) * K; /* memory to be
* requested */
sa = Stack * K; /* stack area size */
#ifdef THREADS
2015-09-25 10:57:26 +01:00
if (wid)
2012-12-13 18:12:50 +00:00
REMOTE_GlobalBase(wid) = (ADDR)REMOTE_ThreadHandle(wid).stack_address;
else
AuxSp = NULL;
#endif
2012-12-13 18:12:50 +00:00
REMOTE_TrailTop(wid) = REMOTE_GlobalBase(wid) + pm;
REMOTE_LocalBase(wid) = REMOTE_GlobalBase(wid) + sa;
REMOTE_TrailBase(wid) = REMOTE_LocalBase(wid) + sizeof(CELL);
2012-12-13 18:12:50 +00:00
REMOTE_ScratchPad(wid).ptr = NULL;
REMOTE_ScratchPad(wid).sz = REMOTE_ScratchPad(wid).msz = SCRATCH_START_SIZE;
2013-11-16 00:27:02 +00:00
#if DEBUG
2011-06-20 14:49:24 +01:00
if (Yap_output_msg) {
UInt ta;
2015-09-25 10:57:26 +01:00
fprintf(stderr,
"HeapBase = %p GlobalBase = %p\n LocalBase = %p TrailTop = %p\n",
Yap_HeapBase, REMOTE_GlobalBase(wid), REMOTE_LocalBase(wid),
REMOTE_TrailTop(wid));
2015-09-25 10:57:26 +01:00
ta = Trail * K; /* trail area size */
fprintf(stderr, "Heap+Aux: %lu\tLocal+Global: %lu\tTrail: %lu\n",
2015-09-25 10:57:26 +01:00
(long unsigned)(pm - sa - ta), (long unsigned)sa,
(long unsigned)ta);
}
#endif /* DEBUG */
}
2015-09-25 10:57:26 +01:00
void Yap_InitExStacks(int wid, int Trail, int Stack) {
2012-12-13 18:12:50 +00:00
InitExStacks(wid, Trail, Stack);
}
#if defined(THREADS)
2015-09-25 10:57:26 +01:00
void Yap_KillStacks(int wid) {
ADDR gb = REMOTE_ThreadHandle(wid).stack_address;
if (gb) {
free(gb);
REMOTE_ThreadHandle(wid).stack_address = NULL;
}
}
#else
2015-09-25 10:57:26 +01:00
void Yap_KillStacks(int wid) {
if (LOCAL_GlobalBase) {
free(LOCAL_GlobalBase);
LOCAL_GlobalBase = NULL;
}
}
#endif
2015-09-25 10:57:26 +01:00
void Yap_InitMemory(UInt Trail, UInt Heap, UInt Stack) { InitHeap(); }
2015-09-25 10:57:26 +01:00
int Yap_ExtendWorkSpace(Int s) {
CACHE_REGS
2015-07-23 00:59:57 +01:00
void *basebp = LOCAL_GlobalBase, *nbp;
2015-09-25 10:57:26 +01:00
UInt s0 = LOCAL_TrailTop - LOCAL_GlobalBase;
nbp = realloc(basebp, s + s0);
if (nbp == NULL)
return FALSE;
#if defined(THREADS)
LOCAL_ThreadHandle.stack_address = (char *)nbp;
#endif
LOCAL_GlobalBase = (char *)nbp;
return TRUE;
}
2015-09-25 10:57:26 +01:00
size_t Yap_ExtendWorkSpaceThroughHole(size_t s) { return 0; }
2015-09-25 10:57:26 +01:00
void Yap_AllocHole(UInt actual_request, UInt total_size) {}
#if HAVE_MALLINFO
2015-09-25 10:57:26 +01:00
UInt Yap_givemallinfo(void) {
struct mallinfo mi = mallinfo();
return mi.uordblks;
}
#endif
#else
#if HAVE_SNPRINTF
2015-09-25 10:57:26 +01:00
#define snprintf3(A, B, C) snprintf(A, B, C)
#define snprintf4(A, B, C, D) snprintf(A, B, C, D)
#define snprintf5(A, B, C, D, E) snprintf(A, B, C, D, E)
#else
2015-09-25 10:57:26 +01:00
#define snprintf3(A, B, C) sprintf(A, C)
#define snprintf4(A, B, C, D) sprintf(A, C, D)
#define snprintf5(A, B, C, D, E) sprintf(A, C, D, E)
#endif
#ifdef LIGHT
#include <stdlib.h>
#endif
#if !USE_DL_MALLOC
2013-04-25 23:15:04 +01:00
static void FreeBlock(BlockHeader *);
static BlockHeader *GetBlock(unsigned long int);
static char *AllocHeap(unsigned long int);
static void RemoveFromFreeList(BlockHeader *);
static void AddToFreeList(BlockHeader *);
2015-09-25 10:57:26 +01:00
#define MinHGap 256 * K
2015-09-25 10:57:26 +01:00
static void RemoveFromFreeList(BlockHeader *b) {
BlockHeader *p;
p = b->b_next_size;
LOCK(HeapUsedLock);
HeapUsed += (b->b_size + 1) * sizeof(YAP_SEG_SIZE);
UNLOCK(HeapUsedLock);
if (p && b->b_size == p->b_size) {
b = b->b_next;
p->b_next = b;
if (b)
b->b_next_size = p;
2015-09-25 10:57:26 +01:00
} else {
BlockHeader **q = &FreeBlocks;
while ((*q) != b)
q = &((*q)->b_next_size);
if (b->b_next) {
p = b->b_next;
*q = p;
p->b_next_size = b->b_next_size;
2015-09-25 10:57:26 +01:00
} else {
*q = b->b_next_size;
}
}
}
2015-09-25 10:57:26 +01:00
static void AddToFreeList(BlockHeader *b) {
BlockHeader **q, *p;
YAP_SEG_SIZE *sp;
/* insert on list of free blocks */
q = &FreeBlocks;
sp = &(b->b_size) + b->b_size;
*sp = b->b_size;
LOCK(HeapUsedLock);
HeapUsed -= (b->b_size + 1) * sizeof(YAP_SEG_SIZE);
UNLOCK(HeapUsedLock);
while ((p = *q) && p->b_size < b->b_size)
q = &p->b_next_size;
if (p && p->b_size == b->b_size) {
b->b_next = p;
b->b_next_size = p->b_next_size;
p->b_next_size = b;
2015-09-25 10:57:26 +01:00
} else {
b->b_next = NIL;
b->b_next_size = p;
}
*q = b;
}
2015-09-25 10:57:26 +01:00
static void FreeBlock(BlockHeader *b) {
BlockHeader *p;
YAP_SEG_SIZE *sp;
/* {
static long long int vsc_free_ops;
2015-09-25 10:57:26 +01:00
vsc_free_ops++;
BlockHeader *q = FreeBlocks;
while (q) q = q->b_next_size;
}*/
/* sanity check */
sp = &(b->b_size) + (b->b_size & ~InUseFlag);
if (!(b->b_size & InUseFlag) || *sp != b->b_size) {
#if !SHORT_INTS
2015-09-25 10:57:26 +01:00
fprintf(
stderr,
"%% YAP INTERNAL ERROR: sanity check failed in FreeBlock %p %x %x\n", b,
b->b_size, Unsigned(*sp));
#else
2015-09-25 10:57:26 +01:00
fprintf(
stderr,
"%% YAP INTERNAL ERROR: sanity check failed in FreeBlock %p %lx %lx\n",
b, b->b_size, *sp);
#endif
return;
}
b->b_size &= ~InUseFlag;
LOCK(FreeBlocksLock);
/* check if we can collapse with other blocsks */
/* check previous */
sp = &(b->b_size) - 1;
2015-09-25 10:57:26 +01:00
if (!(*sp & InUseFlag)) { /* previous block is free */
p = (BlockHeader *)(sp - *sp);
RemoveFromFreeList(p);
p->b_size += b->b_size + 1;
b = p;
}
/* check following */
sp = &(b->b_size) + b->b_size + 1;
2015-09-25 10:57:26 +01:00
if (!(*sp & InUseFlag)) { /* following block is free */
p = (BlockHeader *)sp;
RemoveFromFreeList(p);
b->b_size += p->b_size + 1;
}
LOCK(HeapTopLock);
if (sp == (YAP_SEG_SIZE *)HeapTop) {
LOCK(HeapUsedLock);
HeapUsed -= (b->b_size + 1) * sizeof(YAP_SEG_SIZE);
UNLOCK(HeapUsedLock);
HeapTop = (ADDR)b;
2015-09-25 10:57:26 +01:00
*((YAP_SEG_SIZE *)HeapTop) = InUseFlag;
} else {
2015-09-25 10:57:26 +01:00
/* insert on list of free blocks */
AddToFreeList(b);
}
UNLOCK(HeapTopLock);
UNLOCK(FreeBlocksLock);
}
static BlockHeader *
2015-09-25 10:57:26 +01:00
GetBlock(unsigned long int n) { /* get free block with size at least n */
register BlockHeader **p, *b, *r;
if (FreeBlocks == NIL)
return (NIL);
/* check for bugs */
p = &FreeBlocks;
/* end check for bugs */
p = &FreeBlocks;
while (((b = *p) != NIL) && b->b_size < n)
p = &b->b_next_size;
if (b == NIL || b->b_size < n)
return (NIL);
if ((r = b->b_next) == NIL)
*p = b->b_next_size;
else {
r->b_next_size = b->b_next_size;
*p = r;
}
LOCK(HeapUsedLock);
HeapUsed += (b->b_size + 1) * sizeof(YAP_SEG_SIZE);
if (HeapUsed > HeapMax)
HeapMax = HeapUsed;
UNLOCK(HeapUsedLock);
return (b);
}
2016-07-31 05:07:06 +01:00
static char *AllocHeap(size_t size) {
BlockHeader *b, *n;
YAP_SEG_SIZE *sp;
UInt align, extra;
/* {
static long long int vsc_alloc_ops;
vsc_alloc_ops++;
BlockHeader *q = FreeBlocks;
while (q) q = q->b_next_size;
}*/
2015-09-25 10:57:26 +01:00
extra = size / 16;
#if SIZEOF_INT_P == 4
align = 2 * sizeof(CELL); /* size in dwords + 2 */
#endif
2015-09-25 10:57:26 +01:00
#if SIZEOF_INT_P == 8
align = sizeof(CELL);
#endif
2015-09-25 10:57:26 +01:00
while (align < extra)
align *= 2;
size = ALIGN_SIZE(size, align);
if (size < sizeof(BlockHeader))
size = sizeof(BlockHeader);
size += sizeof(YAP_SEG_SIZE);
/* change units to cells */
2015-09-25 10:57:26 +01:00
size = size / sizeof(CELL);
LOCK(FreeBlocksLock);
if ((b = GetBlock(size))) {
2015-09-25 10:57:26 +01:00
if (b->b_size >= size + 24 + 1) {
n = (BlockHeader *)(((YAP_SEG_SIZE *)b) + size + 1)v;
n->b_size = b->b_size - size - 1;
b->b_size = size;
AddToFreeList(n);
}
sp = &(b->b_size) + b->b_size;
*sp = b->b_size | InUseFlag;
b->b_size |= InUseFlag;
UNLOCK(FreeBlocksLock);
return (Addr(b) + sizeof(YAP_SEG_SIZE));
}
LOCK(HeapTopLock);
UNLOCK(FreeBlocksLock);
2015-09-25 10:57:26 +01:00
b = (BlockHeader *)HeapTop;
HeapTop += size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
LOCK(HeapUsedLock);
HeapUsed += size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
#ifdef YAPOR
if (HeapTop > Addr(LOCAL_GlobalBase) - MinHeapGap)
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "no heap left (AllocHeap)");
#else
if (HeapTop > HeapLim - MinHeapGap) {
HeapTop -= size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
HeapUsed -= size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
if (HeapTop > HeapLim) {
UNLOCK(HeapUsedLock);
UNLOCK(HeapTopLock);
/* we destroyed the stack */
2015-09-25 10:57:26 +01:00
Yap_Error(RESOURCE_ERROR_HEAP, TermNil, "Stack Crashed against Heap...");
return (NULL);
} else {
if (HeapTop + size * sizeof(CELL) + sizeof(YAP_SEG_SIZE) < HeapLim) {
2015-09-25 10:57:26 +01:00
/* small allocations, we can wait */
HeapTop += size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
HeapUsed += size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
UNLOCK(HeapUsedLock);
UNLOCK(HeapTopLock);
Yap_signal(YAP_CDOVF_SIGNAL);
} else {
2015-09-25 10:57:26 +01:00
if (size > GLOBAL_SizeOfOverflow)
GLOBAL_SizeOfOverflow = size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
/* big allocations, the caller must handle the problem */
UNLOCK(HeapUsedLock);
UNLOCK(HeapTopLock);
return (NULL);
}
}
}
#endif /* YAPOR */
2015-09-25 10:57:26 +01:00
*((YAP_SEG_SIZE *)HeapTop) = InUseFlag;
if (HeapUsed > HeapMax)
HeapMax = HeapUsed;
UNLOCK(HeapUsedLock);
b->b_size = size | InUseFlag;
sp = &(b->b_size) + size;
*sp = b->b_size;
UNLOCK(HeapTopLock);
return (Addr(b) + sizeof(YAP_SEG_SIZE));
}
/* If you need to dinamically allocate space from the heap, this is
* the macro you should use */
2015-09-25 10:57:26 +01:00
static void FreeCodeSpace(char *p) {
FreeBlock(((BlockHeader *)(p - sizeof(YAP_SEG_SIZE))));
}
2015-09-25 10:57:26 +01:00
static char *AllocCodeSpace(unsigned long int size) {
if (size < SmallSize + 2 * OpCodeSize + 3 * CellSize)
return (AllocHeap(SmallSize + 2 * OpCodeSize + 3 * CellSize));
return (AllocHeap(size));
}
#if DEBUG_ALLOC
int vsc_mem_trace;
#endif
/* If you need to dinamically allocate space from the heap, this is
* the macro you should use */
2015-09-25 10:57:26 +01:00
void Yap_FreeCodeSpace(char *p) {
#if DEBUG_ALLOC
if (vsc_mem_trace)
2015-09-25 10:57:26 +01:00
printf("-%p\n", p);
#endif
FreeCodeSpace(p);
}
2015-09-25 10:57:26 +01:00
char *Yap_AllocAtomSpace(unsigned long int size) {
char *out = AllocHeap(size);
#if DEBUG_ALLOC
2015-09-25 10:57:26 +01:00
if (vsc_mem_trace)
printf("+%p/%d\n", out, size);
#endif
return out;
}
2015-09-25 10:57:26 +01:00
void Yap_FreeAtomSpace(char *p) {
#if DEBUG_ALLOC
if (vsc_mem_trace)
2015-09-25 10:57:26 +01:00
printf("-%p\n", p);
#endif
FreeCodeSpace(p);
}
2015-09-25 10:57:26 +01:00
char *Yap_AllocCodeSpace(unsigned long int size) {
char *out = AllocCodeSpace(size);
#if DEBUG_ALLOC
2015-09-25 10:57:26 +01:00
if (vsc_mem_trace)
printf("+%p/%d\n", out, size);
#endif
return out;
}
#endif
/************************************************************************/
/* Workspace allocation */
/* */
/* We provide four alternatives for workspace allocation. */
/* - use 'mmap' */
/* - use 'shmat' */
/* - use 'sbrk' and provide a replacement to the 'malloc' library */
/* - use 'malloc' */
/* */
/* In any of the alternatives the interface is through the following */
/* functions: */
/* void *InitWorkSpace(int s) - initial workspace allocation */
/* int ExtendWorkSpace(int s) - extend workspace */
/* int Yap_FreeWorkSpace() - release workspace */
/************************************************************************/
#if defined(_WIN32) || defined(__CYGWIN__)
2011-03-22 09:31:37 +00:00
#undef DEBUG_WIN32_ALLO
#include "windows.h"
static LPVOID brk;
2015-09-25 10:57:26 +01:00
static int ExtendWorkSpace(Int s, int fixed_allocation) {
LPVOID b = brk;
prolog_exec_mode OldPrologMode = LOCAL_PrologMode;
LOCAL_PrologMode = ExtendStackMode;
#if DEBUG_WIN32_ALLOC
2015-09-25 10:57:26 +01:00
fprintf(stderr, "trying: %p (" Int_FORMAT "K) %d\n", b, s / 1024,
fixed_allocation);
#endif
if (fixed_allocation) {
b = VirtualAlloc(b, s, MEM_RESERVE, PAGE_NOACCESS);
} else {
b = VirtualAlloc(NULL, s, MEM_RESERVE, PAGE_NOACCESS);
if (b && b < brk) {
return ExtendWorkSpace(s, fixed_allocation);
}
}
if (!b) {
LOCAL_PrologMode = OldPrologMode;
#if DEBUG_WIN32_ALLOC
{
char msg[256];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
2015-09-25 10:57:26 +01:00
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), msg, 256, NULL);
fprintf(stderr, "NOT OK1: %p %p %s\n", brk, b, msg);
}
#endif
return FALSE;
}
b = VirtualAlloc(b, s, MEM_COMMIT, PAGE_READWRITE);
if (!b) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"VirtualAlloc could not commit %ld bytes", (long int)s);
LOCAL_PrologMode = OldPrologMode;
#if DEBUG_WIN32_ALLOC
2015-09-25 10:57:26 +01:00
fprintf(stderr, "NOT OK2: %p--%p\n", b, brk);
#endif
return FALSE;
}
2015-09-25 10:57:26 +01:00
brk = (LPVOID)((Int)b + s);
#if DEBUG_WIN32_ALLOC
2015-09-25 10:57:26 +01:00
fprintf(stderr, "OK: %p--%p " Int_FORMAT "\n", b, brk, s);
#endif
LOCAL_PrologMode = OldPrologMode;
return TRUE;
}
2015-09-25 10:57:26 +01:00
static MALLOC_T InitWorkSpace(Int s) {
SYSTEM_INFO si;
2010-05-06 15:00:44 +01:00
Int psz;
GetSystemInfo(&si);
2010-05-06 15:00:44 +01:00
psz = Yap_page_size = si.dwPageSize;
brk = (LPVOID)psz;
2015-09-25 10:57:26 +01:00
if (!ExtendWorkSpace(s, 0))
return FALSE;
2015-09-25 10:57:26 +01:00
return (MALLOC_T)brk - s;
}
2015-09-25 10:57:26 +01:00
int Yap_FreeWorkSpace(void) { return TRUE; }
2014-03-07 23:07:46 +00:00
#elif USE_SYSTEM_MMAP
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef MMAP_ADDR
#define USE_FIXED 1
#endif
#ifndef MAP_FIXED
#define MAP_FIXED 1
#endif
static MALLOC_T WorkSpaceTop;
2015-09-25 10:57:26 +01:00
static MALLOC_T InitWorkSpace(Int s) {
MALLOC_T a;
2015-09-25 10:57:26 +01:00
#if !defined(_AIX) && !defined(__APPLE__) && !__hpux
int fd;
#endif
#if defined(_AIX)
2015-09-25 10:57:26 +01:00
a = mmap(0, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_VARIABLE, -1, 0);
#elif __hpux
2015-09-25 10:57:26 +01:00
a = mmap(((void *)MMAP_ADDR), (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (a != (MALLOC_T)MMAP_ADDR) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
"mmap could not map ANON at %p, got %p", (void *)MMAP_ADDR, a);
return (NULL);
}
#elif defined(__APPLE__)
2010-01-25 12:29:27 +00:00
#ifdef MMAP_ADDR
2015-09-25 10:57:26 +01:00
a = mmap(((void *)MMAP_ADDR), (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
if (a != (MALLOC_T)MMAP_ADDR) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
"mmap could not map ANON at %p, got %p", (void *)MMAP_ADDR, a);
return (NULL);
}
2010-01-25 12:29:27 +00:00
#else
2015-09-25 10:57:26 +01:00
a = mmap(NULL, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANON, -1, 0);
2010-01-25 12:29:27 +00:00
#endif
#else
2008-11-26 09:56:18 +00:00
fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd < 0) {
#if HAVE_MKSTEMP
char file[256];
2015-09-25 10:57:26 +01:00
strncpy(file, "/tmp/YAP.TMPXXXXXX", 256);
if (mkstemp(file) == -1) {
#if HAVE_STRERROR
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
"mkstemp could not create temporary file %s (%s)", file,
strerror(errno));
#else
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
"mkstemp could not create temporary file %s", file);
#endif
return NULL;
}
#else
#if HAVE_TMPNAM
char *file = tmpnam(NULL);
#else
char file[YAP_FILENAME_MAX];
2015-09-25 10:57:26 +01:00
strcpy(file, "/tmp/mapfile");
itos(getpid(), &file[12]);
#endif /* HAVE_TMPNAM */
#endif /* HAVE_MKSTEMP */
2015-09-25 10:57:26 +01:00
fd = open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd < 0) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "mmap could not open %s", file);
return NULL;
}
if (lseek(fd, s, SEEK_SET) < 0) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
"mmap could not lseek in mmapped file %s", file);
close(fd);
return FALSE;
}
if (write(fd, "", 1) < 0) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
"mmap could not write in mmapped file %s", file);
close(fd);
return NULL;
}
if (unlink(file) < 0) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
"mmap could not unlink mmapped file %s", file);
close(fd);
return NULL;
}
}
#if USE_FIXED
2015-09-25 10:57:26 +01:00
a = mmap(((void *)MMAP_ADDR), (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_FIXED, fd, 0);
if (a != (MALLOC_T)MMAP_ADDR) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "mmap could not map at %p, got %p",
(void *)MMAP_ADDR, a);
return NULL;
}
#else
2015-09-25 10:57:26 +01:00
a = mmap(0, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd,
0);
if ((CELL)a & YAP_PROTECTED_MASK) {
close(fd);
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
"mmapped address %p collides with YAP tags", a);
return NULL;
}
if (close(fd) == -1) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "while closing mmaped file");
return NULL;
}
#endif
#endif
if
#ifdef MMAP_FAILED
2015-09-25 10:57:26 +01:00
(a == (MALLOC_T)MMAP_FAILED)
#else
2015-09-25 10:57:26 +01:00
(a == (MALLOC_T)-1)
#endif
2015-09-25 10:57:26 +01:00
{
Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "mmap cannot allocate memory ***");
return (NULL);
}
WorkSpaceTop = (char *)a + s;
return (void *)a;
}
#ifndef YAPOR
2015-09-25 10:57:26 +01:00
static MALLOC_T mmap_extension(Int s, MALLOC_T base, int fixed_allocation) {
MALLOC_T a;
2009-04-29 14:22:20 +01:00
#if !defined(_AIX) && !defined(__hpux) && !defined(__APPLE__)
2015-09-25 10:57:26 +01:00
int fd;
#endif
#if defined(_AIX) || defined(__hpux)
2015-09-25 10:57:26 +01:00
a = mmap(base, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#elif defined(__APPLE__)
2015-09-25 10:57:26 +01:00
a = mmap(base, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANON | fixed_allocation, -1, 0);
#else
2015-09-25 10:57:26 +01:00
fd = open("/dev/zero", O_RDWR);
if (fd < 0) {
#if HAVE_MKSTEMP
2015-09-25 10:57:26 +01:00
char file[256];
strncpy(file, "/tmp/YAP.TMPXXXXXX", 256);
if (mkstemp(file) == -1) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
#if HAVE_STRERROR
2015-09-25 10:57:26 +01:00
snprintf5(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
"mkstemp could not create temporary file %s (%s)", file,
strerror(errno));
#else
2015-09-25 10:57:26 +01:00
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
"mkstemp could not create temporary file %s", file);
#endif /* HAVE_STRERROR */
2015-09-25 10:57:26 +01:00
return (MALLOC_T)-1;
}
#else
#if HAVE_TMPNAM
2015-09-25 10:57:26 +01:00
char *file = tmpnam(NULL);
#else
2015-09-25 10:57:26 +01:00
char file[YAP_FILENAME_MAX];
strcpy(file, "/tmp/mapfile");
itos(getpid(), &file[12]);
#endif /* HAVE_TMPNAM */
#endif /* HAVE_MKSTEMP */
2015-09-25 10:57:26 +01:00
fd = open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd < 0) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"mmap could not open %s", file);
2009-04-29 14:22:20 +01:00
return (MALLOC_T)-1;
}
if (lseek(fd, s, SEEK_SET) < 0) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"mmap could not lseek in mmapped file %s", file);
close(fd);
2009-04-29 14:22:20 +01:00
return (MALLOC_T)-1;
}
if (write(fd, "", 1) < 0) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"mmap could not write in mmapped file %s", file);
close(fd);
2009-04-29 14:22:20 +01:00
return (MALLOC_T)-1;
}
if (unlink(file) < 0) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"mmap could not unlink mmapped file %s", file);
close(fd);
2009-04-29 14:22:20 +01:00
return (MALLOC_T)-1;
}
}
2015-09-25 10:57:26 +01:00
a = mmap(
base, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE
#if !defined(__linux)
2015-09-25 10:57:26 +01:00
/* use MAP_FIXED, otherwise God knows where you will be placed */
2016-08-01 23:48:25 +01:00
| fixed_allocation
#endif
2015-09-25 10:57:26 +01:00
,
fd, 0);
if (close(fd) == -1) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
#if HAVE_STRERROR
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"mmap could not close file (%s) ]\n", strerror(errno));
#else
snprintf3(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"mmap could not close file ]\n");
#endif
2009-04-29 14:22:20 +01:00
return (MALLOC_T)-1;
}
#endif
2009-04-29 14:22:20 +01:00
return a;
}
#endif /* !YAPOR */
2012-06-01 16:39:06 +01:00
/*
2015-09-25 10:57:26 +01:00
s= how much memory we need;
2012-06-01 16:39:06 +01:00
fixed_alloc = do we need to contiguously extend stack
returns TRUE or FALSE
updates WorkSpaceTop
*/
2015-09-25 10:57:26 +01:00
static int ExtendWorkSpace(Int s, int fixed_allocation) {
2009-04-29 14:22:20 +01:00
#ifdef YAPOR
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
"cannot extend stacks (ExtendWorkSpace)");
return (FALSE);
2009-04-29 14:22:20 +01:00
#else
MALLOC_T a;
prolog_exec_mode OldPrologMode = LOCAL_PrologMode;
2009-04-29 14:22:20 +01:00
MALLOC_T base = WorkSpaceTop;
if (fixed_allocation == MAP_FIXED)
base = WorkSpaceTop;
else
base = 0L;
LOCAL_PrologMode = ExtendStackMode;
2009-04-29 14:22:20 +01:00
a = mmap_extension(s, base, fixed_allocation);
LOCAL_PrologMode = OldPrologMode;
2015-09-25 10:57:26 +01:00
if (a == (MALLOC_T)-1) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
#if HAVE_STRERROR
snprintf5(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"could not allocate %d bytes (%s)", (int)s, strerror(errno));
#else
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"could not allocate %d bytes", (int)s);
#endif
return FALSE;
}
if (fixed_allocation) {
if (a != WorkSpaceTop) {
munmap((void *)a, (size_t)s);
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf5(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"mmap could not grow memory at %p, got %p", WorkSpaceTop, a);
LOCAL_PrologMode = OldPrologMode;
return FALSE;
}
} else if (a < WorkSpaceTop) {
/* try again */
int res = ExtendWorkSpace(s, fixed_allocation);
/* release memory back to system */
munmap(a, s);
return res;
}
2015-09-25 10:57:26 +01:00
WorkSpaceTop = (char *)a + s;
LOCAL_PrologMode = OldPrologMode;
return TRUE;
#endif /* YAPOR */
}
2015-09-25 10:57:26 +01:00
int Yap_FreeWorkSpace(void) { return 1; }
2014-03-07 23:07:46 +00:00
#elif USE_SYSTEM_SHM
#if HAVE_SYS_SHM_H
#include <sys/shm.h>
#endif
#ifndef MMAP_ADDR
#define MMAP_ADDR 0x0L
#endif
static MALLOC_T WorkSpaceTop;
2015-09-25 10:57:26 +01:00
static MALLOC_T InitWorkSpace(Int s) {
MALLOC_T ptr;
int shm_id;
/* mapping heap area */
2015-09-25 10:57:26 +01:00
if ((shm_id = shmget(IPC_PRIVATE, (size_t)s, SHM_R | SHM_W)) == -1) {
Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "could not shmget %d bytes", s);
return (NULL);
}
if ((ptr = (MALLOC_T)shmat(shm_id, (void *)MMAP_ADDR, 0)) == (MALLOC_T)-1) {
Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "could not shmat at %p", MMAP_ADDR);
return (NULL);
}
if (shmctl(shm_id, IPC_RMID, 0) != 0) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "could not remove shm segment",
shm_id);
return (NULL);
}
2015-09-25 10:57:26 +01:00
WorkSpaceTop = (char *)ptr + s;
return (ptr);
}
2015-09-25 10:57:26 +01:00
static int ExtendWorkSpace(Int s) {
MALLOC_T ptr;
int shm_id;
prolog_exec_mode OldPrologMode = LOCAL_PrologMode;
LOCAL_PrologMode = ExtendStackMode;
/* mapping heap area */
2015-09-25 10:57:26 +01:00
if ((shm_id = shmget(IPC_PRIVATE, (size_t)s, SHM_R | SHM_W)) == -1) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"could not shmget %d bytes", s);
LOCAL_PrologMode = OldPrologMode;
2015-09-25 10:57:26 +01:00
return (FALSE);
}
if ((ptr = (MALLOC_T)shmat(shm_id, WorkSpaceTop, 0)) == (MALLOC_T)-1) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
2015-09-25 10:57:26 +01:00
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE, "could not shmat at %p",
MMAP_ADDR);
LOCAL_PrologMode = OldPrologMode;
2015-09-25 10:57:26 +01:00
return (FALSE);
}
if (shmctl(shm_id, IPC_RMID, 0) != 0) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"could not remove shm segment", shm_id);
LOCAL_PrologMode = OldPrologMode;
2015-09-25 10:57:26 +01:00
return (FALSE);
}
2015-09-25 10:57:26 +01:00
WorkSpaceTop = (char *)ptr + s;
LOCAL_PrologMode = OldPrologMode;
2015-09-25 10:57:26 +01:00
return (TRUE);
}
2015-09-25 10:57:26 +01:00
int Yap_FreeWorkSpace(void) { return TRUE; }
#elif USE_SBRK
/***********************************************************************\
* Worspace allocation based on 'sbrk' *
* We have to provide a replacement for the 'malloc' functions. *
* The situation is further complicated by the need to provide *
* temporary 'malloc' space when restoring a previously saved state. *
\***********************************************************************/
#ifdef _AIX
2013-04-25 23:15:04 +01:00
char *sbrk(int);
#endif
2015-09-25 10:57:26 +01:00
int in_limbo; /* non-zero when restoring a saved state */
#ifndef LIMBO_SIZE
2015-09-25 10:57:26 +01:00
#define LIMBO_SIZE 32 * K
#endif
2015-09-25 10:57:26 +01:00
static char limbo_space[LIMBO_SIZE]; /* temporary malloc space */
static char *limbo_p = limbo_space, *limbo_pp = 0;
2015-09-25 10:57:26 +01:00
static MALLOC_T InitWorkSpace(Int s) {
MALLOC_T ptr = (MALLOC_T)sbrk(s);
2015-09-25 10:57:26 +01:00
if (ptr == ((MALLOC_T)-1)) {
Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "could not allocate %d bytes", s);
return (NULL);
}
2015-09-25 10:57:26 +01:00
return (ptr);
}
2015-09-25 10:57:26 +01:00
static int ExtendWorkSpace(Int s) {
MALLOC_T ptr = (MALLOC_T)sbrk(s);
prolog_exec_mode OldPrologMode = LOCAL_PrologMode;
LOCAL_PrologMode = ExtendStackMode;
2015-09-25 10:57:26 +01:00
if (ptr == ((MALLOC_T)-1)) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"could not expand stacks over %d bytes", s);
LOCAL_PrologMode = OldPrologMode;
2015-09-25 10:57:26 +01:00
return (FALSE);
}
LOCAL_PrologMode = OldPrologMode;
return TRUE;
}
2015-09-25 10:57:26 +01:00
int Yap_FreeWorkSpace(void) { return TRUE; }
MALLOC_T
2015-09-25 10:57:26 +01:00
malloc(size_t size) {
if (in_limbo) {
limbo_pp = limbo_p;
limbo_p += (size + 7) & 0xffff8;
if (limbo_p >= &limbo_space[LIMBO_SIZE])
2015-09-25 10:57:26 +01:00
return (NULL);
return (limbo_pp);
2015-09-25 10:57:26 +01:00
} else {
CODEADDR codep = (CODEADDR)AllocCodeSpace(size + 2 * sizeof(void *));
if (codep == NIL)
2015-09-25 10:57:26 +01:00
return (NIL);
else
2015-09-25 10:57:26 +01:00
return (codep + 2 * sizeof(void *));
}
}
2015-09-25 10:57:26 +01:00
void free(MALLOC_T ptr) {
BlockHeader *b = (BlockHeader *)(((char *)ptr) - 2 * sizeof(void *) -
sizeof(YAP_SEG_SIZE));
if (ptr == limbo_pp) {
limbo_p = limbo_pp;
return;
}
if (!ptr)
return;
2015-09-25 10:57:26 +01:00
if ((char *)ptr < Yap_HeapBase || (char *)ptr > HeapTop)
return;
if (!(b->b_size & InUseFlag))
return;
2015-09-25 10:57:26 +01:00
FreeCodeSpace((char *)ptr - 2 * sizeof(void *));
}
MALLOC_T
2015-09-25 10:57:26 +01:00
XX realloc(MALLOC_T ptr, size_t size) {
MALLOC_T new = malloc(size);
if (ptr)
memcpy(new, ptr, size);
free(ptr);
return (new);
}
MALLOC_T
2015-09-25 10:57:26 +01:00
calloc(size_t n, size_t e) {
unsigned k = n * e;
MALLOC_T p = malloc(k);
memset(p, 0, k);
return (p);
}
#ifdef M_MXFAST
2015-09-25 10:57:26 +01:00
int mallopt(cmd, value) { return (value); }
static struct mallinfo xmall;
2015-09-25 10:57:26 +01:00
struct mallinfo mallinfo(void) {
return (xmall);
}
#endif
#else
/* use malloc to initiliase memory */
/* user should ask for a lot of memory first */
#ifdef __linux
2015-09-25 10:57:26 +01:00
#define MAX_SPACE 420 * 1024 * 1024
#else
2015-09-25 10:57:26 +01:00
#define MAX_SPACE 128 * 1024 * 1024
#endif
static int total_space;
2015-09-25 10:57:26 +01:00
static MALLOC_T InitWorkSpace(Int s) {
MALLOC_T ptr;
#ifdef M_MMAP_MAX
mallopt(M_MMAP_MAX, 0);
#endif
2015-09-25 10:57:26 +01:00
ptr = (MALLOC_T)calloc(MAX_SPACE, 1);
total_space = s;
if (ptr == NULL) {
2015-09-25 10:57:26 +01:00
Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "could not allocate %d bytes", s);
return (NULL);
}
2015-09-25 10:57:26 +01:00
return (ptr);
}
2015-09-25 10:57:26 +01:00
static int ExtendWorkSpace(Int s) {
MALLOC_T ptr;
prolog_exec_mode OldPrologMode = LOCAL_PrologMode;
LOCAL_PrologMode = ExtendStackMode;
total_space += s;
2015-09-25 10:57:26 +01:00
if (total_space < MAX_SPACE)
return TRUE;
ptr = (MALLOC_T)realloc((void *)Yap_HeapBase, total_space);
if (ptr == NULL) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"could not allocate %d bytes", s);
LOCAL_PrologMode = OldPrologMode;
return FALSE;
}
if (ptr != (MALLOC_T)Yap_HeapBase) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"could not expand contiguous stacks %d bytes", s);
LOCAL_PrologMode = OldPrologMode;
return FALSE;
}
2016-07-31 05:07:06 +01:00
#if MBIT
if ((CELL)ptr & MBIT) {
LOCAL_ErrorMessage = LOCAL_ErrorSay;
snprintf5(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
2015-09-25 10:57:26 +01:00
"memory at %p conflicts with MBIT %lx", ptr, (unsigned long)MBIT);
LOCAL_PrologMode = OldPrologMode;
return FALSE;
}
2016-07-31 05:07:06 +01:00
#endif
LOCAL_PrologMode = OldPrologMode;
return TRUE;
}
2015-09-25 10:57:26 +01:00
int Yap_FreeWorkSpace(void) { return TRUE; }
#endif
2015-09-25 10:57:26 +01:00
static void InitHeap(void *heap_addr) {
/* allocate space */
Yap_HeapBase = heap_addr;
/* reserve space for specially allocated functors and atoms so that
their values can be known statically */
HeapTop = Yap_HeapBase + AdjustSize(sizeof(all_heap_codes));
Yap_HoleSize = 0;
#if USE_DL_MALLOC
Yap_initdlmalloc();
#else
2015-09-25 10:57:26 +01:00
HeapMax = HeapUsed = HeapTop - Yap_HeapBase;
/* notice that this forces odd addresses */
2015-09-25 10:57:26 +01:00
*((YAP_SEG_SIZE *)HeapTop) = InUseFlag;
HeapTop = HeapTop + sizeof(YAP_SEG_SIZE);
2015-09-25 10:57:26 +01:00
*((YAP_SEG_SIZE *)HeapTop) = InUseFlag;
#endif
FreeBlocks = NIL;
}
2015-09-25 10:57:26 +01:00
void Yap_InitHeap(void *heap_addr) { InitHeap(heap_addr); }
2015-09-25 10:57:26 +01:00
void Yap_InitMemory(UInt Trail, UInt Heap, UInt Stack) {
UInt pm, sa, ta;
void *addr;
#if defined(_WIN32) || defined(__CYGWIN__)
2015-09-25 10:57:26 +01:00
Stack = ((Stack + (YAP_ALLOC_SIZE - 1)) / YAP_ALLOC_SIZE) * YAP_ALLOC_SIZE;
Heap = ((Heap + (YAP_ALLOC_SIZE - 1)) / YAP_ALLOC_SIZE) * YAP_ALLOC_SIZE;
Trail = ((Trail + (YAP_ALLOC_SIZE - 1)) / YAP_ALLOC_SIZE) * YAP_ALLOC_SIZE;
#endif
2015-09-25 10:57:26 +01:00
pm = (Trail + Heap + Stack); /* memory to be
* requested */
sa = Stack; /* stack area size */
ta = Trail; /* trail area size */
#if RANDOMIZE_START_ADDRESS
srand(time(NULL));
2015-09-25 10:57:26 +01:00
UInt x = (rand() % 100) * YAP_ALLOC_SIZE;
pm += x;
#endif
addr = InitWorkSpace(pm);
#if RANDOMIZE_START_ADDRESS
2015-09-25 10:57:26 +01:00
addr = (char *)addr + x;
pm -= x;
#endif
InitHeap(addr);
LOCAL_TrailTop = Yap_HeapBase + pm;
LOCAL_LocalBase = LOCAL_TrailTop - ta;
LOCAL_TrailBase = LOCAL_LocalBase + sizeof(CELL);
LOCAL_GlobalBase = LOCAL_LocalBase - sa;
2015-09-25 10:57:26 +01:00
HeapLim = LOCAL_GlobalBase; /* avoid confusions while
* * restoring */
#if !USE_DL_MALLOC
AuxTop = (ADDR)(AuxSp = (CELL *)LOCAL_GlobalBase);
#endif
2013-11-16 00:27:02 +00:00
#if DEBUG
2015-09-25 10:57:26 +01:00
#if SIZEOF_INT_P != SIZEOF_INT
2011-06-20 14:49:24 +01:00
if (Yap_output_msg) {
2015-09-25 10:57:26 +01:00
fprintf(stderr,
"HeapBase = %p GlobalBase = %p\n LocalBase = %p TrailTop = %p\n",
Yap_HeapBase, LOCAL_GlobalBase, LOCAL_LocalBase, LOCAL_TrailTop);
#else
2011-06-20 14:49:24 +01:00
if (Yap_output_msg) {
2015-09-25 10:57:26 +01:00
fprintf(stderr,
"HeapBase = %x GlobalBase = %x\n LocalBase = %x TrailTop = %x\n",
(UInt)Yap_HeapBase, (UInt)LOCAL_GlobalBase, (UInt)LOCAL_LocalBase,
(UInt)LOCAL_TrailTop);
#endif
2015-09-25 10:57:26 +01:00
fprintf(stderr, "Heap+Aux: " UInt_FORMAT "\tLocal+Global: " UInt_FORMAT
"\tTrail: " UInt_FORMAT "\n",
pm - sa - ta, sa, ta);
}
#endif /* DEBUG */
}
2015-09-25 10:57:26 +01:00
void Yap_InitExStacks(int wid, int Trail, int Stack) {
#if USE_DL_MALLOC
2012-12-13 18:12:50 +00:00
REMOTE_ScratchPad(wid).ptr = NULL;
REMOTE_ScratchPad(wid).sz = REMOTE_ScratchPad(wid).msz = SCRATCH_START_SIZE;
AuxSp = NULL;
#endif
}
#if defined(_WIN32) || defined(__CYGWIN__)
#define WorkSpaceTop brk
#define MAP_FIXED 1
#endif
#if !USE_DL_MALLOC
/* dead code */
2015-09-25 10:57:26 +01:00
void Yap_add_memory_hole(ADDR Start, ADDR End) { Yap_HoleSize += Start - End; }
#endif
2015-09-25 10:57:26 +01:00
int Yap_ExtendWorkSpace(Int s) {
2014-03-07 23:07:46 +00:00
#if USE_SYSTEM_MMAP
return ExtendWorkSpace(s, MAP_FIXED);
#elif defined(_WIN32)
return ExtendWorkSpace(s, MAP_FIXED);
#else
return ExtendWorkSpace(s);
#endif
}
2015-09-25 10:57:26 +01:00
size_t Yap_ExtendWorkSpaceThroughHole(size_t s) {
2014-03-07 23:07:46 +00:00
#if USE_SYSTEM_MMAP || defined(_WIN32) || defined(__CYGWIN__)
MALLOC_T WorkSpaceTop0 = WorkSpaceTop;
2015-09-25 10:57:26 +01:00
#if SIZEOF_INT_P == 4
while (WorkSpaceTop < (MALLOC_T)0xc0000000L) {
/* progress 1 MB */
2015-09-25 10:57:26 +01:00
WorkSpaceTop += 512 * 1024;
if (ExtendWorkSpace(s, MAP_FIXED)) {
2015-09-25 10:57:26 +01:00
Yap_add_memory_hole((ADDR)WorkSpaceTop0, (ADDR)WorkSpaceTop - s);
LOCAL_ErrorMessage = NULL;
2015-09-25 10:57:26 +01:00
return WorkSpaceTop - WorkSpaceTop0;
}
#if defined(_WIN32)
/* 487 happens when you step over someone else's memory */
if (GetLastError() != 487) {
WorkSpaceTop = WorkSpaceTop0;
2014-09-10 05:50:43 +01:00
return 0;
}
#endif
2015-09-25 10:57:26 +01:00
#elif SIZEOF_INT_P == 8
{
2015-09-25 10:57:26 +01:00
int n = 1024 * 1024;
2011-10-21 22:05:28 +01:00
while (n--) {
/* progress 1 MB */
2015-09-25 10:57:26 +01:00
WorkSpaceTop += 512 * 1024;
if (ExtendWorkSpace(s, MAP_FIXED)) {
2015-09-25 10:57:26 +01:00
Yap_add_memory_hole((ADDR)WorkSpaceTop0, (ADDR)WorkSpaceTop - s);
LOCAL_ErrorMessage = NULL;
return WorkSpaceTop - WorkSpaceTop0;
}
#if defined(_WIN32)
/* 487 happens when you step over someone else's memory */
if (GetLastError() != 487) {
2015-09-25 10:57:26 +01:00
WorkSpaceTop = WorkSpaceTop0;
return 0;
}
#endif
}
#endif
}
WorkSpaceTop = WorkSpaceTop0;
#endif
2014-09-10 05:50:43 +01:00
return 0;
}
2015-09-25 10:57:26 +01:00
void Yap_AllocHole(UInt actual_request, UInt total_size) {
#if (USE_SYSTEM_MMAP || defined(_WIN32) || defined(__CYGWIN__)) && \
!USE_DL_MALLOC
/* where we were when the hole was created,
also where is the hole store */
2015-09-25 10:57:26 +01:00
ADDR WorkSpaceTop0 = WorkSpaceTop - total_size;
BlockHeader *newb = (BlockHeader *)HeapTop;
2015-09-25 10:57:26 +01:00
BlockHeader *endb = (BlockHeader *)(WorkSpaceTop0 - sizeof(YAP_SEG_SIZE));
YAP_SEG_SIZE bsiz = (WorkSpaceTop0 - HeapTop) / sizeof(CELL) -
2 * sizeof(YAP_SEG_SIZE) / sizeof(CELL);
/* push HeapTop to after hole */
2015-09-25 10:57:26 +01:00
HeapTop = WorkSpaceTop - (actual_request - sizeof(YAP_SEG_SIZE));
((YAP_SEG_SIZE *)HeapTop)[0] = InUseFlag;
/* now simulate a block */
2015-09-25 10:57:26 +01:00
((YAP_SEG_SIZE *)HeapTop)[-1] = endb->b_size =
(HeapTop - WorkSpaceTop0) / sizeof(YAP_SEG_SIZE) | InUseFlag;
newb->b_size = bsiz;
AddToFreeList(newb);
#endif
}
#endif /* USE_SYSTEM_MALLOC */