]> gitweb.factorcode.org Git - factor.git/blob - vm/os-windows.cpp
Merge Phil Dawes' VM work
[factor.git] / vm / os-windows.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 HMODULE hFactorDll;
7
8 void factorvm::init_ffi()
9 {
10         hFactorDll = GetModuleHandle(FACTOR_DLL);
11         if(!hFactorDll)
12                 fatal_error("GetModuleHandle(\"" FACTOR_DLL_NAME "\") failed", 0);
13 }
14
15 void factorvm::ffi_dlopen(dll *dll)
16 {
17         dll->dll = LoadLibraryEx((WCHAR *)alien_offset(dll->path), NULL, 0);
18 }
19
20 void *factorvm::ffi_dlsym(dll *dll, symbol_char *symbol)
21 {
22         return (void *)GetProcAddress(dll ? (HMODULE)dll->dll : hFactorDll, symbol);
23 }
24
25 void factorvm::ffi_dlclose(dll *dll)
26 {
27         FreeLibrary((HMODULE)dll->dll);
28         dll->dll = NULL;
29 }
30
31 bool factorvm::windows_stat(vm_char *path)
32 {
33         BY_HANDLE_FILE_INFORMATION bhfi;
34         HANDLE h = CreateFileW(path,
35                         GENERIC_READ,
36                         FILE_SHARE_READ,
37                         NULL,
38                         OPEN_EXISTING,
39                         FILE_FLAG_BACKUP_SEMANTICS,
40                         NULL);
41
42         if(h == INVALID_HANDLE_VALUE)
43         {
44                 // FindFirstFile is the only call that can stat c:\pagefile.sys
45                 WIN32_FIND_DATA st;
46                 HANDLE h;
47
48                 if(INVALID_HANDLE_VALUE == (h = FindFirstFile(path, &st)))
49                         return false;
50                 FindClose(h);
51                 return true;
52         }
53         bool ret;
54         ret = GetFileInformationByHandle(h, &bhfi);
55         CloseHandle(h);
56         return ret;
57 }
58
59
60 void factorvm::windows_image_path(vm_char *full_path, vm_char *temp_path, unsigned int length)
61 {
62         snwprintf(temp_path, length-1, L"%s.image", full_path); 
63         temp_path[length - 1] = 0;
64 }
65
66 /* You must free() this yourself. */
67 const vm_char *factorvm::default_image_path()
68 {
69         vm_char full_path[MAX_UNICODE_PATH];
70         vm_char *ptr;
71         vm_char temp_path[MAX_UNICODE_PATH];
72
73         if(!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
74                 fatal_error("GetModuleFileName() failed", 0);
75
76         if((ptr = wcsrchr(full_path, '.')))
77                 *ptr = 0;
78
79         snwprintf(temp_path, MAX_UNICODE_PATH-1, L"%s.image", full_path); 
80         temp_path[MAX_UNICODE_PATH - 1] = 0;
81
82         return safe_strdup(temp_path);
83 }
84
85 /* You must free() this yourself. */
86 const vm_char *factorvm::vm_executable_path()
87 {
88         vm_char full_path[MAX_UNICODE_PATH];
89         if(!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
90                 fatal_error("GetModuleFileName() failed", 0);
91         return safe_strdup(full_path);
92 }
93
94
95 inline void factorvm::vmprim_existsp()
96 {
97         vm_char *path = untag_check<byte_array>(dpop())->data<vm_char>();
98         box_boolean(windows_stat(path));
99 }
100
101 PRIMITIVE(existsp)
102 {
103         PRIMITIVE_GETVM()->vmprim_existsp();
104 }
105
106 segment *factorvm::alloc_segment(cell size)
107 {
108         char *mem;
109         DWORD ignore;
110
111         if((mem = (char *)VirtualAlloc(NULL, getpagesize() * 2 + size,
112                 MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == 0)
113                 out_of_memory();
114
115         if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore))
116                 fatal_error("Cannot allocate low guard page", (cell)mem);
117
118         if (!VirtualProtect(mem + size + getpagesize(),
119                 getpagesize(), PAGE_NOACCESS, &ignore))
120                 fatal_error("Cannot allocate high guard page", (cell)mem);
121
122         segment *block = (segment *)safe_malloc(sizeof(segment));
123
124         block->start = (cell)mem + getpagesize();
125         block->size = size;
126         block->end = block->start + size;
127
128         return block;
129 }
130
131 void factorvm::dealloc_segment(segment *block)
132 {
133         SYSTEM_INFO si;
134         GetSystemInfo(&si);
135         if(!VirtualFree((void*)(block->start - si.dwPageSize), 0, MEM_RELEASE))
136                 fatal_error("dealloc_segment failed",0);
137         free(block);
138 }
139
140 long factorvm::getpagesize()
141 {
142         static long g_pagesize = 0;
143         if (! g_pagesize)
144         {
145                 SYSTEM_INFO system_info;
146                 GetSystemInfo (&system_info);
147                 g_pagesize = system_info.dwPageSize;
148         }
149         return g_pagesize;
150 }
151
152 void factorvm::sleep_micros(u64 usec)
153 {
154         Sleep((DWORD)(usec / 1000));
155 }
156
157 }