YAP 7.1.0
alloc.c
1/*************************************************************************
2 * *
3 * YAP Prolog *
4 * *
5 * Yap Prolog was developed at NCCUP - Universidade do Porto *
6 * *
7 * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8 * *
9 **************************************************************************
10 * *
11 * File: alloc.c * Last
12 *rev: * mods:
13 ** comments: allocating space *
14 * version:$Id: alloc.c,v 1.95 2008-05-10 23:24:11 vsc Exp $ *
15 *************************************************************************/
16#ifdef SCCS
17static char SccsId[] = "%W% %G%";
18
19#endif
20
21#include "Yap.h"
22
23#include "YapHeap.h"
24#include "Yatom.h"
25#include "alloc.h"
26#include "yapio.h"
27#if HAVE_STRING_H
28#include <string.h>
29#endif
30#if HAVE_MALLOC_H
31#include <malloc.h>
32#endif
33#if USE_DL_MALLOC
34#include "dlmalloc.h"
35#endif
36#if HAVE_MEMORY_H
37#include <memory.h>
38#endif
39#if HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42#if HAVE_FCNTL_H
43#include <fcntl.h>
44#endif
45#if HAVE_SYS_TIME_H
46#include <sys/time.h>
47#endif
48#if HAVE_SYS_RESOURCE_H
49#include <sys/resource.h>
50#endif
51#if HAVE_SYS_STAT_H
52#include <sys/stat.h>
53#endif
54#include <stdio.h>
55#include <stdlib.h>
56
57#if __simplescalar__
58#ifdef USE_SYSTEM_MMAP
59#undef USE_SYSTEM_MMAP
60#endif
61#ifdef USE_SBRK
62#undef USE_SBRK
63#endif
64#endif
65//#define DEBUG_MALLOC 1
66//#define DEBUG_D 1
67
68/************************************************************************/
69/* Yap workspace management */
70
71#define MASK 0x968e00
72#if USE_SYSTEM_MALLOC
73#if 1
74
75#undef free
76#undef malloc
77#undef realloc
78
79int write_malloc = 0;
80
81void *my_malloc(size_t sz) {
82 void *p;
83
84 p = calloc(sz,1);
85 // Yap_DebugPuts(stderr,"gof\n");
86#ifdef DEBUG_MALLOC
87 if (DEBUG_DIRECT || Yap_do_low_level_trace) {
88#if __ANDROID__
89 // __android_log_print(ANDROID_LOG_ERROR, "YAPDroid ", "+ %d %p", write_malloc,p);
90#else
91 fprintf(stderr, "+s %p\n @%p %ld\n", p, TR, LCL0 - (CELL *)LCL0);
92#endif
93 }
94#endif
95 return p;
96}
97
98void *my_realloc(void *ptr, size_t sz) {
99 void *p;
100
101 p = realloc(ptr, sz);
102 #ifdef DEBUG_MALLOC
103 if (DEBUG_DIRECT ||Yap_do_low_level_trace)
104 fprintf(stderr, "+ %p -> %p : " Sizet_F "\n", ptr, p, sz);
105 #endif
106 // Yap_DebugPuts(stderr,"gof\n");
107// if (sz > 500 && write_malloc++ > 0)
108// __android_log_print(ANDROID_LOG_ERROR, "YAPDroid ", "* %d %p",
109// write_malloc, p);
110 return p;
111}
112
113void my_free(void *p) {
114 // printf("f %p\n",p);
115#ifdef DEBUG_MALLOC
116if (DEBUG_DIRECT ||Yap_do_low_level_trace)
117 fprintf(stderr, "- %p\n @%p %ld\n", p, TR, (long int)(LCL0 - (CELL *)B) );
118#endif
119 free(p);
120 // Yap_DebugPuts(stderr,"gof\n");
121}
122
123#endif
124
125#else // USE_SYSTEM_MALLOC
126
127#define my_malloc(sz) Yap_dlmalloc(sz)
128#define my_realloc(ptr, sz) Yap_dlrealloc(ptr, sz)
129#define my_free(sz) Yap_dlfree(sz)
130
131static char *my_reallocl(char *ptr, UInt sz, UInt osz, int safe) {
132 char *nptr;
133
134restart:
135 /* simple case */
136 if (ptr < Yap_HeapBase || ptr > HeapTop) {
137 /* we have enough room */
138 nptr = Yap_dlmalloc(sz);
139 if (nptr) {
140 memmove(nptr, ptr, osz);
141 free(ptr);
142 }
143 } else {
144 nptr = Yap_dlrealloc(ptr, sz);
145 }
146 if (nptr) {
147 return nptr;
148 }
149 /* we do not have enough room */
150 if (safe) {
151 if (Yap_growheap(FALSE, sz, NULL)) {
152 /* now, we have room */
153 goto restart;
154 }
155 }
156 /* no room in Heap, gosh */
157 if (ptr < Yap_HeapBase || ptr > HeapTop) {
158 /* try expanding outside the heap */
159 nptr = realloc(ptr, sz);
160 if (nptr) {
161 memmove(nptr, ptr, osz);
162 }
163 } else {
164 /* try calling the outside world for help */
165 nptr = malloc(sz);
166 if (!nptr)
167 return NULL;
168 memmove(nptr, ptr, osz);
169 Yap_dlfree(ptr);
170 }
171 /* did we suceed? at this point we could not care less */
172 return nptr;
173}
174#endif
175
176#if USE_SYSTEM_MALLOC || USE_DL_MALLOC
177
178long long unsigned int mallocs, reallocs, frees;
179long long unsigned int tmalloc;
180
181#undef INSTRUMENT_MALLOC
182
183static inline char *call_malloc(size_t size) {
184 CACHE_REGS
185 char *out;
186#if USE_DL_MALLOC
187 LOCK(DLMallocLock);
188#endif
189#if INSTRUMENT_MALLOC
190 mallocs++;
191 tmalloc += size;
192 size += sizeof(CELL);
193#endif
194 LOCAL_PrologMode |= MallocMode;
195 out = (char *)my_malloc(size);
196#if INSTRUMENT_MALLOC
197 *(CELL *)out = size - sizeof(CELL);
198 out += sizeof(CELL);
199#endif
200 LOCAL_PrologMode &= ~MallocMode;
201#if USE_DL_MALLOC
202 UNLOCK(DLMallocLock);
203#endif
204 return out;
205}
206
207void *Yap_AllocCodeSpace(size_t size) {
208 size = AdjustSize(size);
209 return call_malloc(size);
210}
211
212static inline char *call_realloc(char *p, size_t size) {
213 CACHE_REGS
214 char *out;
215#if USE_DL_MALLOC
216 LOCK(DLMallocLock);
217#endif
218#if INSTRUMENT_MALLOC
219 reallocs++;
220 tmalloc += size;
221 size += sizeof(CELL);
222 p -= sizeof(CELL);
223 tmalloc -= *(CELL *)p;
224#endif
225 LOCAL_PrologMode |= MallocMode;
226 out = (char *)my_realloc(p, size);
227#if INSTRUMENT_MALLOC
228 *(CELL *)out = size - sizeof(CELL);
229 out += sizeof(CELL);
230#endif
231 LOCAL_PrologMode &= ~MallocMode;
232#if USE_DL_MALLOC
233 UNLOCK(DLMallocLock);
234#endif
235 return out;
236}
237
238void *Yap_ReallocCodeSpace(void *p, size_t size) {
239 size = AdjustSize(size);
240 return call_realloc(p, size);
241}
242
243void Yap_FreeCodeSpace(void *p) {
244 CACHE_REGS
245#if USE_DL_MALLOC
246 LOCK(DLMallocLock);
247#endif
248 LOCAL_PrologMode |= MallocMode;
249#if INSTRUMENT_MALLOC
250 p -= sizeof(CELL);
251 tmalloc -= *(CELL *)p;
252 frees++;
253#endif
254 my_free(p);
255 LOCAL_PrologMode &= ~MallocMode;
256#if USE_DL_MALLOC
257 UNLOCK(DLMallocLock);
258#endif
259}
260
261void *Yap_AllocAtomSpace(size_t size) {
262 size = AdjustSize(size);
263 return call_malloc(size);
264}
265
266void Yap_FreeAtomSpace(void *p) {
267 CACHE_REGS
268#if USE_DL_MALLOC
269 LOCK(DLMallocLock);
270#endif
271 LOCAL_PrologMode |= MallocMode;
272#if INSTRUMENT_MALLOC
273 p -= sizeof(CELL);
274 tmalloc -= *(CELL *)p;
275 frees++;
276#endif
277 my_free(p);
278 LOCAL_PrologMode &= ~MallocMode;
279#if USE_DL_MALLOC
280 UNLOCK(DLMallocLock);
281#endif
282}
283
284#endif
285
286/* If you need to dinamically allocate space from the heap, this is
287 * the macro you should use */
288ADDR Yap_InitPreAllocCodeSpace(int wid) {
289 CACHE_REGS
290 char *ptr;
291 UInt sz = REMOTE_ScratchPad(wid).msz;
292
293 if (REMOTE_ScratchPad(wid).ptr == NULL) {
294#if USE_DL_MALLOC
295 LOCK(DLMallocLock);
296#endif
297 REMOTE_PrologMode(wid) |= MallocMode;
298#if INSTRUMENT_MALLOC
299 mallocs++;
300 tmalloc += sz;
301 sz += sizeof(CELL);
302#endif
303 while (!(ptr =
304#ifdef YAPOR_COPY
305 malloc(sz)
306#else
307 my_malloc(sz)
308#endif
309 )) {
310 REMOTE_PrologMode(wid) &= ~MallocMode;
311#if USE_DL_MALLOC
312 UNLOCK(DLMallocLock);
313#endif
314 if (!Yap_growheap(FALSE, LOCAL_Error_Size, NULL)) {
315 Yap_Error(RESOURCE_ERROR_HEAP, TermNil, LOCAL_ErrorMessage);
316 return (NULL);
317 }
318#if INSTRUMENT_MALLOC
319 sz -= sizeof(CELL);
320 *(CELL *)ptr = sz;
321 ptr += sizeof(CELL);
322#endif
323#if USE_DL_MALLOC
324 LOCK(DLMallocLock);
325#endif
326 REMOTE_PrologMode(wid) |= MallocMode;
327 }
328 REMOTE_PrologMode(wid) &= ~MallocMode;
329#if USE_DL_MALLOC
330 UNLOCK(DLMallocLock);
331#endif
332 REMOTE_ScratchPad(wid).ptr = ptr;
333 } else {
334 ptr = REMOTE_ScratchPad(wid).ptr;
335 }
336 AuxBase = (ADDR)(ptr);
337 AuxSp = (CELL *)(AuxTop = AuxBase + REMOTE_ScratchPad(wid).sz);
338 return ptr;
339}
340
341ADDR Yap_ExpandPreAllocCodeSpace(UInt sz0, void *cip, int safe) {
342 CACHE_REGS
343 char *ptr;
344 UInt sz;
345 if (sz0 < SCRATCH_INC_SIZE)
346 sz0 = SCRATCH_INC_SIZE;
347 if (sz0 < LOCAL_ScratchPad.sz)
348 sz = LOCAL_ScratchPad.sz + sz0;
349 else
350 sz = sz0;
351 sz = AdjustLargePageSize(sz + sz / 4);
352
353#if USE_DL_MALLOC
354 LOCK(DLMallocLock);
355#endif
356 LOCAL_PrologMode |= MallocMode;
357#if INSTRUMENT_MALLOC
358 reallocs++;
359 tmalloc -= LOCAL_ScratchPad.sz;
360 tmalloc += sz;
361#endif
362 if (!(ptr = my_realloc(LOCAL_ScratchPad.ptr, sz))) {
363 LOCAL_PrologMode &= ~MallocMode;
364#if USE_DL_MALLOC
365 UNLOCK(DLMallocLock);
366#endif
367 return NULL;
368 }
369 LOCAL_PrologMode &= ~MallocMode;
370#if USE_DL_MALLOC
371 UNLOCK(DLMallocLock);
372#endif
373 LOCAL_ScratchPad.sz = LOCAL_ScratchPad.msz = sz;
374 LOCAL_ScratchPad.ptr = ptr;
375 AuxBase = ptr;
376 AuxSp = (CELL *)(AuxTop = ptr + sz);
377 return ptr;
378}
379
380#if USE_SYSTEM_MALLOC
381
382struct various_codes *Yap_heap_regs;
383
384
385// get an approximation to total memory data-base size.
386 size_t Yap_HeapUsed(void)
387{
388 #if HAVE_MALLINFO
389 struct mallinfo mi = mallinfo();
390 return mi.uordblks - (LOCAL_TrailTop-LOCAL_GlobalBase);
391#else
392 return Yap_ClauseSpace+Yap_IndexSpace_Tree+Yap_LUClauseSpace+Yap_LUIndexSpace_CP;
393#endif
394}
395
396static void InitExStacks(int wid, size_t Trail, size_t Stack) {
397 CACHE_REGS
398 size_t pm, sa;
399
400 /* sanity checking for data areas */
401 if (Trail < MinTrailSpace)
402 Trail = MinTrailSpace;
403 if (Stack < MinStackSpace)
404 Stack = MinStackSpace;
405 pm = (Trail + Stack) * K; /* memory to be
406 * requested */
407 sa = Stack * K; /* stack area size */
408
409#ifdef THREADS
410 if (wid)
411 REMOTE_GlobalBase(wid) = (ADDR)REMOTE_ThreadHandle(wid).stack_address;
412 else
413 AuxSp = NULL;
414#endif
415 REMOTE_TrailTop(wid) = REMOTE_GlobalBase(wid) + pm;
416 REMOTE_LocalBase(wid) = REMOTE_GlobalBase(wid) + sa;
417 REMOTE_TrailBase(wid) = REMOTE_LocalBase(wid) + sizeof(CELL);
418
419 REMOTE_ScratchPad(wid).ptr = NULL;
420 REMOTE_ScratchPad(wid).sz = REMOTE_ScratchPad(wid).msz = SCRATCH_START_SIZE;
421
422#if DEBUG
423 if (Yap_output_msg) {
424 size_t ta;
425
426 fprintf(stderr,
427 "HeapBase = %p GlobalBase = %p\n LocalBase = %p TrailTop = %p\n",
428 Yap_HeapBase, REMOTE_GlobalBase(wid), REMOTE_LocalBase(wid),
429 REMOTE_TrailTop(wid));
430
431 ta = Trail * K; /* trail area size */
432 fprintf(stderr, "Heap+Aux: %lu\tLocal+Global: %lu\tTrail: %lu\n",
433 (long unsigned)(pm - sa - ta), (long unsigned)sa,
434 (long unsigned)ta);
435 }
436#endif /* DEBUG */
437}
438
439void Yap_InitExStacks(int wid, size_t Trail, size_t Stack) {
440 //memset(&REMOTE_WorkerBuffer(wid),0,sizeof(scratch_sys_struct_t));
441 InitExStacks(wid, Trail, Stack);
442}
443
444#if defined(THREADS)
445void Yap_KillStacks(int wid) {
446 ADDR gb = REMOTE_ThreadHandle(wid).stack_address;
447 if (gb) {
448 free(gb);
449 REMOTE_ThreadHandle(wid).stack_address = NULL;
450 }
451}
452#else
453void Yap_KillStacks(int wid) {
454 if (LOCAL_GlobalBase) {
455 free(LOCAL_GlobalBase);
456 LOCAL_GlobalBase = NULL;
457 }
458}
459#endif
460
461void Yap_InitMemory(size_t Trail, size_t Heap, size_t Stack) {
462 Yap_HoleSize = 0;
463 HeapMax = 0;
464 Yap_heap_regs =
465 (struct various_codes *)calloc(1, sizeof(struct various_codes));
466 }
467
468int Yap_ExtendWorkSpace(Int s) {
469 CACHE_REGS
470 void *basebp = LOCAL_GlobalBase, *nbp;
471 UInt s0 = LOCAL_TrailTop - LOCAL_GlobalBase;
472 nbp = realloc(basebp, s + s0);
473 if (nbp == NULL)
474 return FALSE;
475#if defined(THREADS)
476 LOCAL_ThreadHandle.stack_address = (char *)nbp;
477#endif
478 LOCAL_GlobalBase = (char *)nbp;
479 return TRUE;
480}
481
482size_t Yap_ExtendWorkSpaceThroughHole(size_t s) { return 0; }
483
484void Yap_AllocHole(UInt actual_request, UInt total_size) {}
485
486#if HAVE_MALLINFO
487UInt Yap_givemallinfo(void) {
488 struct mallinfo mi = mallinfo();
489 return mi.uordblks;
490}
491#endif
492
493#else
494
495#if HAVE_SNPRINTF
496#define snprintf3(A, B, C) snprintf(A, B, C)
497#define snprintf4(A, B, C, D) snprintf(A, B, C, D)
498#define snprintf5(A, B, C, D, E) snprintf(A, B, C, D, E)
499#else
500#define snprintf3(A, B, C) sprintf(A, C)
501#define snprintf4(A, B, C, D) sprintf(A, C, D)
502#define snprintf5(A, B, C, D, E) sprintf(A, C, D, E)
503#endif
504
505#ifdef LIGHT
506#include <stdlib.h>
507#endif
508
509#if !USE_DL_MALLOC
510
511static void FreeBlock(BlockHeader *);
512static BlockHeader *GetBlock(unsigned long int);
513static char *AllocHeap(unsigned long int);
514static void RemoveFromFreeList(BlockHeader *);
515static void AddToFreeList(BlockHeader *);
516
517#define MinHGap 256 * K
518
519static void RemoveFromFreeList(BlockHeader *b) {
520 BlockHeader *p;
521
522 p = b->b_next_size;
523 LOCK(HeapUsedLock);
524 HeapUsed += (b->b_size + 1) * sizeof(YAP_SEG_SIZE);
525 UNLOCK(HeapUsedLock);
526
527 if (p && b->b_size == p->b_size) {
528 b = b->b_next;
529 p->b_next = b;
530 if (b)
531 b->b_next_size = p;
532 } else {
533 BlockHeader **q = &FreeBlocks;
534
535 while ((*q) != b)
536 q = &((*q)->b_next_size);
537 if (b->b_next) {
538 p = b->b_next;
539 *q = p;
540 p->b_next_size = b->b_next_size;
541 } else {
542 *q = b->b_next_size;
543 }
544 }
545}
546
547static void AddToFreeList(BlockHeader *b) {
548 BlockHeader **q, *p;
549 YAP_SEG_SIZE *sp;
550
551 /* insert on list of free blocks */
552 q = &FreeBlocks;
553 sp = &(b->b_size) + b->b_size;
554 *sp = b->b_size;
555 LOCK(HeapUsedLock);
556 HeapUsed -= (b->b_size + 1) * sizeof(YAP_SEG_SIZE);
557 UNLOCK(HeapUsedLock);
558
559 while ((p = *q) && p->b_size < b->b_size)
560 q = &p->b_next_size;
561 if (p && p->b_size == b->b_size) {
562 b->b_next = p;
563 b->b_next_size = p->b_next_size;
564 p->b_next_size = b;
565 } else {
566 b->b_next = NIL;
567 b->b_next_size = p;
568 }
569 *q = b;
570}
571
572static void FreeBlock(BlockHeader *b) {
573 BlockHeader *p;
574 YAP_SEG_SIZE *sp;
575
576 /* {
577 static long long int vsc_free_ops;
578
579 vsc_free_ops++;
580 BlockHeader *q = FreeBlocks;
581 while (q) q = q->b_next_size;
582 }*/
583
584 /* sanity check */
585 sp = &(b->b_size) + (b->b_size & ~InUseFlag);
586 if (!(b->b_size & InUseFlag) || *sp != b->b_size) {
587#if !SHORT_INTS
588 fprintf(
589 stderr,
590 "%% YAP INTERNAL ERROR: sanity check failed in FreeBlock %p %x %x\n", b,
591 b->b_size, Unsigned(*sp));
592#else
593 fprintf(
594 stderr,
595 "%% YAP INTERNAL ERROR: sanity check failed in FreeBlock %p %lx %lx\n",
596 b, b->b_size, *sp);
597#endif
598 return;
599 }
600 b->b_size &= ~InUseFlag;
601 LOCK(FreeBlocksLock);
602 /* check if we can collapse with other blocsks */
603 /* check previous */
604 sp = &(b->b_size) - 1;
605 if (!(*sp & InUseFlag)) { /* previous block is free */
606 p = (BlockHeader *)(sp - *sp);
607 RemoveFromFreeList(p);
608 p->b_size += b->b_size + 1;
609 b = p;
610 }
611 /* check following */
612 sp = &(b->b_size) + b->b_size + 1;
613 if (!(*sp & InUseFlag)) { /* following block is free */
614 p = (BlockHeader *)sp;
615 RemoveFromFreeList(p);
616 b->b_size += p->b_size + 1;
617 }
618 LOCK(HeapTopLock);
619 if (sp == (YAP_SEG_SIZE *)HeapTop) {
620 LOCK(HeapUsedLock);
621 HeapUsed -= (b->b_size + 1) * sizeof(YAP_SEG_SIZE);
622 UNLOCK(HeapUsedLock);
623 HeapTop = (ADDR)b;
624 *((YAP_SEG_SIZE *)HeapTop) = InUseFlag;
625 } else {
626 /* insert on list of free blocks */
627 AddToFreeList(b);
628 }
629 UNLOCK(HeapTopLock);
630 UNLOCK(FreeBlocksLock);
631}
632
633static BlockHeader *
634GetBlock(unsigned long int n) { /* get free block with size at least n */
635 register BlockHeader **p, *b, *r;
636
637 if (FreeBlocks == NIL)
638 return (NIL);
639 /* check for bugs */
640 p = &FreeBlocks;
641 /* end check for bugs */
642 p = &FreeBlocks;
643 while (((b = *p) != NIL) && b->b_size < n)
644 p = &b->b_next_size;
645 if (b == NIL || b->b_size < n)
646 return (NIL);
647 if ((r = b->b_next) == NIL)
648 *p = b->b_next_size;
649 else {
650 r->b_next_size = b->b_next_size;
651 *p = r;
652 }
653 LOCK(HeapUsedLock);
654 HeapUsed += (b->b_size + 1) * sizeof(YAP_SEG_SIZE);
655 if (HeapUsed > HeapMax)
656 HeapMax = HeapUsed;
657 UNLOCK(HeapUsedLock);
658 return (b);
659}
660
661static char *AllocHeap(size_t size) {
662 BlockHeader *b, *n;
663 YAP_SEG_SIZE *sp;
664 UInt align, extra;
665
666 /* {
667 static long long int vsc_alloc_ops;
668 vsc_alloc_ops++;
669 BlockHeader *q = FreeBlocks;
670 while (q) q = q->b_next_size;
671 }*/
672
673 extra = size / 16;
674#if SIZEOF_INT_P == 4
675 align = 2 * sizeof(CELL); /* size in dwords + 2 */
676#endif
677#if SIZEOF_INT_P == 8
678 align = sizeof(CELL);
679#endif
680 while (align < extra)
681 align *= 2;
682 size = ALIGN_SIZE(size, align);
683 if (size < sizeof(BlockHeader))
684 size = sizeof(BlockHeader);
685 size += sizeof(YAP_SEG_SIZE);
686 /* change units to cells */
687 size = size / sizeof(CELL);
688 LOCK(FreeBlocksLock);
689 if ((b = GetBlock(size))) {
690 if (b->b_size >= size + 24 + 1) {
691 n = (BlockHeader *)(((YAP_SEG_SIZE *)b) + size + 1) v;
692 n->b_size = b->b_size - size - 1;
693 b->b_size = size;
694 AddToFreeList(n);
695 }
696 sp = &(b->b_size) + b->b_size;
697 *sp = b->b_size | InUseFlag;
698 b->b_size |= InUseFlag;
699 UNLOCK(FreeBlocksLock);
700 return (Addr(b) + sizeof(YAP_SEG_SIZE));
701 }
702 LOCK(HeapTopLock);
703 UNLOCK(FreeBlocksLock);
704 b = (BlockHeader *)HeapTop;
705 HeapTop += size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
706 LOCK(HeapUsedLock);
707 HeapUsed += size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
708
709#ifdef YAPOR
710 if (HeapTop > Addr(LOCAL_GlobalBase) - MinHeapGap)
711 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "no heap left (AllocHeap)");
712#else
713 if (HeapTop > HeapLim - MinHeapGap) {
714 HeapTop -= size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
715 HeapUsed -= size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
716 if (HeapTop > HeapLim) {
717 UNLOCK(HeapUsedLock);
718 UNLOCK(HeapTopLock);
719 /* we destroyed the stack */
720 Yap_Error(RESOURCE_ERROR_HEAP, TermNil, "Stack Crashed against Heap...");
721 return (NULL);
722 } else {
723 if (HeapTop + size * sizeof(CELL) + sizeof(YAP_SEG_SIZE) < HeapLim) {
724 /* small allocations, we can wait */
725 HeapTop += size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
726 HeapUsed += size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
727 UNLOCK(HeapUsedLock);
728 UNLOCK(HeapTopLock);
729 Yap_signal(YAP_CDOVF_SIGNAL);
730 } else {
731 if (size > GLOBAL_SizeOfOverflow)
732 GLOBAL_SizeOfOverflow = size * sizeof(CELL) + sizeof(YAP_SEG_SIZE);
733 /* big allocations, the caller must handle the problem */
734 UNLOCK(HeapUsedLock);
735 UNLOCK(HeapTopLock);
736 return (NULL);
737 }
738 }
739 }
740#endif /* YAPOR */
741 *((YAP_SEG_SIZE *)HeapTop) = InUseFlag;
742 if (HeapUsed > HeapMax)
743 HeapMax = HeapUsed;
744 UNLOCK(HeapUsedLock);
745 b->b_size = size | InUseFlag;
746 sp = &(b->b_size) + size;
747 *sp = b->b_size;
748 UNLOCK(HeapTopLock);
749 return (Addr(b) + sizeof(YAP_SEG_SIZE));
750}
751
752/* If you need to dinamically allocate space from the heap, this is
753 * the macro you should use */
754static void FreeCodeSpace(char *p) {
755 FreeBlock(((BlockHeader *)(p - sizeof(YAP_SEG_SIZE))));
756}
757
758static char *AllocCodeSpace(unsigned long int size) {
759 if (size < SmallSize + 2 * OpCodeSize + 3 * CellSize)
760 return (AllocHeap(SmallSize + 2 * OpCodeSize + 3 * CellSize));
761 return (AllocHeap(size));
762}
763
764#if DEBUG_ALLOC
765int vsc_mem_trace;
766#endif
767
768/* If you need to dinamically allocate space from the heap, this is
769 * the macro you should use */
770void Yap_FreeCodeSpace(char *p) {
771#if DEBUG_ALLOC
772 if (vsc_mem_trace)
773 printf("-%p\n", p);
774#endif
775 FreeCodeSpace(p);
776}
777
778char *Yap_AllocAtomSpace(unsigned long int size) {
779 char *out = AllocHeap(size);
780#if DEBUG_ALLOC
781 if (vsc_mem_trace)
782 printf("+%p/%d\n", out, size);
783#endif
784 return out;
785}
786
787void Yap_FreeAtomSpace(char *p) {
788#if DEBUG_ALLOC
789 if (vsc_mem_trace)
790 printf("-%p\n", p);
791#endif
792 FreeCodeSpace(p);
793}
794
795char *Yap_AllocCodeSpace(unsigned long int size) {
796 char *out = AllocCodeSpace(size);
797#if DEBUG_ALLOC
798 if (vsc_mem_trace)
799 printf("+%p/%d\n", out, size);
800#endif
801 return out;
802}
803
804#endif
805
806/************************************************************************/
807/* Workspace allocation */
808/* */
809/* We provide four alternatives for workspace allocation. */
810/* - use 'mmap' */
811/* - use 'shmat' */
812/* - use 'sbrk' and provide a replacement to the 'malloc' library */
813/* - use 'malloc' */
814/* */
815/* In any of the alternatives the interface is through the following */
816/* functions: */
817/* void *InitWorkSpace(int s) - initial workspace allocation */
818/* int ExtendWorkSpace(int s) - extend workspace */
819/* int Yap_FreeWorkSpace() - release workspace */
820/************************************************************************/
821
822#if defined(_WIN32) || defined(__CYGWIN__)
823
824#undef DEBUG_WIN32_ALLO
825
826#include "windows.h"
827
828static LPVOID brk;
829
830static int ExtendWorkSpace(Int s, int fixed_allocation) {
831 LPVOID b = brk;
832 prolog_exec_mode OldPrologMode = LOCAL_PrologMode;
833
834 LOCAL_PrologMode = ExtendStackMode;
835
836#if DEBUG_WIN32_ALLOC
837 fprintf(stderr, "trying: %p (" Int_FORMAT "K) %d\n", b, s / 1024,
838 fixed_allocation);
839#endif
840 if (fixed_allocation) {
841 b = VirtualAlloc(b, s, MEM_RESERVE, PAGE_NOACCESS);
842 } else {
843 b = VirtualAlloc(NULL, s, MEM_RESERVE, PAGE_NOACCESS);
844 if (b && b < brk) {
845 LOCAL_PrologMode = OldPrologMode;
846 return ExtendWorkSpace(s, fixed_allocation);
847 }
848 }
849 if (!b) {
850 LOCAL_PrologMode = OldPrologMode;
851#if DEBUG_WIN32_ALLOC
852 {
853 char msg[256];
854 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
855 NULL, GetLastError(),
856 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), msg, 256, NULL);
857 fprintf(stderr, "NOT OK1: %p %p %s\n", brk, b, msg);
858 }
859#endif
860 return FALSE;
861 }
862 b = VirtualAlloc(b, s, MEM_COMMIT, PAGE_READWRITE);
863 if (!b) {
864 LOCAL_ErrorMessage = LOCAL_ErrorSay;
865 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
866 "VirtualAlloc could not commit %ld bytes", (long int)s);
867 LOCAL_PrologMode = OldPrologMode;
868#if DEBUG_WIN32_ALLOC
869 fprintf(stderr, "NOT OK2: %p--%p\n", b, brk);
870#endif
871 return FALSE;
872 }
873 brk = (LPVOID)((Int)b + s);
874#if DEBUG_WIN32_ALLOC
875 fprintf(stderr, "OK: %p--%p " Int_FORMAT "\n", b, brk, s);
876#endif
877 LOCAL_PrologMode = OldPrologMode;
878 return TRUE;
879}
880
881static MALLOC_T InitWorkSpace(Int s) {
882 SYSTEM_INFO si;
883 Int psz;
884
885 GetSystemInfo(&si);
886 psz = Yap_page_size = si.dwPageSize;
887 brk = (LPVOID)psz;
888 if (!ExtendWorkSpace(s, 0))
889 return FALSE;
890 return (MALLOC_T)brk - s;
891}
892
893int Yap_FreeWorkSpace(void) { return TRUE; }
894
895#elif USE_SYSTEM_MMAP
896
897#if HAVE_UNISTD_H
898#include <unistd.h>
899#endif
900#if HAVE_SYS_MMAN_H
901#include <sys/mman.h>
902#endif
903#if HAVE_SYS_TYPES_H
904#include <sys/types.h>
905#endif
906#if HAVE_FCNTL_H
907#include <fcntl.h>
908#endif
909
910#ifdef MMAP_ADDR
911#define USE_FIXED 1
912#endif
913
914#ifndef MAP_FIXED
915#define MAP_FIXED 1
916#endif
917
918static MALLOC_T WorkSpaceTop;
919
920static MALLOC_T InitWorkSpace(Int s) {
921 MALLOC_T a;
922#if !defined(_AIX) && !defined(__APPLE__) && !__hpux
923 int fd;
924#endif
925#if defined(_AIX)
926 a = mmap(0, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
927 MAP_PRIVATE | MAP_ANONYMOUS | MAP_VARIABLE, -1, 0);
928#elif __hpux
929 a = mmap(((void *)MMAP_ADDR), (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
930 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
931 if (a != (MALLOC_T)MMAP_ADDR) {
932 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
933 "mmap could not map ANON at %p, got %p", (void *)MMAP_ADDR, a);
934 return (NULL);
935 }
936#elif defined(__APPLE__)
937#ifdef MMAP_ADDR
938 a = mmap(((void *)MMAP_ADDR), (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
939 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
940 if (a != (MALLOC_T)MMAP_ADDR) {
941 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
942 "mmap could not map ANON at %p, got %p", (void *)MMAP_ADDR, a);
943 return (NULL);
944 }
945#else
946 a = mmap(NULL, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
947 MAP_PRIVATE | MAP_ANON, -1, 0);
948#endif
949#else
950 fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
951 if (fd < 0) {
952#if HAVE_MKSTEMP
953 char file[256];
954 strncpy(file, "/tmp/YAP.TMPXXXXXX", 256);
955 if (mkstemp(file) == -1) {
956#if HAVE_STRERROR
957 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
958 "mkstemp could not create temporary file %s (%s)", file,
959 strerror(errno));
960#else
961 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
962 "mkstemp could not create temporary file %s", file);
963#endif
964 return NULL;
965 }
966#else
967#if HAVE_TMPNAM
968 char *file = tmpnam(NULL);
969#else
970 char file[MAX_PATH];
971 strcpy(file, "/tmp/mapfile");
972 itos(getpid(), &file[12]);
973#endif /* HAVE_TMPNAM */
974#endif /* HAVE_MKSTEMP */
975 fd = open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
976 if (fd < 0) {
977 Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "mmap could not open %s", file);
978 return NULL;
979 }
980 if (lseek(fd, s, SEEK_SET) < 0) {
981 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
982 "mmap could not lseek in mmapped file %s", file);
983 close(fd);
984 return FALSE;
985 }
986 if (write(fd, "", 1) < 0) {
987 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
988 "mmap could not write in mmapped file %s", file);
989 close(fd);
990 return NULL;
991 }
992 if (unlink(file) < 0) {
993 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
994 "mmap could not unlink mmapped file %s", file);
995 close(fd);
996 return NULL;
997 }
998 }
999#if USE_FIXED
1000 a = mmap(((void *)MMAP_ADDR), (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
1001 MAP_PRIVATE | MAP_FIXED, fd, 0);
1002 if (a != (MALLOC_T)MMAP_ADDR) {
1003 Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "mmap could not map at %p, got %p",
1004 (void *)MMAP_ADDR, a);
1005 return NULL;
1006 }
1007#else
1008 a = mmap(0, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd,
1009 0);
1010 if ((CELL)a & YAP_PROTECTED_MASK) {
1011 close(fd);
1012 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
1013 "mmapped address %p collides with YAP tags", a);
1014 return NULL;
1015 }
1016 if (close(fd) == -1) {
1017 Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "while closing mmaped file");
1018 return NULL;
1019 }
1020#endif
1021#endif
1022 if
1023#ifdef MMAP_FAILED
1024 (a == (MALLOC_T)MMAP_FAILED)
1025#else
1026 (a == (MALLOC_T)-1)
1027#endif
1028 {
1029 Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "mmap cannot allocate memory ***");
1030 return (NULL);
1031 }
1032 WorkSpaceTop = (char *)a + s;
1033 return (void *)a;
1034}
1035
1036#ifndef YAPOR
1037static MALLOC_T mmap_extension(Int s, MALLOC_T base, int fixed_allocation) {
1038 MALLOC_T a;
1039
1040#if !defined(_AIX) && !defined(__hpux) && !defined(__APPLE__)
1041 int fd;
1042#endif
1043#if defined(_AIX) || defined(__hpux)
1044 a = mmap(base, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
1045 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1046
1047#elif defined(__APPLE__)
1048 a = mmap(base, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
1049 MAP_PRIVATE | MAP_ANON | fixed_allocation, -1, 0);
1050#else
1051 fd = open("/dev/zero", O_RDWR);
1052 if (fd < 0) {
1053#if HAVE_MKSTEMP
1054 char file[256];
1055 strncpy(file, "/tmp/YAP.TMPXXXXXX", 256);
1056 if (mkstemp(file) == -1) {
1057 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1058#if HAVE_STRERROR
1059 snprintf5(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1060 "mkstemp could not create temporary file %s (%s)", file,
1061 strerror(errno));
1062#else
1063 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1064 "mkstemp could not create temporary file %s", file);
1065#endif /* HAVE_STRERROR */
1066 return (MALLOC_T)-1;
1067 }
1068#else
1069#if HAVE_TMPNAM
1070 char *file = tmpnam(NULL);
1071#else
1072 char file[MAX_PATH];
1073 strcpy(file, "/tmp/mapfile");
1074 itos(getpid(), &file[12]);
1075#endif /* HAVE_TMPNAM */
1076#endif /* HAVE_MKSTEMP */
1077 fd = open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1078 if (fd < 0) {
1079 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1080 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1081 "mmap could not open %s", file);
1082 return (MALLOC_T)-1;
1083 }
1084 if (lseek(fd, s, SEEK_SET) < 0) {
1085 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1086 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1087 "mmap could not lseek in mmapped file %s", file);
1088 close(fd);
1089 return (MALLOC_T)-1;
1090 }
1091 if (write(fd, "", 1) < 0) {
1092 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1093 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1094 "mmap could not write in mmapped file %s", file);
1095 close(fd);
1096 return (MALLOC_T)-1;
1097 }
1098 if (unlink(file) < 0) {
1099 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1100 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1101 "mmap could not unlink mmapped file %s", file);
1102 close(fd);
1103 return (MALLOC_T)-1;
1104 }
1105 }
1106 a = mmap(
1107 base, (size_t)s, PROT_READ | PROT_WRITE | PROT_EXEC,
1108 MAP_PRIVATE
1109#if !defined(__linux)
1110 /* use MAP_FIXED, otherwise God knows where you will be placed */
1111 | fixed_allocation
1112#endif
1113 ,
1114 fd, 0);
1115 if (close(fd) == -1) {
1116 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1117#if HAVE_STRERROR
1118 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1119 "mmap could not close file (%s) ]\n", strerror(errno));
1120#else
1121 snprintf3(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1122 "mmap could not close file ]\n");
1123#endif
1124 return (MALLOC_T)-1;
1125 }
1126#endif
1127 return a;
1128}
1129#endif /* !YAPOR */
1130
1131/*
1132 s= how much memory we need;
1133 fixed_alloc = do we need to contiguously extend stack
1134 returns TRUE or FALSE
1135
1136 updates WorkSpaceTop
1137*/
1138static int ExtendWorkSpace(Int s, int fixed_allocation) {
1139#ifdef YAPOR
1140 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
1141 "cannot extend stacks (ExtendWorkSpace)");
1142 return (FALSE);
1143#else
1144 MALLOC_T a;
1145 prolog_exec_mode OldPrologMode = LOCAL_PrologMode;
1146 MALLOC_T base = WorkSpaceTop;
1147
1148 if (fixed_allocation == MAP_FIXED)
1149 base = WorkSpaceTop;
1150 else
1151 base = 0L;
1152 LOCAL_PrologMode = ExtendStackMode;
1153 a = mmap_extension(s, base, fixed_allocation);
1154 LOCAL_PrologMode = OldPrologMode;
1155 if (a == (MALLOC_T)-1) {
1156 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1157#if HAVE_STRERROR
1158 snprintf5(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1159 "could not allocate %d bytes (%s)", (int)s, strerror(errno));
1160#else
1161 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1162 "could not allocate %d bytes", (int)s);
1163#endif
1164 return FALSE;
1165 }
1166 if (fixed_allocation) {
1167 if (a != WorkSpaceTop) {
1168 munmap((void *)a, (size_t)s);
1169 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1170 snprintf5(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1171 "mmap could not grow memory at %p, got %p", WorkSpaceTop, a);
1172 LOCAL_PrologMode = OldPrologMode;
1173 return FALSE;
1174 }
1175 } else if (a < WorkSpaceTop) {
1176 /* try again */
1177 int res = ExtendWorkSpace(s, fixed_allocation);
1178 /* release memory back to system */
1179 munmap(a, s);
1180 return res;
1181 }
1182 WorkSpaceTop = (char *)a + s;
1183 LOCAL_PrologMode = OldPrologMode;
1184 return TRUE;
1185#endif /* YAPOR */
1186}
1187
1188int Yap_FreeWorkSpace(void) { return 1; }
1189
1190#elif USE_SYSTEM_SHM
1191
1192#if HAVE_SYS_SHM_H
1193#include <sys/shm.h>
1194#endif
1195
1196#ifndef MMAP_ADDR
1197#define MMAP_ADDR 0x0L
1198#endif
1199
1200static MALLOC_T WorkSpaceTop;
1201
1202static MALLOC_T InitWorkSpace(Int s) {
1203 MALLOC_T ptr;
1204 int shm_id;
1205
1206 /* mapping heap area */
1207 if ((shm_id = shmget(IPC_PRIVATE, (size_t)s, SHM_R | SHM_W)) == -1) {
1208 Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "could not shmget %d bytes", s);
1209 return (NULL);
1210 }
1211 if ((ptr = (MALLOC_T)shmat(shm_id, (void *)MMAP_ADDR, 0)) == (MALLOC_T)-1) {
1212 Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "could not shmat at %p", MMAP_ADDR);
1213 return (NULL);
1214 }
1215 if (shmctl(shm_id, IPC_RMID, 0) != 0) {
1216 Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "could not remove shm segment",
1217 shm_id);
1218 return (NULL);
1219 }
1220 WorkSpaceTop = (char *)ptr + s;
1221 return (ptr);
1222}
1223
1224static int ExtendWorkSpace(Int s) {
1225 MALLOC_T ptr;
1226 int shm_id;
1227 prolog_exec_mode OldPrologMode = LOCAL_PrologMode;
1228
1229 LOCAL_PrologMode = ExtendStackMode;
1230 /* mapping heap area */
1231 if ((shm_id = shmget(IPC_PRIVATE, (size_t)s, SHM_R | SHM_W)) == -1) {
1232 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1233 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1234 "could not shmget %d bytes", s);
1235 LOCAL_PrologMode = OldPrologMode;
1236 return (FALSE);
1237 }
1238 if ((ptr = (MALLOC_T)shmat(shm_id, WorkSpaceTop, 0)) == (MALLOC_T)-1) {
1239 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1240 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE, "could not shmat at %p",
1241 MMAP_ADDR);
1242 LOCAL_PrologMode = OldPrologMode;
1243 return (FALSE);
1244 }
1245 if (shmctl(shm_id, IPC_RMID, 0) != 0) {
1246 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1247 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1248 "could not remove shm segment", shm_id);
1249 LOCAL_PrologMode = OldPrologMode;
1250 return (FALSE);
1251 }
1252 WorkSpaceTop = (char *)ptr + s;
1253 LOCAL_PrologMode = OldPrologMode;
1254 return (TRUE);
1255}
1256
1257int Yap_FreeWorkSpace(void) { return TRUE; }
1258
1259#elif USE_SBRK
1260
1261/***********************************************************************\
1262* Worspace allocation based on 'sbrk' *
1263* We have to provide a replacement for the 'malloc' functions. *
1264* The situation is further complicated by the need to provide *
1265* temporary 'malloc' space when restoring a previously saved state. *
1266\***********************************************************************/
1267
1268#ifdef _AIX
1269char *sbrk(int);
1270
1271#endif
1272
1273int in_limbo; /* non-zero when restoring a saved state */
1274
1275#ifndef LIMBO_SIZE
1276#define LIMBO_SIZE 32 * K
1277#endif
1278
1279static char limbo_space[LIMBO_SIZE]; /* temporary malloc space */
1280static char *limbo_p = limbo_space, *limbo_pp = 0;
1281
1282static MALLOC_T InitWorkSpace(Int s) {
1283 MALLOC_T ptr = (MALLOC_T)sbrk(s);
1284
1285 if (ptr == ((MALLOC_T)-1)) {
1286 Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "could not allocate %d bytes", s);
1287 return (NULL);
1288 }
1289 return (ptr);
1290}
1291
1292static int ExtendWorkSpace(Int s) {
1293 MALLOC_T ptr = (MALLOC_T)sbrk(s);
1294 prolog_exec_mode OldPrologMode = LOCAL_PrologMode;
1295
1296 LOCAL_PrologMode = ExtendStackMode;
1297 if (ptr == ((MALLOC_T)-1)) {
1298 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1299 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1300 "could not expand stacks over %d bytes", s);
1301 LOCAL_PrologMode = OldPrologMode;
1302 return (FALSE);
1303 }
1304 LOCAL_PrologMode = OldPrologMode;
1305 return TRUE;
1306}
1307
1308int Yap_FreeWorkSpace(void) { return TRUE; }
1309
1310MALLOC_T
1311malloc(size_t size) {
1312 if (in_limbo) {
1313 limbo_pp = limbo_p;
1314 limbo_p += (size + 7) & 0xffff8;
1315 if (limbo_p >= &limbo_space[LIMBO_SIZE])
1316 return (NULL);
1317 return (limbo_pp);
1318 } else {
1319 CODEADDR codep = (CODEADDR)AllocCodeSpace(size + 2 * sizeof(void *));
1320 if (codep == NIL)
1321 return (NIL);
1322 else
1323 return (codep + 2 * sizeof(void *));
1324 }
1325}
1326
1327void free(MALLOC_T ptr) {
1328 BlockHeader *b = (BlockHeader *)(((char *)ptr) - 2 * sizeof(void *) -
1329 sizeof(YAP_SEG_SIZE));
1330
1331 if (ptr == limbo_pp) {
1332 limbo_p = limbo_pp;
1333 return;
1334 }
1335 if (!ptr)
1336 return;
1337 if ((char *)ptr < Yap_HeapBase || (char *)ptr > HeapTop)
1338 return;
1339 if (!(b->b_size & InUseFlag))
1340 return;
1341 FreeCodeSpace((char *)ptr - 2 * sizeof(void *));
1342}
1343
1344MALLOC_T
1345XX realloc(MALLOC_T ptr, size_t size) {
1346 MALLOC_T new = malloc(size);
1347
1348 if (ptr)
1349 memmove(new, ptr, size);
1350 free(ptr);
1351 return (new);
1352}
1353
1354MALLOC_T
1355calloc(size_t n, size_t e) {
1356 unsigned k = n * e;
1357 MALLOC_T p = malloc(k);
1358
1359 memset(p, 0, k);
1360 return (p);
1361}
1362
1363#ifdef M_MXFAST
1364int mallopt(cmd, value) { return (value); }
1365
1366static struct mallinfo xmall;
1367
1368struct mallinfo mallinfo(void) {
1369 return (xmall);
1370}
1371#endif
1372
1373#else
1374
1375/* use malloc to initiliase memory */
1376
1377/* user should ask for a lot of memory first */
1378
1379#ifdef __linux
1380#define MAX_SPACE 420 * 1024 * 1024
1381#else
1382#define MAX_SPACE 128 * 1024 * 1024
1383#endif
1384
1385static int total_space;
1386
1387static MALLOC_T InitWorkSpace(Int s) {
1388 MALLOC_T ptr;
1389
1390#ifdef M_MMAP_MAX
1391 mallopt(M_MMAP_MAX, 0);
1392#endif
1393 ptr = (MALLOC_T)calloc(MAX_SPACE, 1);
1394 total_space = s;
1395
1396 if (ptr == NULL) {
1397 Yap_Error(SYSTEM_ERROR_FATAL, TermNil, "could not allocate %d bytes", s);
1398 return (NULL);
1399 }
1400 return (ptr);
1401}
1402
1403static int ExtendWorkSpace(Int s) {
1404 MALLOC_T ptr;
1405 prolog_exec_mode OldPrologMode = LOCAL_PrologMode;
1406
1407 total_space += s;
1408 if (total_space < MAX_SPACE)
1409 return TRUE;
1410 LOCAL_PrologMode = ExtendStackMode;
1411 ptr = (MALLOC_T)realloc((void *)Yap_HeapBase, total_space);
1412 if (ptr == NULL) {
1413 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1414 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1415 "could not allocate %d bytes", s);
1416 LOCAL_PrologMode = OldPrologMode;
1417 return FALSE;
1418 }
1419 if (ptr != (MALLOC_T)Yap_HeapBase) {
1420 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1421 snprintf4(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1422 "could not expand contiguous stacks %d bytes", s);
1423 LOCAL_PrologMode = OldPrologMode;
1424 return FALSE;
1425 }
1426#if MBIT
1427 if ((CELL)ptr & MBIT) {
1428 LOCAL_ErrorMessage = LOCAL_ErrorSay;
1429 snprintf5(LOCAL_ErrorMessage, MAX_ERROR_MSG_SIZE,
1430 "memory at %p conflicts with MBIT %lx", ptr, (unsigned long)MBIT);
1431 LOCAL_PrologMode = OldPrologMode;
1432 return FALSE;
1433 }
1434#endif
1435 LOCAL_PrologMode = OldPrologMode;
1436 return TRUE;
1437}
1438
1439int Yap_FreeWorkSpace(void) { return TRUE; }
1440#endif
1441
1442static void InitHeap(void *heap_addr) {
1443 /* allocate space */
1444 Yap_HeapBase = heap_addr;
1445
1446 /* reserve space for specially allocated functors and atoms so that
1447 their values can be known statically */
1448 HeapTop = Yap_HeapBase + AdjustSize(sizeof(all_heap_codes));
1449 Yap_HoleSize = 0;
1450#if USE_DL_MALLOC
1451 Yap_initdlmalloc();
1452#else
1453 HeapMax = HeapUsed = HeapTop - Yap_HeapBase;
1454 /* notice that this forces odd addresses */
1455 *((YAP_SEG_SIZE *)HeapTop) = InUseFlag;
1456 HeapTop = HeapTop + sizeof(YAP_SEG_SIZE);
1457 *((YAP_SEG_SIZE *)HeapTop) = InUseFlag;
1458#endif
1459
1460 FreeBlocks = NIL;
1461}
1462
1463void Yap_InitHeap(void *heap_addr) { InitHeap(heap_addr); }
1464
1465void Yap_InitMemory(UInt Trail, UInt Heap, UInt Stack) {
1466 UInt pm, sa, ta;
1467 void *addr;
1468
1469#if defined(_WIN32) || defined(__CYGWIN__)
1470 Stack = ((Stack + (YAP_ALLOC_SIZE - 1)) / YAP_ALLOC_SIZE) * YAP_ALLOC_SIZE;
1471 Heap = ((Heap + (YAP_ALLOC_SIZE - 1)) / YAP_ALLOC_SIZE) * YAP_ALLOC_SIZE;
1472 Trail = ((Trail + (YAP_ALLOC_SIZE - 1)) / YAP_ALLOC_SIZE) * YAP_ALLOC_SIZE;
1473#endif
1474 pm = (Trail + Heap + Stack); /* memory to be
1475 * requested */
1476 sa = Stack; /* stack area size */
1477 ta = Trail; /* trail area size */
1478
1479#if RANDOMIZE_START_ADDRESS
1480 srand(time(NULL));
1481 UInt x = (rand() % 100) * YAP_ALLOC_SIZE;
1482 pm += x;
1483#endif
1484 addr = InitWorkSpace(pm);
1485#if RANDOMIZE_START_ADDRESS
1486 addr = (char *)addr + x;
1487 pm -= x;
1488#endif
1489
1490 InitHeap(addr);
1491
1492 LOCAL_TrailTop = Yap_HeapBase + pm;
1493 LOCAL_LocalBase = LOCAL_TrailTop - ta;
1494 LOCAL_TrailBase = LOCAL_LocalBase + sizeof(CELL);
1495
1496 LOCAL_GlobalBase = LOCAL_LocalBase - sa;
1497 HeapLim = LOCAL_GlobalBase; /* avoid confusions while
1498 * * restoring */
1499#if !USE_DL_MALLOC
1500 AuxTop = (ADDR)(AuxSp = (CELL *)LOCAL_GlobalBase);
1501#endif
1502
1503#if DEBUG
1504#if SIZEOF_INT_P != SIZEOF_INT
1505 if (Yap_output_msg) {
1506 fprintf(stderr,
1507 "HeapBase = %p GlobalBase = %p\n LocalBase = %p TrailTop = %p\n",
1508 Yap_HeapBase, LOCAL_GlobalBase, LOCAL_LocalBase, LOCAL_TrailTop);
1509#else
1510 if (Yap_output_msg) {
1511 fprintf(stderr,
1512 "HeapBase = %x GlobalBase = %x\n LocalBase = %x TrailTop = %x\n",
1513 (UInt)Yap_HeapBase, (UInt)LOCAL_GlobalBase, (UInt)LOCAL_LocalBase,
1514 (UInt)LOCAL_TrailTop);
1515#endif
1516
1517 fprintf(stderr,
1518 "Heap+Aux: " UInt_FORMAT "\tLocal+Global: " UInt_FORMAT
1519 "\tTrail: " UInt_FORMAT "\n",
1520 pm - sa - ta, sa, ta);
1521 }
1522#endif /* DEBUG */
1523}
1524
1525void Yap_InitExStacks(int wid, int Trail, int Stack) {
1526#if USE_DL_MALLOC
1527 REMOTE_ScratchPad(wid).ptr = NULL;
1528 REMOTE_ScratchPad(wid).sz = REMOTE_ScratchPad(wid).msz = SCRATCH_START_SIZE;
1529 AuxSp = NULL;
1530#endif
1531}
1532
1533#if defined(_WIN32) || defined(__CYGWIN__)
1534#define WorkSpaceTop brk
1535#define MAP_FIXED 1
1536#endif
1537
1538#if !USE_DL_MALLOC
1539/* dead code */
1540void Yap_add_memory_hole(ADDR Start, ADDR End) { Yap_HoleSize += Start - End; }
1541#endif
1542
1543int Yap_ExtendWorkSpace(Int s) {
1544#if USE_SYSTEM_MMAP
1545 return ExtendWorkSpace(s, MAP_FIXED);
1546#elif defined(_WIN32)
1547 return ExtendWorkSpace(s, MAP_FIXED);
1548#else
1549 return ExtendWorkSpace(s);
1550#endif
1551}
1552
1553size_t Yap_ExtendWorkSpaceThroughHole(size_t s) {
1554#if USE_SYSTEM_MMAP || defined(_WIN32) || defined(__CYGWIN__)
1555 MALLOC_T WorkSpaceTop0 = WorkSpaceTop;
1556#if SIZEOF_INT_P == 4
1557 while (WorkSpaceTop < (MALLOC_T)0xc0000000L) {
1558 /* progress 1 MB */
1559 WorkSpaceTop += 512 * 1024;
1560 if (ExtendWorkSpace(s, MAP_FIXED)) {
1561 Yap_add_memory_hole((ADDR)WorkSpaceTop0, (ADDR)WorkSpaceTop - s);
1562 LOCAL_ErrorMessage = NULL;
1563 return WorkSpaceTop - WorkSpaceTop0;
1564 }
1565#if defined(_WIN32)
1566 /* 487 happens when you step over someone else's memory */
1567 if (GetLastError() != 487) {
1568 WorkSpaceTop = WorkSpaceTop0;
1569 return 0;
1570 }
1571#endif
1572#elif SIZEOF_INT_P == 8
1573 {
1574 int n = 1024 * 1024;
1575 while (n--) {
1576 /* progress 1 MB */
1577 WorkSpaceTop += 512 * 1024;
1578 if (ExtendWorkSpace(s, MAP_FIXED)) {
1579 Yap_add_memory_hole((ADDR)WorkSpaceTop0, (ADDR)WorkSpaceTop - s);
1580 LOCAL_ErrorMessage = NULL;
1581 return WorkSpaceTop - WorkSpaceTop0;
1582 }
1583#if defined(_WIN32)
1584 /* 487 happens when you step over someone else's memory */
1585 WorkSpaceTop = WorkSpaceTop0;
1586 return 0;
1587 }
1588#endif
1589 }
1590#endif
1591 }
1592 WorkSpaceTop = WorkSpaceTop0;
1593#endif
1594 return 0;
1595}
1596
1597void Yap_AllocHole(UInt actual_request, UInt total_size) {
1598#if (USE_SYSTEM_MMAP || defined(_WIN32) || defined(__CYGWIN__)) && \
1599 !USE_DL_MALLOC
1600 /* where we were when the hole was created,
1601 also where is the hole store */
1602 ADDR WorkSpaceTop0 = WorkSpaceTop - total_size;
1603 BlockHeader *newb = (BlockHeader *)HeapTop;
1604 BlockHeader *endb = (BlockHeader *)(WorkSpaceTop0 - sizeof(YAP_SEG_SIZE));
1605 YAP_SEG_SIZE bsiz = (WorkSpaceTop0 - HeapTop) / sizeof(CELL) -
1606 2 * sizeof(YAP_SEG_SIZE) / sizeof(CELL);
1607
1608 /* push HeapTop to after hole */
1609 HeapTop = WorkSpaceTop - (actual_request - sizeof(YAP_SEG_SIZE));
1610 ((YAP_SEG_SIZE *)HeapTop)[0] = InUseFlag;
1611 /* now simulate a block */
1612 ((YAP_SEG_SIZE *)HeapTop)[-1] = endb->b_size =
1613 (HeapTop - WorkSpaceTop0) / sizeof(YAP_SEG_SIZE) | InUseFlag;
1614 newb->b_size = bsiz;
1615 AddToFreeList(newb);
1616#endif
1617}
1618
1619
1620
1621
1622#endif /* USE_SYSTEM_MALLOC */
1623
1632#include "Yap.h"
1633#include "YapEval.h"
1634#include "YapHeap.h"
1635#include "YapStreams.h"
1636#include "YapText.h"
1637#include "Yatom.h"
1638#include "yapio.h"
1639
1640#include <YapText.h>
1641#include <string.h>
1642#include <wchar.h>
1643
1644
1650#define MAX_PATHNAME 2048
1651
1652struct mblock {
1653 struct mblock *prev, *next;
1654 int lvl;
1655 size_t sz;
1656};
1657
1658typedef struct TextBuffer_manager {
1659 void *buf, *ptr;
1660 size_t sz;
1661 struct mblock *first[16];
1662 struct mblock *last[16];
1663 int lvl;
1665
1666int AllocLevel(void) { return LOCAL_TextBuffer->lvl; }
1667// void pop_text_stack(int i) { LOCAL_TextBuffer->lvl = i; }
1668void insert_block(struct mblock *o) {
1669 int lvl = o->lvl;
1670 o->prev = LOCAL_TextBuffer->last[lvl];
1671 if (o->prev) {
1672 o->prev->next = o;
1673 }
1674 if (LOCAL_TextBuffer->first[lvl]) {
1675 LOCAL_TextBuffer->last[lvl] = o;
1676 } else {
1677 LOCAL_TextBuffer->first[lvl] = LOCAL_TextBuffer->last[lvl] = o;
1678 }
1679 o->next = NULL;
1680}
1681
1682 void release_block(struct mblock *o) {
1683 int lvl = o->lvl;
1684 if (LOCAL_TextBuffer->first[lvl] == o) {
1685 if (LOCAL_TextBuffer->last[lvl] == o) {
1686 LOCAL_TextBuffer->first[lvl] = LOCAL_TextBuffer->last[lvl] = NULL;
1687 }
1688 LOCAL_TextBuffer->first[lvl] = o->next;
1689 } else if (LOCAL_TextBuffer->last[lvl] == o) {
1690 LOCAL_TextBuffer->last[lvl] = o->prev;
1691 }
1692 if (o->prev)
1693 o->prev->next = o->next;
1694 if (o->next)
1695 o->next->prev = o->prev;
1696}
1697
1698int push_text_stack__(USES_REGS1) {
1699 int i = LOCAL_TextBuffer->lvl;
1700 LOCAL_TextBuffer->lvl = i+1;
1701
1702 return i;
1703}
1704
1705int pop_text_stack__(int i) {
1706 int lvl = LOCAL_TextBuffer->lvl;
1707 while (lvl > i) {
1708 struct mblock *p = LOCAL_TextBuffer->first[lvl];
1709 while (p) {
1710 struct mblock *np = p->next;
1711 free(p);
1712 p = np;
1713 }
1714 LOCAL_TextBuffer->first[lvl] = NULL;
1715 LOCAL_TextBuffer->last[lvl] = NULL;
1716 lvl--;
1717 }
1718 LOCAL_TextBuffer->lvl = lvl;
1719 return lvl;
1720}
1721
1722void *pop_output_text_stack__(int i, const void *export) {
1723 int lvl = LOCAL_TextBuffer->lvl;
1724 bool found = false;
1725 while (lvl > i) {
1726 struct mblock *p = LOCAL_TextBuffer->first[lvl];
1727 while (p) {
1728 struct mblock *np = p->next;
1729 if (p + 1 == export) {
1730 found = true;
1731 } else {
1732 free(p);
1733 }
1734 p = np;
1735 }
1736 LOCAL_TextBuffer->first[lvl] = NULL;
1737 LOCAL_TextBuffer->last[lvl] = NULL;
1738 lvl--;
1739 }
1740 LOCAL_TextBuffer->lvl = lvl;
1741 if (found) {
1742 if (lvl) {
1743 struct mblock *o = (struct mblock *)export-1;
1744 o->lvl = lvl;
1745 o->prev = o->next = 0;
1746 insert_block(o);
1747
1748 } else {
1749 struct mblock *p = (struct mblock *)export-1;
1750 size_t sz = p->sz - sizeof(struct mblock);
1751 memmove(p, p + 1, sz);
1752 export = p;
1753
1754 }
1755 }
1756 return (void *)export;
1757}
1758
1759void *Malloc(size_t sz USES_REGS) {
1760 int lvl = LOCAL_TextBuffer->lvl;
1761 if (sz == 0)
1762 sz = 1024;
1763 sz = ALIGN_BY_TYPE(sz + sizeof(struct mblock), CELL);
1764 struct mblock *o = malloc(sz);
1765 if (!o)
1766 return NULL;
1767 o->sz = sz;
1768 o->lvl = lvl;
1769 o->prev = o->next = 0;
1770 insert_block(o);
1771 return o + 1;
1772}
1773
1774void *MallocAtLevel(size_t sz, int atL USES_REGS) {
1775 int lvl = LOCAL_TextBuffer->lvl;
1776 if (atL > 0 && atL <= lvl) {
1777 lvl = atL;
1778 } else if (atL < 0 && lvl - atL >= 0) {
1779 lvl += atL;
1780 } else {
1781 return NULL;
1782 }
1783 if (sz == 0)
1784 sz = 1024;
1785 sz = ALIGN_BY_TYPE(sz + sizeof(struct mblock), CELL);
1786 struct mblock *o = malloc(sz);
1787 if (!o)
1788 return NULL;
1789 o->sz = sz;
1790 o->lvl = lvl;
1791 o->prev = o->next = 0;
1792 insert_block(o);
1793 return o + 1;
1794}
1795
1796void *Realloc(void *pt, size_t sz USES_REGS) {
1797 struct mblock *old = pt, *o;
1798 if (!pt)
1799 return Malloc(sz PASS_REGS);
1800 old--;
1801 sz = ALIGN_BY_TYPE(sz, Yap_Max(CELLSIZE,sizeof(struct mblock)));
1802 sz += 2*sizeof(struct mblock);
1803 o = realloc(old, sz);
1804 if (o->next) {
1805 o->next->prev = o;
1806 } else {
1807 LOCAL_TextBuffer->last[o->lvl] = o;
1808 }
1809 if (o->prev) {
1810 o->prev->next = o;
1811 } else {
1812 LOCAL_TextBuffer->first[o->lvl] = o;
1813 }
1814 o->sz = sz;
1815 return o + 1;
1816}
1817
1824const void *MallocExportAsRO(const void *pt USES_REGS) {
1825 struct mblock *old = (void *)pt, *o = old - 1;
1826 if (old == NULL)
1827 return NULL;
1828 size_t sz = o->sz;
1829 release_block(o);
1830 memmove((void *)o, pt, sz);
1831 return realloc((void *)o, sz);
1832}
1833
1834void Free(void *pt USES_REGS) {
1835 struct mblock *o = pt;
1836 o--;
1837 release_block(o);
1838 free(o);
1839}
1840
1841void *Yap_InitTextAllocator(void) {
1842 struct TextBuffer_manager *new = calloc(sizeof(struct TextBuffer_manager), 1);
1843 return new;
1844}
1845
1846/*
1847 bool Yap_get_scratch_buf(scratch_struct_t *handle, size_t nof, size_t each) {
1848 if (!nof) nof=1024;
1849 if (!LOCAL_WorkerBuffer.data) {
1850 LOCAL_WorkerBuffer.data = malloc(nof*each);
1851 LOCAL_WorkerBuffer.sz = nof*each;
1852 handle->n_of = nof;
1853 handle->size_of = each;
1854 LOCAL_WorkerBuffer.in_use = true;
1855 } else if (LOCAL_WorkerBuffer.data && !LOCAL_WorkerBuffer.in_use) {
1856 if (LOCAL_WorkerBuffer.sz < nof*each) {
1857 LOCAL_WorkerBuffer.data = realloc( LOCAL_WorkerBuffer.data, nof*each);
1858 LOCAL_WorkerBuffer.sz = nof*each;
1859 }
1860 LOCAL_WorkerBuffer.in_use = true;
1861 handle->data = LOCAL_WorkerBuffer.data;
1862 handle->is_thread_scratch_buf = true;
1863 } else {
1864 handle->data = malloc(nof*each);
1865 handle->is_thread_scratch_buf = false;
1866 }
1867 handle->n_of = nof;
1868 handle->size_of = each;
1869 printf("+ %lx @ %p\n", handle->n_of, handle->data);
1870return handle->data != NULL;
1871 }
1872
1873
1874
1875bool Yap_realloc_scratch_buf(scratch_struct_t *handle, size_t nof) {
1876 size_t each = handle->size_of;
1877if (nof==0 && handle->n_of)
1878 nof = handle->n_of*2;
1879 if (handle->is_thread_scratch_buf) {
1880 LOCAL_WorkerBuffer.data = realloc( LOCAL_WorkerBuffer.data, nof*each);
1881 LOCAL_WorkerBuffer.sz = nof*each;
1882 handle->data = LOCAL_WorkerBuffer.data;
1883 } else {
1884 handle->data = realloc(handle->data, nof*each);
1885 }
1886
1887 handle->n_of = nof;
1888 printf("? %lx @ %p\n", handle->n_of, handle->data);
1889 return handle->data != NULL;
1890}
1891
1892
1893 bool Yap_release_scratch_buf(scratch_struct_t *handle) {
1894 if (handle->is_thread_scratch_buf &&
1895 handle->data == LOCAL_WorkerBuffer.data) {
1896 LOCAL_WorkerBuffer.in_use= false;
1897 handle->is_thread_scratch_buf= false;
1898 } else {
1899 free(handle->data);
1900
1901 }
1902// printf("- %lx @ %p\n", handle->n_of, handle->data);
1903 handle->data = NULL;
1904 handle->n_of = 0;
1905
1906 return true;
1907 }
1908
1909 */
Main definitions.
CELL YAP_SEG_SIZE
definitions required by saver/restorer and memory manager
Definition: alloc.h:61
Definition: alloc.h:63
void * Malloc(size_t sz USES_REGS)
allocate a temporary text block
Definition: alloc.c:1759
Definition: alloc.c:1652