]> gitweb.factorcode.org Git - factor.git/blob - vm/os-windows-nt.cpp
Update Win64 support
[factor.git] / vm / os-windows-nt.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 THREADHANDLE start_thread(void *(*start_routine)(void *), void *args)
7 {
8         return (void *)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, args, 0, 0);
9 }
10
11 DWORD dwTlsIndex; 
12
13 void init_platform_globals()
14 {
15         if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
16                 fatal_error("TlsAlloc failed - out of indexes",0);
17 }
18
19 void register_vm_with_thread(factor_vm *vm)
20 {
21         if (! TlsSetValue(dwTlsIndex, vm))
22                 fatal_error("TlsSetValue failed",0);
23 }
24
25 factor_vm *tls_vm()
26 {
27         factor_vm *vm = (factor_vm*)TlsGetValue(dwTlsIndex);
28         assert(vm != NULL);
29         return vm;
30 }
31
32 u64 system_micros()
33 {
34         FILETIME t;
35         GetSystemTimeAsFileTime(&t);
36         return (((u64)t.dwLowDateTime | (u64)t.dwHighDateTime<<32)
37                 - EPOCH_OFFSET) / 10;
38 }
39
40 /* On VirtualBox, QueryPerformanceCounter does not increment
41 the high part every time the low part overflows.  Workaround. */
42 u64 nano_count()
43 {
44         LARGE_INTEGER count;
45         LARGE_INTEGER frequency;
46         static u32 hi = 0;
47         static u32 lo = 0;
48         BOOL ret;
49         ret = QueryPerformanceCounter(&count);
50         if(ret == 0)
51                 fatal_error("QueryPerformanceCounter", 0);
52         ret = QueryPerformanceFrequency(&frequency);
53         if(ret == 0)
54                 fatal_error("QueryPerformanceFrequency", 0);
55
56         if(count.LowPart < lo)
57                 hi += 1;
58         lo = count.LowPart;
59
60         return (u64)((((u64)hi << 32) | (u64)lo)*(1000000000.0/frequency.QuadPart));
61 }
62
63 void sleep_nanos(u64 nsec)
64 {
65         Sleep((DWORD)(nsec/1000000));
66 }
67
68 LONG factor_vm::exception_handler(PEXCEPTION_POINTERS pe)
69 {
70         PEXCEPTION_RECORD e = (PEXCEPTION_RECORD)pe->ExceptionRecord;
71         CONTEXT *c = (CONTEXT*)pe->ContextRecord;
72
73         if(in_code_heap_p(c->EIP))
74                 signal_callstack_top = (stack_frame *)c->ESP;
75         else
76                 signal_callstack_top = NULL;
77
78         switch (e->ExceptionCode)
79         {
80         case EXCEPTION_ACCESS_VIOLATION:
81                 signal_fault_addr = e->ExceptionInformation[1];
82                 c->EIP = (cell)factor::memory_signal_handler_impl;
83                 break;
84
85         case STATUS_FLOAT_DENORMAL_OPERAND:
86         case STATUS_FLOAT_DIVIDE_BY_ZERO:
87         case STATUS_FLOAT_INEXACT_RESULT:
88         case STATUS_FLOAT_INVALID_OPERATION:
89         case STATUS_FLOAT_OVERFLOW:
90         case STATUS_FLOAT_STACK_CHECK:
91         case STATUS_FLOAT_UNDERFLOW:
92         case STATUS_FLOAT_MULTIPLE_FAULTS:
93         case STATUS_FLOAT_MULTIPLE_TRAPS:
94 #ifdef FACTOR_AMD64
95                 signal_fpu_status = fpu_status(MXCSR(c));
96 #else
97                 signal_fpu_status = fpu_status(X87SW(c) | MXCSR(c));
98                 X87SW(c) = 0;
99 #endif
100                 MXCSR(c) &= 0xffffffc0;
101                 c->EIP = (cell)factor::fp_signal_handler_impl;
102                 break;
103         case 0x40010006:
104                 /* If the Widcomm bluetooth stack is installed, the BTTray.exe
105                 process injects code into running programs. For some reason this
106                 results in random SEH exceptions with this (undocumented)
107                 exception code being raised. The workaround seems to be ignoring
108                 this altogether, since that is what happens if SEH is not
109                 enabled. Don't really have any idea what this exception means. */
110                 break;
111         default:
112                 signal_number = e->ExceptionCode;
113                 c->EIP = (cell)factor::misc_signal_handler_impl;
114                 break;
115         }
116         return EXCEPTION_CONTINUE_EXECUTION;
117 }
118
119 FACTOR_STDCALL(LONG) exception_handler(PEXCEPTION_POINTERS pe)
120 {
121         return tls_vm()->exception_handler(pe);
122 }
123
124 void factor_vm::c_to_factor_toplevel(cell quot)
125 {
126         if(!AddVectoredExceptionHandler(0, (PVECTORED_EXCEPTION_HANDLER)factor::exception_handler))
127                 fatal_error("AddVectoredExceptionHandler failed", 0);
128
129         c_to_factor(quot);
130
131         RemoveVectoredExceptionHandler((void *)factor::exception_handler);
132 }
133
134 void factor_vm::open_console()
135 {
136 }
137
138 }