--- A.c Fri Jun 17 18:04:15 2005 +++ B.c Fri Jun 17 18:20:54 2005 @@ -285,6 +285,51 @@ static void ifree(void *ptr); static void *irealloc(void *ptr, size_t size); +/* + * Ugly Wine compatibility stuff: + * This trades brk/sbrk in the data segment for mmap() from WINE_HEAPBASE up + * to the process's stack. + */ + +static caddr_t heapbase; +static caddr_t heaptail; +#define WINE_HEAPBASE ((caddr_t)0xa0000000) + +static caddr_t +heapend() +{ + if (!heapbase) + return sbrk(0); + return heaptail; +} + +static int +heapset(caddr_t point) +{ + caddr_t end; + int error; + + if (!heapbase) + return brk(point); + + /* Page-align the current end point */ + end = (caddr_t)((intptr_t)(heaptail + malloc_pagesize - 1) & + ~(malloc_pagesize - 1)); + error = 0; + + /* Grow or shrink? */ + if (end > point) { + error = munmap(point, end - point); + } + if (end < point) { + error = mmap(end, point - heaptail, PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0) == MAP_FAILED ? -1 : 0; + } + if (!error) + heaptail = point; + return error; +} + static void wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4) { @@ -328,12 +373,12 @@ { caddr_t result, tail; - result = (caddr_t)pageround((u_long)sbrk(0)); + result = (caddr_t)pageround((u_long)heapend()); tail = result + (pages << malloc_pageshift); if (tail < result) return (NULL); - if (brk(tail)) { + if (heapset(tail)) { #ifdef MALLOC_EXTRA_SANITY wrterror("(ES): map_pages fails\n"); #endif /* MALLOC_EXTRA_SANITY */ @@ -457,6 +502,7 @@ case 'X': malloc_xmalloc = 1; break; case 'z': malloc_zero = 0; break; case 'Z': malloc_zero = 1; break; + case 'W': heapbase = heaptail = WINE_HEAPBASE; break; default: _malloc_message(_getprogname(), malloc_func, " warning: ", "unknown char in MALLOC_OPTIONS\n"); @@ -485,7 +531,7 @@ * We need a maximum of malloc_pageshift buckets, steal these from the * front of the page_directory; */ - malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift; + malloc_origo = ((u_long)pageround((u_long)heapend())) >> malloc_pageshift; malloc_origo -= malloc_pageshift; malloc_ninfo = malloc_pagesize / sizeof *page_dir; @@ -532,7 +578,7 @@ wrterror("(ES): zero entry on free_list\n"); if (pf->page > pf->end) wrterror("(ES): sick entry on free_list\n"); - if ((void*)pf->page >= (void*)sbrk(0)) + if ((void*)pf->page >= (void*)heapend()) wrterror("(ES): entry on free_list past brk\n"); if (page_dir[ptr2index(pf->page)] != MALLOC_FREE) wrterror("(ES): non-free first page on free-list\n"); @@ -948,7 +994,7 @@ if (pf->next == NULL && /* If we're the last one, */ pf->size > malloc_cache && /* ..and the cache is full, */ pf->end == malloc_brk && /* ..and none behind us, */ - malloc_brk == sbrk(0)) { /* ..and it's OK to do... */ + malloc_brk == heapend()) { /* ..and it's OK to do... */ /* * Keep the cache intact. Notice that the '>' above guarantees that @@ -957,7 +1003,7 @@ pf->end = (char *)pf->page + malloc_cache; pf->size = malloc_cache; - brk(pf->end); + heapset(pf->end); malloc_brk = pf->end; index = ptr2index(pf->end);