8 void factor_vm::init_ffi()
10 hFactorDll = GetModuleHandle(FACTOR_DLL);
12 fatal_error("GetModuleHandle() failed", 0);
15 void factor_vm::ffi_dlopen(dll *dll)
17 dll->handle = LoadLibraryEx((WCHAR *)alien_offset(dll->path), NULL, 0);
20 void *factor_vm::ffi_dlsym(dll *dll, symbol_char *symbol)
22 return (void *)GetProcAddress(dll ? (HMODULE)dll->handle : hFactorDll, symbol);
25 void *factor_vm::ffi_dlsym_raw(dll *dll, symbol_char *symbol)
27 return ffi_dlsym(dll, symbol);
30 void factor_vm::ffi_dlclose(dll *dll)
32 FreeLibrary((HMODULE)dll->handle);
36 BOOL factor_vm::windows_stat(vm_char *path)
38 BY_HANDLE_FILE_INFORMATION bhfi;
39 HANDLE h = CreateFileW(path,
44 FILE_FLAG_BACKUP_SEMANTICS,
47 if(h == INVALID_HANDLE_VALUE)
49 // FindFirstFile is the only call that can stat c:\pagefile.sys
53 if(INVALID_HANDLE_VALUE == (h = FindFirstFile(path, &st)))
58 BOOL ret = GetFileInformationByHandle(h, &bhfi);
63 void factor_vm::windows_image_path(vm_char *full_path, vm_char *temp_path, unsigned int length)
65 wcsncpy(temp_path, full_path, length - 1);
66 size_t full_path_len = wcslen(full_path);
67 if (full_path_len < length - 1)
68 wcsncat(temp_path, L".image", length - full_path_len - 1);
69 temp_path[length - 1] = 0;
72 /* You must free() this yourself. */
73 const vm_char *factor_vm::default_image_path()
75 vm_char full_path[MAX_UNICODE_PATH];
77 vm_char temp_path[MAX_UNICODE_PATH];
79 if(!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
80 fatal_error("GetModuleFileName() failed", 0);
82 if((ptr = wcsrchr(full_path, '.')))
85 wcsncpy(temp_path, full_path, MAX_UNICODE_PATH - 1);
86 size_t full_path_len = wcslen(full_path);
87 if (full_path_len < MAX_UNICODE_PATH - 1)
88 wcsncat(temp_path, L".image", MAX_UNICODE_PATH - full_path_len - 1);
89 temp_path[MAX_UNICODE_PATH - 1] = 0;
91 return safe_strdup(temp_path);
94 /* You must free() this yourself. */
95 const vm_char *factor_vm::vm_executable_path()
97 vm_char full_path[MAX_UNICODE_PATH];
98 if(!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
99 fatal_error("GetModuleFileName() failed", 0);
100 return safe_strdup(full_path);
103 void factor_vm::primitive_existsp()
105 vm_char *path = untag_check<byte_array>(ctx->pop())->data<vm_char>();
106 ctx->push(tag_boolean(windows_stat(path)));
109 segment::segment(cell size_, bool executable_p)
116 if((mem = (char *)VirtualAlloc(NULL, getpagesize() * 2 + size,
117 MEM_COMMIT, executable_p ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE)) == 0)
120 if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore))
121 fatal_error("Cannot allocate low guard page", (cell)mem);
123 if (!VirtualProtect(mem + size + getpagesize(),
124 getpagesize(), PAGE_NOACCESS, &ignore))
125 fatal_error("Cannot allocate high guard page", (cell)mem);
127 start = (cell)mem + getpagesize();
135 if(!VirtualFree((void*)(start - si.dwPageSize), 0, MEM_RELEASE))
136 fatal_error("Segment deallocation failed",0);
141 static long g_pagesize = 0;
144 SYSTEM_INFO system_info;
145 GetSystemInfo (&system_info);
146 g_pagesize = system_info.dwPageSize;
151 void code_heap::guard_safepoint()
154 if (!VirtualProtect(safepoint_page, getpagesize(), PAGE_NOACCESS, &ignore))
155 fatal_error("Cannot protect safepoint guard page", (cell)safepoint_page);
158 void code_heap::unguard_safepoint()
161 if (!VirtualProtect(safepoint_page, getpagesize(), PAGE_READWRITE, &ignore))
162 fatal_error("Cannot unprotect safepoint guard page", (cell)safepoint_page);
165 void factor_vm::move_file(const vm_char *path1, const vm_char *path2)
167 if(MoveFileEx((path1),(path2),MOVEFILE_REPLACE_EXISTING) == false)
168 general_error(ERROR_IO,tag_fixnum(GetLastError()),false_object);
171 void factor_vm::init_signals() {}
173 THREADHANDLE start_thread(void *(*start_routine)(void *), void *args)
175 return (void *)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, args, 0, 0);
180 static double scale_factor;
186 BOOL ret = QueryPerformanceCounter(&count);
188 fatal_error("QueryPerformanceCounter", 0);
190 if(scale_factor == 0.0)
192 LARGE_INTEGER frequency;
193 BOOL ret = QueryPerformanceFrequency(&frequency);
195 fatal_error("QueryPerformanceFrequency", 0);
196 scale_factor = (1000000000.0 / frequency.QuadPart);
202 /* On VirtualBox, QueryPerformanceCounter does not increment
203 the high part every time the low part overflows. Workaround. */
204 if(lo > count.LowPart)
209 return (u64)((((u64)hi << 32) | (u64)lo) * scale_factor);
212 void sleep_nanos(u64 nsec)
214 Sleep((DWORD)(nsec/1000000));
217 LONG factor_vm::exception_handler(PEXCEPTION_RECORD e, void *frame, PCONTEXT c, void *dispatch)
219 switch (e->ExceptionCode)
221 case EXCEPTION_ACCESS_VIOLATION:
222 signal_fault_addr = e->ExceptionInformation[1];
223 dispatch_signal_handler(
226 (cell)factor::memory_signal_handler_impl
230 case STATUS_FLOAT_DENORMAL_OPERAND:
231 case STATUS_FLOAT_DIVIDE_BY_ZERO:
232 case STATUS_FLOAT_INEXACT_RESULT:
233 case STATUS_FLOAT_INVALID_OPERATION:
234 case STATUS_FLOAT_OVERFLOW:
235 case STATUS_FLOAT_STACK_CHECK:
236 case STATUS_FLOAT_UNDERFLOW:
237 case STATUS_FLOAT_MULTIPLE_FAULTS:
238 case STATUS_FLOAT_MULTIPLE_TRAPS:
240 signal_fpu_status = fpu_status(MXCSR(c));
242 signal_fpu_status = fpu_status(X87SW(c) | MXCSR(c));
244 /* This seems to have no effect */
247 MXCSR(c) &= 0xffffffc0;
248 dispatch_signal_handler(
251 (cell)factor::fp_signal_handler_impl
255 signal_number = e->ExceptionCode;
256 dispatch_signal_handler(
259 (cell)factor::synchronous_signal_handler_impl
267 VM_C_API LONG exception_handler(PEXCEPTION_RECORD e, void *frame, PCONTEXT c, void *dispatch)
269 factor_vm *vm = current_vm_p();
271 return vm->exception_handler(e,frame,c,dispatch);
274 fatal_error("Foreign thread received exception ", e->ExceptionCode);
275 return 0; // to placate MSVC
279 static BOOL WINAPI ctrl_handler(DWORD dwCtrlType)
281 switch (dwCtrlType) {
283 case CTRL_BREAK_EVENT:
285 /* The CtrlHandler runs in its own thread without stopping the main thread.
286 Since in practice nobody uses the multi-VM stuff yet, we just grab the first
287 VM we can get. This will not be a good idea when we actually support native
289 assert(thread_vms.size() == 1);
290 factor_vm *vm = thread_vms.begin()->second;
291 vm->enqueue_safepoint_fep();
299 void factor_vm::open_console()
301 std::cout << "setting ctrl handler\n";
302 SetConsoleCtrlHandler(factor::ctrl_handler, TRUE);