1 #define GC_SMALLEST_PAGESIZE 4096
2 /* #define DEBUG_MREMAP 1 */
4 /* Used to allocate at the head and tail of an existing allocation */
5 static void *GC_extendHead (void *base
, size_t length
);
6 static void *GC_extendTail (void *base
, size_t length
);
8 void *GC_mremap (void *base
, size_t oldLength
, size_t newLength
) {
9 static void* cacheAddress
= 0;
10 static size_t cacheOldLength
= 0;
11 static size_t cacheNewLength
= 0;
12 static size_t cacheTailSize
;
13 static size_t cacheHeadSize
;
18 size_t growth
, bsLow
, bsHigh
, bsTry
;
21 fprintf(stderr
, "remap(%08X, %d, %d)\n", (size_t)base
, oldLength
, newLength
);
25 if (newLength
== oldLength
)
27 if (newLength
< oldLength
) {
28 GC_release((char*)base
+ newLength
, oldLength
-newLength
);
32 growth
= newLength
-oldLength
;
34 if (cacheAddress
== base
&&
35 cacheOldLength
== oldLength
&&
36 cacheNewLength
> newLength
) /* cache only during backoff */
37 goto GC_mremap_cached
;
39 /* Start probing for the available tail length */
41 bsHigh
= (growth
+GC_SMALLEST_PAGESIZE
-1)/GC_SMALLEST_PAGESIZE
;
42 /* Round bsHigh to a power of two -> allocation works with all page sizes */
43 for (bsTry
= 1; bsTry
<= bsHigh
; bsTry
+= bsTry
) { }
45 while (bsHigh
- bsLow
> 1) {
46 bsTry
= (bsHigh
+ bsLow
)/2;
47 tail
= (char*)base
+ oldLength
;
48 alloc
= GC_extendTail(tail
, bsTry
*GC_SMALLEST_PAGESIZE
);
51 GC_release(alloc
, bsTry
*GC_SMALLEST_PAGESIZE
);
54 if (alloc
!= (void*)-1)
55 GC_release(alloc
, bsTry
*GC_SMALLEST_PAGESIZE
);
59 cacheTailSize
= bsLow
*GC_SMALLEST_PAGESIZE
;
61 /* Start probing for the available head length */
63 bsHigh
= (growth
+GC_SMALLEST_PAGESIZE
-1)/GC_SMALLEST_PAGESIZE
;
64 /* Round bsHigh to a power of two -> allocation works with all page sizes */
65 for (bsTry
= 1; bsTry
<= bsHigh
; bsTry
+= bsTry
) { }
67 while (bsHigh
- bsLow
> 1) {
68 bsTry
= (bsHigh
+ bsLow
)/2;
69 head
= (char*)base
- bsTry
*GC_SMALLEST_PAGESIZE
;
70 alloc
= GC_extendHead(head
, bsTry
*GC_SMALLEST_PAGESIZE
);
73 GC_release(alloc
, bsTry
*GC_SMALLEST_PAGESIZE
);
76 if (alloc
!= (void*)-1)
77 GC_release(alloc
, bsTry
*GC_SMALLEST_PAGESIZE
);
81 cacheHeadSize
= bsLow
*GC_SMALLEST_PAGESIZE
;
84 fprintf(stderr
, "Expansion detects: %10d/%10d/%10d = %10d\n",
85 cacheHeadSize
, oldLength
, cacheTailSize
,
86 cacheHeadSize
+ oldLength
+ cacheTailSize
);
91 cacheOldLength
= oldLength
;
94 cacheNewLength
= newLength
;
96 /* Is there enough free space? */
97 if (cacheTailSize
+ cacheHeadSize
< growth
) {
98 /* No, there's not. Try to move it instead. */
99 alloc
= GC_mmapAnon(0, newLength
);
100 if (alloc
!= (void*)-1) {
101 memcpy(alloc
, base
, oldLength
);
102 GC_release(base
, oldLength
);
105 /* Failed even to move it */
110 fprintf(stderr
, "Expansion attempts %d bytes\n", newLength
);
114 if (growth
<= cacheTailSize
) {
115 tail
= (char*)base
+ oldLength
;
116 alloc
= GC_extendTail(tail
, growth
);
118 /* This shouldn't happen; we tested for the memory! */
119 if (alloc
!= (void*)-1)
120 GC_release(alloc
, growth
);
126 if (cacheTailSize
> 0) {
127 tail
= (char*)base
+ oldLength
;
128 alloc
= GC_extendTail(tail
, cacheTailSize
);
130 /* This shouldn't happen; we tested for the memory! */
131 if (alloc
!= (void*)-1)
132 GC_release(alloc
, cacheTailSize
);
136 tail
= 0; /* quell warning */
139 head
= (char*)base
- (growth
-cacheTailSize
);
140 alloc
= GC_extendHead(head
, growth
-cacheTailSize
);
142 /* This shouldn't happen; we tested for the memory! */
143 if (alloc
!= (void*)-1)
144 GC_release(alloc
, growth
-cacheTailSize
);
145 if (cacheTailSize
> 0)
146 GC_release(tail
, cacheTailSize
);
150 memmove(head
, base
, oldLength
);