| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | namespace factor { | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | HMODULE hFactorDll; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::init_ffi() { | 
					
						
							|  |  |  |   hFactorDll = GetModuleHandle(FACTOR_DLL); | 
					
						
							|  |  |  |   if (!hFactorDll) | 
					
						
							|  |  |  |     fatal_error("GetModuleHandle() failed", 0); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::ffi_dlopen(dll* dll) { | 
					
						
							|  |  |  |   dll->handle = LoadLibraryEx((WCHAR*)alien_offset(dll->path), NULL, 0); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void* factor_vm::ffi_dlsym(dll* dll, symbol_char* symbol) { | 
					
						
							|  |  |  |   return (void*)GetProcAddress(dll ? (HMODULE) dll->handle : hFactorDll, | 
					
						
							|  |  |  |                                symbol); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void* factor_vm::ffi_dlsym_raw(dll* dll, symbol_char* symbol) { | 
					
						
							|  |  |  |   return ffi_dlsym(dll, symbol); | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::ffi_dlclose(dll* dll) { | 
					
						
							|  |  |  |   FreeLibrary((HMODULE) dll->handle); | 
					
						
							|  |  |  |   dll->handle = NULL; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | BOOL factor_vm::windows_stat(vm_char* path) { | 
					
						
							|  |  |  |   BY_HANDLE_FILE_INFORMATION bhfi; | 
					
						
							|  |  |  |   HANDLE h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, | 
					
						
							|  |  |  |                          OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (h == INVALID_HANDLE_VALUE) { | 
					
						
							|  |  |  |     // FindFirstFile is the only call that can stat c:\pagefile.sys
 | 
					
						
							|  |  |  |     WIN32_FIND_DATA st; | 
					
						
							|  |  |  |     HANDLE h; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (INVALID_HANDLE_VALUE == (h = FindFirstFile(path, &st))) | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     FindClose(h); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   BOOL ret = GetFileInformationByHandle(h, &bhfi); | 
					
						
							|  |  |  |   CloseHandle(h); | 
					
						
							|  |  |  |   return ret; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::windows_image_path(vm_char* full_path, vm_char* temp_path, | 
					
						
							|  |  |  |                                    unsigned int length) { | 
					
						
							|  |  |  |   wcsncpy(temp_path, full_path, length - 1); | 
					
						
							|  |  |  |   size_t full_path_len = wcslen(full_path); | 
					
						
							|  |  |  |   if (full_path_len < length - 1) | 
					
						
							|  |  |  |     wcsncat(temp_path, L".image", length - full_path_len - 1); | 
					
						
							|  |  |  |   temp_path[length - 1] = 0; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* You must free() this yourself. */ | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | const vm_char* factor_vm::default_image_path() { | 
					
						
							|  |  |  |   vm_char full_path[MAX_UNICODE_PATH]; | 
					
						
							|  |  |  |   vm_char* ptr; | 
					
						
							|  |  |  |   vm_char temp_path[MAX_UNICODE_PATH]; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   if (!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH)) | 
					
						
							|  |  |  |     fatal_error("GetModuleFileName() failed", 0); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   if ((ptr = wcsrchr(full_path, '.'))) | 
					
						
							|  |  |  |     *ptr = 0; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   wcsncpy(temp_path, full_path, MAX_UNICODE_PATH - 1); | 
					
						
							|  |  |  |   size_t full_path_len = wcslen(full_path); | 
					
						
							|  |  |  |   if (full_path_len < MAX_UNICODE_PATH - 1) | 
					
						
							|  |  |  |     wcsncat(temp_path, L".image", MAX_UNICODE_PATH - full_path_len - 1); | 
					
						
							|  |  |  |   temp_path[MAX_UNICODE_PATH - 1] = 0; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   return safe_strdup(temp_path); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* You must free() this yourself. */ | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | const vm_char* factor_vm::vm_executable_path() { | 
					
						
							|  |  |  |   vm_char full_path[MAX_UNICODE_PATH]; | 
					
						
							|  |  |  |   if (!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH)) | 
					
						
							|  |  |  |     fatal_error("GetModuleFileName() failed", 0); | 
					
						
							|  |  |  |   return safe_strdup(full_path); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::primitive_existsp() { | 
					
						
							|  |  |  |   vm_char* path = untag_check<byte_array>(ctx->pop())->data<vm_char>(); | 
					
						
							|  |  |  |   ctx->push(tag_boolean(windows_stat(path))); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | segment::segment(cell size_, bool executable_p) { | 
					
						
							|  |  |  |   size = size_; | 
					
						
							| 
									
										
										
										
											2009-09-25 22:17:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   char* mem; | 
					
						
							|  |  |  |   DWORD ignore; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   if ((mem = (char*)VirtualAlloc( | 
					
						
							|  |  |  |            NULL, getpagesize() * 2 + size, MEM_COMMIT, | 
					
						
							|  |  |  |            executable_p ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE)) == | 
					
						
							|  |  |  |       0) | 
					
						
							|  |  |  |     out_of_memory(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore)) | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |     fatal_error("Cannot allocate low guard page", (cell)mem); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   if (!VirtualProtect(mem + size + getpagesize(), getpagesize(), PAGE_NOACCESS, | 
					
						
							|  |  |  |                       &ignore)) | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |     fatal_error("Cannot allocate high guard page", (cell)mem); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   start = (cell)mem + getpagesize(); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   end = start + size; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | segment::~segment() { | 
					
						
							|  |  |  |   SYSTEM_INFO si; | 
					
						
							|  |  |  |   GetSystemInfo(&si); | 
					
						
							|  |  |  |   if (!VirtualFree((void*)(start - si.dwPageSize), 0, MEM_RELEASE)) | 
					
						
							|  |  |  |     fatal_error("Segment deallocation failed", 0); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | long getpagesize() { | 
					
						
							|  |  |  |   static long g_pagesize = 0; | 
					
						
							|  |  |  |   if (!g_pagesize) { | 
					
						
							|  |  |  |     SYSTEM_INFO system_info; | 
					
						
							|  |  |  |     GetSystemInfo(&system_info); | 
					
						
							|  |  |  |     g_pagesize = system_info.dwPageSize; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return g_pagesize; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void code_heap::guard_safepoint() { | 
					
						
							|  |  |  |   DWORD ignore; | 
					
						
							|  |  |  |   if (!VirtualProtect(safepoint_page, getpagesize(), PAGE_NOACCESS, &ignore)) | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |     fatal_error("Cannot protect safepoint guard page", (cell)safepoint_page); | 
					
						
							| 
									
										
										
										
											2011-10-17 16:46:25 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void code_heap::unguard_safepoint() { | 
					
						
							|  |  |  |   DWORD ignore; | 
					
						
							|  |  |  |   if (!VirtualProtect(safepoint_page, getpagesize(), PAGE_READWRITE, &ignore)) | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |     fatal_error("Cannot unprotect safepoint guard page", (cell)safepoint_page); | 
					
						
							| 
									
										
										
										
											2011-10-17 16:46:25 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::move_file(const vm_char* path1, const vm_char* path2) { | 
					
						
							|  |  |  |   if (MoveFileEx((path1), (path2), MOVEFILE_REPLACE_EXISTING) == false) | 
					
						
							|  |  |  |     general_error(ERROR_IO, tag_fixnum(GetLastError()), false_object); | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-02-03 17:03:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-28 11:37:28 -04:00
										 |  |  | void factor_vm::init_signals() {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | THREADHANDLE start_thread(void* (*start_routine)(void*), void* args) { | 
					
						
							|  |  |  |   return (void*)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) start_routine, | 
					
						
							|  |  |  |                              args, 0, 0); | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  | uint64_t nano_count() { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   static double scale_factor; | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |   static uint32_t hi = 0; | 
					
						
							|  |  |  |   static uint32_t lo = 0; | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   LARGE_INTEGER count; | 
					
						
							|  |  |  |   BOOL ret = QueryPerformanceCounter(&count); | 
					
						
							|  |  |  |   if (ret == 0) | 
					
						
							|  |  |  |     fatal_error("QueryPerformanceCounter", 0); | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   if (scale_factor == 0.0) { | 
					
						
							|  |  |  |     LARGE_INTEGER frequency; | 
					
						
							|  |  |  |     BOOL ret = QueryPerformanceFrequency(&frequency); | 
					
						
							|  |  |  |     if (ret == 0) | 
					
						
							|  |  |  |       fatal_error("QueryPerformanceFrequency", 0); | 
					
						
							|  |  |  |     scale_factor = (1000000000.0 / frequency.QuadPart); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef FACTOR_64
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   hi = count.HighPart; | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   /* On VirtualBox, QueryPerformanceCounter does not increment
 | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | 	the high part every time the low part overflows.  Workaround. */ | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   if (lo > count.LowPart) | 
					
						
							|  |  |  |     hi++; | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   lo = count.LowPart; | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   return (uint64_t)((((uint64_t)hi << 32) | (uint64_t)lo) * scale_factor); | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  | void sleep_nanos(uint64_t nsec) { Sleep((DWORD)(nsec / 1000000)); } | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | typedef enum _EXCEPTION_DISPOSITION { | 
					
						
							|  |  |  |   ExceptionContinueExecution = 0, | 
					
						
							|  |  |  |   ExceptionContinueSearch = 1, | 
					
						
							|  |  |  |   ExceptionNestedException = 2, | 
					
						
							|  |  |  |   ExceptionCollidedUnwind = 3 | 
					
						
							| 
									
										
										
										
											2011-11-11 16:29:46 -05:00
										 |  |  | } EXCEPTION_DISPOSITION; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | LONG factor_vm::exception_handler(PEXCEPTION_RECORD e, void* frame, PCONTEXT c, | 
					
						
							|  |  |  |                                   void* dispatch) { | 
					
						
							|  |  |  |   switch (e->ExceptionCode) { | 
					
						
							|  |  |  |     case EXCEPTION_ACCESS_VIOLATION: | 
					
						
							|  |  |  |       signal_fault_addr = e->ExceptionInformation[1]; | 
					
						
							|  |  |  |       verify_memory_protection_error(signal_fault_addr); | 
					
						
							|  |  |  |       dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP, | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |                               (cell)factor::memory_signal_handler_impl); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case STATUS_FLOAT_DENORMAL_OPERAND: | 
					
						
							|  |  |  |     case STATUS_FLOAT_DIVIDE_BY_ZERO: | 
					
						
							|  |  |  |     case STATUS_FLOAT_INEXACT_RESULT: | 
					
						
							|  |  |  |     case STATUS_FLOAT_INVALID_OPERATION: | 
					
						
							|  |  |  |     case STATUS_FLOAT_OVERFLOW: | 
					
						
							|  |  |  |     case STATUS_FLOAT_STACK_CHECK: | 
					
						
							|  |  |  |     case STATUS_FLOAT_UNDERFLOW: | 
					
						
							|  |  |  |     case STATUS_FLOAT_MULTIPLE_FAULTS: | 
					
						
							|  |  |  |     case STATUS_FLOAT_MULTIPLE_TRAPS: | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | #ifdef FACTOR_64
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |       signal_fpu_status = fpu_status(MXCSR(c)); | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |       signal_fpu_status = fpu_status(X87SW(c) | MXCSR(c)); | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |       /* This seems to have no effect */ | 
					
						
							|  |  |  |       X87SW(c) = 0; | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |       MXCSR(c) &= 0xffffffc0; | 
					
						
							|  |  |  |       dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP, | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |                               (cell)factor::fp_signal_handler_impl); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       signal_number = e->ExceptionCode; | 
					
						
							|  |  |  |       dispatch_signal_handler((cell*)&c->ESP, (cell*)&c->EIP, | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |                               (cell)factor::synchronous_signal_handler_impl); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ExceptionContinueExecution; | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | VM_C_API LONG exception_handler(PEXCEPTION_RECORD e, void* frame, PCONTEXT c, | 
					
						
							|  |  |  |                                 void* dispatch) { | 
					
						
							|  |  |  |   if (factor_vm::fatal_erroring_p) | 
					
						
							|  |  |  |     return ExceptionContinueSearch; | 
					
						
							| 
									
										
										
										
											2011-11-11 16:29:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |   factor_vm* vm = current_vm_p(); | 
					
						
							|  |  |  |   if (vm) | 
					
						
							|  |  |  |     return vm->exception_handler(e, frame, c, dispatch); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return ExceptionContinueSearch; | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) { | 
					
						
							|  |  |  |   switch (dwCtrlType) { | 
					
						
							|  |  |  |     case CTRL_C_EVENT: { | 
					
						
							|  |  |  |       /* The CtrlHandler runs in its own thread without stopping the main
 | 
					
						
							|  |  |  |          thread. Since in practice nobody uses the multi-VM stuff yet, we just | 
					
						
							|  |  |  |          grab the first VM we can get. This will not be a good idea when we | 
					
						
							|  |  |  |          actually support native threads. */ | 
					
						
							|  |  |  |       FACTOR_ASSERT(thread_vms.size() == 1); | 
					
						
							|  |  |  |       factor_vm* vm = thread_vms.begin()->second; | 
					
						
							|  |  |  |       vm->safepoint.enqueue_fep(vm); | 
					
						
							|  |  |  |       return TRUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-10-19 21:54:49 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::open_console() { handle_ctrl_c(); } | 
					
						
							| 
									
										
										
										
											2011-11-15 21:50:42 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::ignore_ctrl_c() { | 
					
						
							|  |  |  |   SetConsoleCtrlHandler(factor::ctrl_handler, FALSE); | 
					
						
							| 
									
										
										
										
											2011-11-15 21:50:42 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::handle_ctrl_c() { | 
					
						
							|  |  |  |   SetConsoleCtrlHandler(factor::ctrl_handler, TRUE); | 
					
						
							| 
									
										
										
										
											2011-10-19 21:54:49 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-09-19 15:02:32 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::lock_console() {} | 
					
						
							| 
									
										
										
										
											2011-11-08 00:12:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::unlock_console() {} | 
					
						
							| 
									
										
										
										
											2011-11-08 00:12:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::close_console() {} | 
					
						
							| 
									
										
										
										
											2011-11-12 16:06:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::sampler_thread_loop() { | 
					
						
							|  |  |  |   LARGE_INTEGER counter, new_counter, units_per_second; | 
					
						
							|  |  |  |   DWORD ok; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ok = QueryPerformanceFrequency(&units_per_second); | 
					
						
							|  |  |  |   FACTOR_ASSERT(ok); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ok = QueryPerformanceCounter(&counter); | 
					
						
							|  |  |  |   FACTOR_ASSERT(ok); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   counter.QuadPart *= samples_per_second; | 
					
						
							|  |  |  |   while (atomic::load(&sampling_profiler_p)) { | 
					
						
							|  |  |  |     SwitchToThread(); | 
					
						
							|  |  |  |     ok = QueryPerformanceCounter(&new_counter); | 
					
						
							|  |  |  |     FACTOR_ASSERT(ok); | 
					
						
							|  |  |  |     new_counter.QuadPart *= samples_per_second; | 
					
						
							|  |  |  |     cell samples = 0; | 
					
						
							|  |  |  |     while (new_counter.QuadPart - counter.QuadPart > | 
					
						
							|  |  |  |            units_per_second.QuadPart) { | 
					
						
							|  |  |  |       ++samples; | 
					
						
							|  |  |  |       counter.QuadPart += units_per_second.QuadPart; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-10-31 17:38:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  |     if (samples > 0) { | 
					
						
							|  |  |  |       DWORD suscount = SuspendThread(thread); | 
					
						
							|  |  |  |       FACTOR_ASSERT(suscount == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       CONTEXT context; | 
					
						
							|  |  |  |       memset((void*)&context, 0, sizeof(CONTEXT)); | 
					
						
							|  |  |  |       context.ContextFlags = CONTEXT_CONTROL; | 
					
						
							|  |  |  |       BOOL context_ok = GetThreadContext(thread, &context); | 
					
						
							|  |  |  |       FACTOR_ASSERT(context_ok); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       suscount = ResumeThread(thread); | 
					
						
							|  |  |  |       FACTOR_ASSERT(suscount == 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       safepoint.enqueue_samples(this, samples, context.EIP, false); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-10-31 17:38:49 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | static DWORD WINAPI sampler_thread_entry(LPVOID parent_vm) { | 
					
						
							|  |  |  |   static_cast<factor_vm*>(parent_vm)->sampler_thread_loop(); | 
					
						
							|  |  |  |   return 0; | 
					
						
							| 
									
										
										
										
											2011-10-31 03:11:59 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::start_sampling_profiler_timer() { | 
					
						
							|  |  |  |   sampler_thread = CreateThread(NULL, 0, &sampler_thread_entry, | 
					
						
							|  |  |  |                                 static_cast<LPVOID>(this), 0, NULL); | 
					
						
							| 
									
										
										
										
											2011-10-31 03:11:59 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void factor_vm::end_sampling_profiler_timer() { | 
					
						
							|  |  |  |   atomic::store(&sampling_profiler_p, false); | 
					
						
							|  |  |  |   DWORD wait_result = | 
					
						
							|  |  |  |       WaitForSingleObject(sampler_thread, 3000 * (DWORD) samples_per_second); | 
					
						
							|  |  |  |   if (wait_result != WAIT_OBJECT_0) | 
					
						
							|  |  |  |     TerminateThread(sampler_thread, 0); | 
					
						
							|  |  |  |   sampler_thread = NULL; | 
					
						
							| 
									
										
										
										
											2011-11-11 16:29:46 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:24:31 -04:00
										 |  |  | void abort() { ::abort(); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-03 17:03:22 -05:00
										 |  |  | } |