diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h index cdbfac0..a37510e 100644 --- a/nt/inc/ms-w32.h +++ b/nt/inc/ms-w32.h @@ -457,6 +457,10 @@ extern void *malloc_after_dump(size_t); extern void *realloc_after_dump(void *, size_t); extern void free_after_dump(void *); +extern void *malloc_after_dump_9x(size_t); +extern void *realloc_after_dump_9x(void *, size_t); +extern void free_after_dump_9x(void *); + extern malloc_fn the_malloc_fn; extern realloc_fn the_realloc_fn; extern free_fn the_free_fn; diff --git a/src/w32heap.c b/src/w32heap.c index 54646bf..3f6ed67 100644 --- a/src/w32heap.c +++ b/src/w32heap.c @@ -258,9 +258,18 @@ init_heap (void) } #endif - the_malloc_fn = malloc_after_dump; - the_realloc_fn = realloc_after_dump; - the_free_fn = free_after_dump; + if (os_subtype == OS_9X) + { + the_malloc_fn = malloc_after_dump_9x; + the_realloc_fn = realloc_after_dump_9x; + the_free_fn = free_after_dump_9x; + } + else + { + the_malloc_fn = malloc_after_dump; + the_realloc_fn = realloc_after_dump; + the_free_fn = free_after_dump; + } } else { @@ -291,9 +300,18 @@ init_heap (void) exit (-1); } heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, ¶ms); - the_malloc_fn = malloc_before_dump; - the_realloc_fn = realloc_before_dump; - the_free_fn = free_before_dump; + + if (os_subtype == OS_9X) + { + fprintf (stderr, "Cannot run pre-dump Emacs on Windows 9X.\n" ); + exit (-1); + } + else + { + the_malloc_fn = malloc_before_dump; + the_realloc_fn = realloc_before_dump; + the_free_fn = free_before_dump; + } } /* Update system version information to match current system. */ @@ -504,6 +522,65 @@ free_before_dump (void *ptr) } } +/* On Windows 98, HeapAlloc may return pointers that are not aligned + to 8-byte boundary, which is expected by the Lisp memory + management. To circumvent this problem, manually enforce alignment + on Windows 9X. */ + +void * +malloc_after_dump_9x (size_t size) +{ + void *p = malloc_after_dump (size + 8); + void *pa; + if (p == NULL) + return p; + pa = (void*)(((intptr_t)p + 8) & ~7); + *((void**)pa-1) = p; + return pa; +} + +void * +realloc_after_dump_9x (void *ptr, size_t size) +{ + if (FREEABLE_P (ptr)) + { + void *po = *((void**)ptr-1); + void *p; + void *pa; + p = realloc_after_dump (po, size + 8); + if (p == NULL) + return p; + pa = (void*)(((intptr_t)p + 8) & ~7); + if (ptr != NULL && + (char*)pa - (char*)p != (char*)ptr - (char*)po) + { + /* Handle the case where alignment in pre-realloc and + post-realloc blocks do not match. */ + MoveMemory (pa, (void*)((char*)p + ((char*)ptr - (char*)po)), size); + } + *((void**)pa-1) = p; + return pa; + } + else + { + /* Non-freeable pointers have no alignment-enforcing header + (since dumping is not allowed on Windows 9X). */ + void* p = malloc_after_dump_9x (size); + if (p != NULL) + CopyMemory (p, ptr, size); + return p; + } +} + +void +free_after_dump_9x (void *ptr) +{ + if (FREEABLE_P (ptr)) + { + free_after_dump (*((void**)ptr-1)); + } +} + #ifdef ENABLE_CHECKING void report_temacs_memory_usage (void)