#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include "w32heap.h"
#include "lisp.h"
#define RVA_TO_PTR(rva) ((unsigned char *)((DWORD)(rva) + (DWORD)GetModuleHandle (NULL)))
SYSTEM_INFO sysinfo_cache;
OSVERSIONINFO osinfo_cache;
unsigned long syspage_mask = 0;
int w32_major_version;
int w32_minor_version;
int w32_build_number;
int os_subtype;
void
cache_system_info (void)
{
union
{
struct info
{
char major;
char minor;
short platform;
} info;
DWORD data;
} version;
version.data = GetVersion ();
w32_major_version = version.info.major;
w32_minor_version = version.info.minor;
if (version.info.platform & 0x8000)
os_subtype = OS_WIN95;
else
os_subtype = OS_NT;
GetSystemInfo (&sysinfo_cache);
syspage_mask = sysinfo_cache.dwPageSize - 1;
osinfo_cache.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx (&osinfo_cache);
w32_build_number = osinfo_cache.dwBuildNumber;
if (os_subtype == OS_WIN95)
w32_build_number &= 0xffff;
}
int
getpagesize (void)
{
return sysinfo_cache.dwPageSize;
}
PIMAGE_SECTION_HEADER preload_heap_section;
unsigned char *data_region_base = NULL;
unsigned char *data_region_end = NULL;
unsigned char *real_data_region_end = NULL;
unsigned long reserved_heap_size = 0;
unsigned char *
get_data_start (void)
{
return data_region_base;
}
unsigned char *
get_data_end (void)
{
return data_region_end;
}
static char *
allocate_heap (void)
{
unsigned long base =
ROUND_UP ((RVA_TO_PTR (preload_heap_section->VirtualAddress)
+ preload_heap_section->Misc.VirtualSize),
get_allocation_unit ());
unsigned long end = 1 << VALBITS;
void *ptr = NULL;
while (!ptr && (base < end))
{
reserved_heap_size = end - base;
ptr = VirtualAlloc ((void *) base,
get_reserved_heap_size (),
MEM_RESERVE,
PAGE_NOACCESS);
base += 0x00100000;
}
return ptr;
}
void *
sbrk (unsigned long increment)
{
void *result;
long size = (long) increment;
result = data_region_end;
if (size < 0)
{
int new_size;
unsigned char *new_data_region_end;
size = -size;
if ((data_region_end - size) < data_region_base)
return NULL;
new_data_region_end = (data_region_end - size);
new_data_region_end = (unsigned char *)
((long) (new_data_region_end + syspage_mask) & ~syspage_mask);
new_size = real_data_region_end - new_data_region_end;
real_data_region_end = new_data_region_end;
if (new_size > 0)
{
if (using_dynamic_heap
&& !VirtualFree (real_data_region_end, new_size, MEM_DECOMMIT))
return NULL;
}
data_region_end -= size;
}
else if (size > 0)
{
if ((data_region_end + size) >
(data_region_base + get_reserved_heap_size ()))
return NULL;
if (using_dynamic_heap
&& VirtualAlloc (data_region_end, size, MEM_COMMIT,
PAGE_READWRITE) == NULL)
return NULL;
data_region_end += size;
real_data_region_end = (unsigned char *)
((long) (data_region_end + syspage_mask) & ~syspage_mask);
}
return result;
}
void
init_heap ()
{
PIMAGE_DOS_HEADER dos_header;
PIMAGE_NT_HEADERS nt_header;
dos_header = (PIMAGE_DOS_HEADER) RVA_TO_PTR (0);
nt_header = (PIMAGE_NT_HEADERS) (((unsigned long) dos_header) +
dos_header->e_lfanew);
preload_heap_section = find_section ("EMHEAP", nt_header);
if (using_dynamic_heap)
{
data_region_base = allocate_heap ();
if (!data_region_base)
{
printf ("Error: Could not reserve dynamic heap area.\n");
exit (1);
}
#if defined (NO_UNION_TYPE) && !defined (USE_LSB_TAG)
if (((unsigned long) data_region_base & ~VALMASK) != 0)
{
printf ("Error: The heap was allocated in upper memory.\n");
exit (1);
}
#endif
data_region_end = data_region_base;
real_data_region_end = data_region_end;
}
else
{
data_region_base = RVA_TO_PTR (preload_heap_section->VirtualAddress);
data_region_end = data_region_base;
real_data_region_end = data_region_end;
reserved_heap_size = preload_heap_section->Misc.VirtualSize;
}
cache_system_info ();
}
void
round_heap (unsigned long align)
{
unsigned long needs_to_be;
unsigned long need_to_alloc;
needs_to_be = (unsigned long) ROUND_UP (get_heap_end (), align);
need_to_alloc = needs_to_be - (unsigned long) get_heap_end ();
if (need_to_alloc)
sbrk (need_to_alloc);
}
#if (_MSC_VER >= 1000 && _MSC_VER < 1300 && !defined(USE_CRT_DLL))
int __cdecl
_heap_init (void)
{
return 1;
}
void __cdecl
_heap_term (void)
{
return;
}
#endif