/* Startup code for running on NT. When we are running as the dumped version, we need to bootstrap our heap and .bss section into our address space before we can actually hand off control to the startup code supplied by NT (primarily because that code relies upon malloc ()). */ void _start (void) { extern void mainCRTStartup (void); #if 1 /* Give us a way to debug problems with crashes on startup when running under the MSVC profiler. */ if (GetEnvironmentVariable ("EMACS_DEBUG", NULL, 0) > 0) DebugBreak (); #endif /* Cache system info, e.g., the NT page size. */ cache_system_info (); /* Grab our malloc arena space now, before CRT starts up. */ init_heap (); /* This prevents ctrl-c's in shells running while we're suspended from having us exit. */ SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrl_c_handler, TRUE); /* Prevent Emacs from being locked up (eg. in batch mode) when accessing devices that aren't mounted (eg. removable media drives). */ SetErrorMode (SEM_FAILCRITICALERRORS); mainCRTStartup (); }
VOID WINAPI GetSystemInfo( LPSYSTEM_INFO si /* [out] system information */ ) { if (!cache) cache_system_info(); memcpy(si,&cachedsi,sizeof(*si)); return; }
/*********************************************************************** * IsProcessorFeaturePresent [KERNEL32.@] * RETURNS: * TRUE if processor feature present * FALSE otherwise */ BOOL WINAPI IsProcessorFeaturePresent ( DWORD feature /* [in] feature number, see PF_ defines */ ) { /* Ensure the information is loaded and cached */ if (!cache) cache_system_info(); if (feature < 64) return PF[feature]; else return FALSE; }
/* Initialize the internal heap variables used by sbrk. When running in preload phase (ie. in the undumped executable), we rely entirely on a fixed size heap section included in the .exe itself; this is preserved during dumping, and truncated to the size actually used. When running in the dumped executable, we reserve as much as possible of the address range that is addressable by Lisp object pointers, to supplement what is left of the preload heap. Although we cannot rely on the dynamically allocated arena being contiguous with the static heap area, it is not a problem because sbrk can pretend that the gap was allocated by something else; GNU malloc detects when there is a jump in the sbrk values, and starts a new heap block. */ void init_heap (void) { PIMAGE_DOS_HEADER dos_header; PIMAGE_NT_HEADERS nt_header; dos_header = (PIMAGE_DOS_HEADER) RVA_TO_PTR (0); nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) 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 !USE_LSB_TAG /* Ensure that the addresses don't use the upper tag bits since the Lisp type goes there. */ if (((DWORD_PTR) 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; } /* Update system version information to match current system. */ cache_system_info (); }
/* Startup code for running on NT. When we are running as the dumped version, we need to bootstrap our heap and .bss section into our address space before we can actually hand off control to the startup code supplied by NT (primarily because that code relies upon malloc ()). */ void _start (void) { extern void mainCRTStartup (void); #if 1 /* Give us a way to debug problems with crashes on startup when running under the MSVC profiler. */ if (GetEnvironmentVariable ("EMACS_DEBUG", NULL, 0) > 0) DebugBreak (); #endif /* Cache system info, e.g., the NT page size. */ cache_system_info (); /* Grab our malloc arena space now, before CRT starts up. */ init_heap (); /* This prevents ctrl-c's in shells running while we're suspended from having us exit. */ SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrl_c_handler, TRUE); /* Prevent Emacs from being locked up (eg. in batch mode) when accessing devices that aren't mounted (eg. removable media drives). */ SetErrorMode (SEM_FAILCRITICALERRORS); /* Invoke the NT CRT startup routine now that our housecleaning is finished. */ #ifdef HAVE_NTGUI /* determine WinMain args like crt0.c does */ hinst = GetModuleHandle(NULL); lpCmdLine = GetCommandLine(); nCmdShow = SW_SHOWDEFAULT; #endif mainCRTStartup (); }
void init_heap (bool use_dynamic_heap) { /* FIXME: Remove the condition, the 'else' branch below, and all the related definitions and code, including dumped_data[], when unexec support is removed from Emacs. */ if (use_dynamic_heap) { /* After dumping, use a new private heap. We explicitly enable the low fragmentation heap (LFH) here, for the sake of pre Vista versions. Note: this will harmlessly fail on Vista and later, where the low-fragmentation heap is enabled by default. It will also fail on pre-Vista versions when Emacs is run under a debugger; set _NO_DEBUG_HEAP=1 in the environment before starting GDB to get low fragmentation heap on XP and older systems, for the price of losing "certain heap debug options"; for the details see http://msdn.microsoft.com/en-us/library/windows/desktop/aa366705%28v=vs.85%29.aspx. */ data_region_end = data_region_base; /* Create the private heap. */ heap = HeapCreate (0, 0, 0); #ifndef MINGW_W64 unsigned long enable_lfh = 2; /* Set the low-fragmentation heap for OS before Vista. */ HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll"); HeapSetInformation_Proc s_pfn_Heap_Set_Information = (HeapSetInformation_Proc) get_proc_addr (hm_kernel32dll, "HeapSetInformation"); if (s_pfn_Heap_Set_Information != NULL) { if (s_pfn_Heap_Set_Information ((PVOID) heap, HeapCompatibilityInformation, &enable_lfh, sizeof(enable_lfh)) == 0) DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n", GetLastError ())); } #endif 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 /* Before dumping with unexec: use static heap. */ { /* Find the RtlCreateHeap function. Headers for this function are provided with the w32 DDK, but the function is available in ntdll.dll since XP. */ HMODULE hm_ntdll = LoadLibrary ("ntdll.dll"); RtlCreateHeap_Proc s_pfn_Rtl_Create_Heap = (RtlCreateHeap_Proc) get_proc_addr (hm_ntdll, "RtlCreateHeap"); /* Specific parameters for the private heap. */ RTL_HEAP_PARAMETERS params; ZeroMemory (¶ms, sizeof(params)); params.Length = sizeof(RTL_HEAP_PARAMETERS); data_region_base = (unsigned char *)ROUND_UP (dumped_data, 0x1000); data_region_end = bc_limit = dumped_data + DUMPED_HEAP_SIZE; params.InitialCommit = committed = 0x1000; params.InitialReserve = sizeof(dumped_data); /* Use our own routine to commit memory from the dumped_data array. */ params.CommitRoutine = &dumped_data_commit; /* Create the private heap. */ if (s_pfn_Rtl_Create_Heap == NULL) { fprintf (stderr, "Cannot build Emacs without RtlCreateHeap being available; exiting.\n"); exit (-1); } heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, ¶ms); if (os_subtype == OS_9X) { fprintf (stderr, "Cannot dump Emacs on Windows 9X; exiting.\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. */ cache_system_info (); }