From 8d7ca096969e6ca4bbc92dd59308b2f17c99e748 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Wed, 8 Jul 2020 20:47:56 +0300 Subject: [PATCH 01/17] Added Windows support on com.oracle.max.vm.native, except Tele (code relies exclusively on existing native Windows Libraries, no dependency required) --- com.oracle.max.vm.native/desktop.ini | 3 + com.oracle.max.vm.native/hosted/platform.c | 18 +- com.oracle.max.vm.native/javatest/javatest.mk | 2 +- com.oracle.max.vm.native/javatest/tests.c | 36 +++- com.oracle.max.vm.native/launch/maxvm.c | 40 +++- com.oracle.max.vm.native/makefile | 2 +- com.oracle.max.vm.native/platform/aarch64.c | 2 +- com.oracle.max.vm.native/platform/aarch64.h | 2 +- com.oracle.max.vm.native/platform/amd64.c | 6 +- com.oracle.max.vm.native/platform/amd64.h | 16 ++ com.oracle.max.vm.native/platform/arm.c | 6 +- com.oracle.max.vm.native/platform/platform.mk | 44 +++- .../platform/usercygwinamd64.h | 45 ++++ com.oracle.max.vm.native/share/c.h | 4 +- com.oracle.max.vm.native/share/condition.c | 33 ++- com.oracle.max.vm.native/share/condition.h | 4 + com.oracle.max.vm.native/share/log.c | 35 +-- com.oracle.max.vm.native/share/mutex.c | 21 +- com.oracle.max.vm.native/share/mutex.h | 3 +- com.oracle.max.vm.native/share/threadLocals.c | 26 ++- com.oracle.max.vm.native/share/threads.h | 7 +- .../share/virtualMemory.c | 154 ++++++++++++-- com.oracle.max.vm.native/substrate/barrier.c | 6 +- com.oracle.max.vm.native/substrate/image.c | 11 +- com.oracle.max.vm.native/substrate/jni.c | 23 +- com.oracle.max.vm.native/substrate/jvm.c | 199 +++++++++++++----- com.oracle.max.vm.native/substrate/jvmti.c | 10 +- com.oracle.max.vm.native/substrate/maxine.c | 116 ++++++++-- com.oracle.max.vm.native/substrate/maxine.h | 2 +- com.oracle.max.vm.native/substrate/memory.c | 6 +- com.oracle.max.vm.native/substrate/signal.c | 37 +++- com.oracle.max.vm.native/substrate/sync.c | 5 +- com.oracle.max.vm.native/substrate/threads.c | 94 ++++++++- com.oracle.max.vm.native/substrate/time.c | 48 ++++- com.oracle.max.vm.native/substrate/trap.c | 74 +++++-- com.oracle.max.vm.native/substrate/trap.h | 14 +- com.oracle.max.vm.native/substrate/vm.h | 4 + 37 files changed, 957 insertions(+), 201 deletions(-) create mode 100644 com.oracle.max.vm.native/desktop.ini create mode 100644 com.oracle.max.vm.native/platform/usercygwinamd64.h diff --git a/com.oracle.max.vm.native/desktop.ini b/com.oracle.max.vm.native/desktop.ini new file mode 100644 index 0000000000..4af9750217 --- /dev/null +++ b/com.oracle.max.vm.native/desktop.ini @@ -0,0 +1,3 @@ +[.ShellClassInfo] +InfoTip=MEGA synced folder +IconResource=C:\Users\mihalis341\AppData\Local\MEGAsync\MEGAsync.exe,3 diff --git a/com.oracle.max.vm.native/hosted/platform.c b/com.oracle.max.vm.native/hosted/platform.c index de3410bb39..b0c02489a3 100644 --- a/com.oracle.max.vm.native/hosted/platform.c +++ b/com.oracle.max.vm.native/hosted/platform.c @@ -18,12 +18,21 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if !os_WINDOWS #include +#else + #include + #include +#endif #include "word.h" #include "isa.h" #include "jni.h" #include #include +#include + + JNIEXPORT void JNICALL JVM_OnLoad(JavaVM *vm, char *options, void *arg) @@ -54,7 +63,14 @@ Java_com_sun_max_platform_Platform_nativeGetOS(JNIEnv *env, jclass c) JNIEXPORT jint JNICALL Java_com_sun_max_platform_Platform_nativeGetPageSize(JNIEnv *env, jclass c) { - return (jint) sysconf(_SC_PAGESIZE); + #if os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + return systemInfo.dwPageSize ; + + #else + return (jint) sysconf(_SC_PAGESIZE); + #endif } diff --git a/com.oracle.max.vm.native/javatest/javatest.mk b/com.oracle.max.vm.native/javatest/javatest.mk index 6a76e4ed70..7a92b47a1a 100644 --- a/com.oracle.max.vm.native/javatest/javatest.mk +++ b/com.oracle.max.vm.native/javatest/javatest.mk @@ -27,7 +27,7 @@ LIB = javatest include $(PROJECT)/platform/platform.mk -SOURCES = jvmni.c tests.c threads.c jnitests.c +SOURCES = jvmni.c tests.c threads.c jnitests.c jvm.c jni.c threadLocals.c image.c log.c virtualMemory.c mutex.c c.c trap.c time.c jmm.c jvmti.c relocation.c signal.c dataio.c SOURCE_DIRS = javatest jni platform hosted share substrate diff --git a/com.oracle.max.vm.native/javatest/tests.c b/com.oracle.max.vm.native/javatest/tests.c index 94c9cb4f4b..f700cd6dac 100644 --- a/com.oracle.max.vm.native/javatest/tests.c +++ b/com.oracle.max.vm.native/javatest/tests.c @@ -24,8 +24,11 @@ * JNI code for any of the JavaTester tests that use native methods. */ #include "os.h" - +#if !os_WINDOWS #include +#else + #include +#endif #include "jni.h" JNIEXPORT void JNICALL @@ -96,23 +99,42 @@ void upcall(jclass cls) { (*env)->DeleteGlobalRef(env, cls); (*vm)->DetachCurrentThread(vm); } - +#if os_WINDOWS +DWORD WINAPI thread_function(void *arguments) {//we prefer this signature in order to avoid compiler waring on Windows. +#else void *thread_function(void *arguments) { +#endif upcall((jclass) arguments); - return NULL; + #if os_WINDOWS + return 0; + #else + return NULL; + #endif } JNIEXPORT void JNICALL Java_test_output_AttachThread_callHelloWorldOnAttachedThread(JNIEnv *env, jclass clazz) { - pthread_t thread_id; - pthread_attr_t attributes; - + #if !os_WINDOWS + pthread_t thread_id; + pthread_attr_t attributes; + + #endif /* Convert argument to be a global handle as it is going to the new thread */ clazz = (*env)->NewGlobalRef(env, clazz); - void *arguments = clazz; + #if os_WINDOWS + LPVOID + #else + void * + #endif + arguments = clazz; + #if !os_WINDOWS pthread_attr_init(&attributes); pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE); pthread_create(&thread_id, &attributes, thread_function, arguments); pthread_attr_destroy(&attributes); + #else + CreateThread(NULL, 0, thread_function, arguments, 0, NULL); + + #endif } diff --git a/com.oracle.max.vm.native/launch/maxvm.c b/com.oracle.max.vm.native/launch/maxvm.c index 1c45914fff..214a12a67e 100644 --- a/com.oracle.max.vm.native/launch/maxvm.c +++ b/com.oracle.max.vm.native/launch/maxvm.c @@ -18,13 +18,19 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + #include "os.h" +#if os_WINDOWS +#include +char last_dl_error [100]; //emulating dlerror() function not available on Windows + +#else #include +#endif #include #include #include #include -#include "os.h" #include "maxine.h" typedef int (*MaxineFunction)(int argc, char *argv[], char *executablePath); @@ -58,6 +64,15 @@ typedef int (*MaxineFunction)(int argc, char *argv[], char *executablePath); #include const CFNullRef initializeCoreFoundationOnMainThread; +#elif os_WINDOWS +#define LIBRARY_NAME "jvm.dll" +#define MAIN_EXTRA_ARGS +#define PROG_PATH argv[0] +char *dlerror(){ + + + return last_dl_error; +} #else #define LIBRARY_NAME "libjvm.so" #define MAIN_EXTRA_ARGS @@ -108,23 +123,42 @@ int main(int argc, char *argv[] MAIN_EXTRA_ARGS) { strncpy(libraryPath, programPath, prefixLength); strcpy(libraryPath + prefixLength, LIBRARY_NAME); #endif + #if os_WINDOWS + void *result = LoadLibraryA(libraryPath); + if (result==NULL) { + sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); + fprintf(stderr, "could not load %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); + exit(1); + + } + MaxineFunction maxine = (MaxineFunction) GetProcAddress(result, "maxine"); + if (maxine == 0) { + sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); + fprintf(stderr, "could not find symbol 'maxine' in %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); + exit(1); + } + + return (*maxine)(argc, argv, NULL); + #else void *handle = dlopen(libraryPath, RTLD_LAZY | RTLD_GLOBAL); if (handle == 0) { - fprintf(stderr, "could not load %s: %s\n", LIBRARY_NAME, dlerror()); + fprintf(stderr, "could not load %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); exit(1); } MaxineFunction maxine = (MaxineFunction) dlsym(handle, "maxine"); if (maxine == 0) { - fprintf(stderr, "could not find symbol 'maxine' in %s: %s\n", LIBRARY_NAME, dlerror()); + fprintf(stderr, "could not find symbol 'maxine' in %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); exit(1); } + #endif #if os_DARWIN return (*maxine)(argc, argv, programPath); #else free(libraryPath); + return (*maxine)(argc, argv, NULL); #endif } diff --git a/com.oracle.max.vm.native/makefile b/com.oracle.max.vm.native/makefile index cab187f58c..e5c253f008 100644 --- a/com.oracle.max.vm.native/makefile +++ b/com.oracle.max.vm.native/makefile @@ -28,7 +28,7 @@ include platform/platform.mk -all : hosted substrate launch tele javatest +all : hosted substrate launch javatest tele hosted : build/$(OS)/hosted/makefile $(AT) (cd build/$(OS)/hosted; $(MAKE) all) diff --git a/com.oracle.max.vm.native/platform/aarch64.c b/com.oracle.max.vm.native/platform/aarch64.c index 3b946e3ff8..b8ca765cf4 100644 --- a/com.oracle.max.vm.native/platform/aarch64.c +++ b/com.oracle.max.vm.native/platform/aarch64.c @@ -23,7 +23,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_CanonicalIntegerRegisters c) { -#if os_LINUX +#if os_LINUX || os_WINDOWS #define CANONICALIZE(reg) c->r##reg = (Word) os->regs[reg] #else #define CANONICALIZE(reg, ucReg) c_UNIMPLEMENTED() diff --git a/com.oracle.max.vm.native/platform/aarch64.h b/com.oracle.max.vm.native/platform/aarch64.h index 75303f0b13..5efd40fd8d 100644 --- a/com.oracle.max.vm.native/platform/aarch64.h +++ b/com.oracle.max.vm.native/platform/aarch64.h @@ -23,7 +23,7 @@ #include "word.h" -#if os_LINUX +#if (os_LINUX || os_WINDOWS) # include # include typedef struct user_regs_struct *aarch64_OsTeleIntegerRegisters; diff --git a/com.oracle.max.vm.native/platform/amd64.c b/com.oracle.max.vm.native/platform/amd64.c index 5db518c005..df6edd7508 100644 --- a/com.oracle.max.vm.native/platform/amd64.c +++ b/com.oracle.max.vm.native/platform/amd64.c @@ -27,7 +27,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can #if os_DARWIN #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->__##reg -#elif os_LINUX || os_MAXVE +#elif os_LINUX || os_MAXVE || os_WINDOWS #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->reg #elif os_SOLARIS #define CANONICALIZE(reg, ucReg) c->reg = (Word) os[REG_##ucReg] @@ -58,7 +58,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can void isa_canonicalizeTeleFloatingPointRegisters(isa_OsTeleFloatingPointRegisters os, isa_CanonicalFloatingPointRegisters c) { #if os_DARWIN #define CANONICALIZE(reg) c->xmm##reg = (*((Word *) (&os->__fpu_xmm##reg))) -#elif os_LINUX +#elif os_LINUX || os_WINDOWS #define CANONICALIZE(reg) c->xmm##reg = (Word) ((XMMRegister *) &os->xmm_space)[reg].low #elif os_SOLARIS #define CANONICALIZE(reg) c->xmm##reg = (Word) *((Word *) &os->fp_reg_set.fpchip_state.xmm[reg]) @@ -92,7 +92,7 @@ void isa_canonicalizeTeleStateRegisters(isa_OsTeleStateRegisters os, isa_Canonic #if os_DARWIN c->rip = (Word) os->__rip; c->flags = (Word) os->__rflags; -#elif os_LINUX +#elif os_LINUX || os_WINDOWS c->rip = (Word) os->rip; c->flags = (Word) os->eflags; #elif os_SOLARIS diff --git a/com.oracle.max.vm.native/platform/amd64.h b/com.oracle.max.vm.native/platform/amd64.h index 25f1015604..731be34164 100644 --- a/com.oracle.max.vm.native/platform/amd64.h +++ b/com.oracle.max.vm.native/platform/amd64.h @@ -40,6 +40,16 @@ Word low; Word high; } XMMRegister; +#elif os_WINDOWS +//# include +# include "usercygwinamd64.h" + typedef struct user_regs_struct *amd64_OsTeleIntegerRegisters; + typedef struct user_fpregs_struct *amd64_OsTeleFloatingPointRegisters; + typedef struct user_regs_struct *amd64_OsTeleStateRegisters; + typedef struct { + Word low; + Word high; + } XMMRegister; #elif os_SOLARIS # include typedef prgreg_t *amd64_OsTeleIntegerRegisters; @@ -47,6 +57,12 @@ typedef prgreg_t *amd64_OsTeleStateRegisters; #elif os_MAXVE # include +# include + typedef struct db_regs* amd64_OsTeleIntegerRegisters; + typedef struct db_regs* amd64_OsTeleStateRegisters; + typedef struct db_regs* amd64_OsTeleFloatingPointRegisters; +#elif os_WINDOWS +# include # include typedef struct db_regs* amd64_OsTeleIntegerRegisters; typedef struct db_regs* amd64_OsTeleStateRegisters; diff --git a/com.oracle.max.vm.native/platform/arm.c b/com.oracle.max.vm.native/platform/arm.c index 6b73ec0f9d..8ca37e79bc 100644 --- a/com.oracle.max.vm.native/platform/arm.c +++ b/com.oracle.max.vm.native/platform/arm.c @@ -25,7 +25,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can #if os_DARWIN #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->__##reg -#elif os_LINUX || os_MAXVE +#elif os_LINUX || os_MAXVE || os_WINDOWS #ifdef __arm__ #define CANONICALIZE(reg, intpos) c->reg = (Word) os->uregs[intpos] #else @@ -79,7 +79,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can void isa_canonicalizeTeleFloatingPointRegisters(isa_OsTeleFloatingPointRegisters os, isa_CanonicalFloatingPointRegisters c) { #if os_DARWIN #define CANONICALIZE(reg) c->xmm##reg = (*((Word *) (&os->__fpu_xmm##reg))) -#elif os_LINUX +#elif os_LINUX || os_WINDOWS #define CANONICALIZE(reg) c->xmm##reg = (Word) ((XMMRegister *) &os->xmm_space)[reg].low #elif os_SOLARIS #define CANONICALIZE(reg) c->xmm##reg = (Word) *((Word *) &os->fp_reg_set.fpchip_state.xmm[reg]) @@ -116,7 +116,7 @@ void isa_canonicalizeTeleStateRegisters(isa_OsTeleStateRegisters os, isa_Canonic #if os_DARWIN c->rip = (Word) os->__rip; c->flags = (Word) os->__rflags; -#elif os_LINUX +#elif os_LINUX || os_WINDOWS #ifdef __arm__ log_println("ARM: isa_canonicalizeTeleStateRegisters is not implemented!"); #else diff --git a/com.oracle.max.vm.native/platform/platform.mk b/com.oracle.max.vm.native/platform/platform.mk index 69221735ef..fe15588ab0 100644 --- a/com.oracle.max.vm.native/platform/platform.mk +++ b/com.oracle.max.vm.native/platform/platform.mk @@ -22,6 +22,7 @@ # # Print verbose output only when MX_VERBOSE is set to y (i.e. mx -V command is used) + ifneq ($(MX_VERBOSE), y) AT := @ MAKE := $(MAKE) -s @@ -54,6 +55,8 @@ ifneq ($(MAIN),) TARGET := LAUNCH endif +OS := windows +ISA := amd64 # HOSTOS is the platform we are compiling on HOSTOS = $(shell uname -s) # TARGETOS is the platform we are compiling for (usually the same as HOSTOS) @@ -151,9 +154,9 @@ ifeq ($(TARGETOS),SunOS) endif endif -ifeq ($(findstring CYGWIN,$(TARGETOS)),CYGWIN) +ifeq ($(TARGETOS),WindowsNT) OS := windows - ISA := ia32 + ISA := amd64 endif # There are three variants for Maxine VE, owing to the 32/64 dom0 variants @@ -310,20 +313,33 @@ ifeq ($(OS),solaris) endif ifeq ($(OS),windows) - # determine predefined macros: touch foo.c; gcc -E -dD foo.c ifneq "$(findstring def, $(origin CC))" "" # origin of CC is either undefined or default, so set it here CC = gcc endif ifneq "$(findstring def, $(origin CFLAGS))" "" # origin of CFLAGS is either undefined or default, so set it here - CFLAGS = -g -ansi -Wall -pedantic -Wno-long-long -mno-cygwin -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) + CFLAGS = -g -Wall -Wno-long-long -Wextra -Wno-main -Wno-unused-parameter -fPIC -D_GNU_SOURCE -D$(ISA) -DWINDOWS -D__int64=int64_t -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) $(OTHER_CFLAGS) endif - C_DEPENDENCIES_FLAGS = -MM -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) - LINK_MAIN = $(CC) -g -mno-cygwin -Wall -W1,----add-stdcall-alias -ldl - LINK_LIB = $(CC) -g -shared -mno-cygwin -Wall -W1,----add-stdcall-alias + C_DEPENDENCIES_FLAGS = -M -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) + # The '-rpath' linker option is used so that LD_LIBRARY_PATH does not have to be configured at runtime to + # find Maxine's version of the libjvm.so library. + # The '-z execstack' is a workaround that stops the runtime dynamic linker from + # changing the protection of the main thread's stack (via mprotect) *after* the + # yellow guard page (for detecting stack overflow) has been mprotected. Without + # this flag, the main thread's complete stack (including the guard page) is + # mprotected with PROT_READ, PROT_WRITE, PROT_EXEC when dlopen() is called to + # open libjava.so. + LINK_MAIN = $(CC) -g -Xlinker -rpath -Xlinker $(shell cd $(PROJECT)/generated/$(OS) && /bin/pwd) -o $(MAIN) + + LINK_LIB = $(CC) -g -shared -mwindows + LINK_LIB_POSTFIX += -lole32 -lws2_32 + + + LIB_PREFIX = - LIB_SUFFIX = .dll + LIB_SUFFIX = .dll + endif ifeq ($(OS),maxve) @@ -413,9 +429,15 @@ else endif JNI_INCLUDES = -I $(dir $(JNI_H_PATH)) endif - else - JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) - JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) + else + ifeq ($(OS),windows) + JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/win32/ + JNI_H_PATH = $(JAVA_HOME)/include/win32/jni.h + else + JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) + JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) + endif + endif endif diff --git a/com.oracle.max.vm.native/platform/usercygwinamd64.h b/com.oracle.max.vm.native/platform/usercygwinamd64.h new file mode 100644 index 0000000000..e1a4c0d496 --- /dev/null +++ b/com.oracle.max.vm.native/platform/usercygwinamd64.h @@ -0,0 +1,45 @@ +struct user_fpregs_struct +{ + unsigned short int cwd; + unsigned short int swd; + unsigned short int ftw; + unsigned short int fop; + __extension__ unsigned long long int rip; + __extension__ unsigned long long int rdp; + unsigned int mxcsr; + unsigned int mxcr_mask; + unsigned int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ + unsigned int padding[24]; +}; + +struct user_regs_struct +{ + __extension__ unsigned long long int r15; + __extension__ unsigned long long int r14; + __extension__ unsigned long long int r13; + __extension__ unsigned long long int r12; + __extension__ unsigned long long int rbp; + __extension__ unsigned long long int rbx; + __extension__ unsigned long long int r11; + __extension__ unsigned long long int r10; + __extension__ unsigned long long int r9; + __extension__ unsigned long long int r8; + __extension__ unsigned long long int rax; + __extension__ unsigned long long int rcx; + __extension__ unsigned long long int rdx; + __extension__ unsigned long long int rsi; + __extension__ unsigned long long int rdi; + __extension__ unsigned long long int orig_rax; + __extension__ unsigned long long int rip; + __extension__ unsigned long long int cs; + __extension__ unsigned long long int eflags; + __extension__ unsigned long long int rsp; + __extension__ unsigned long long int ss; + __extension__ unsigned long long int fs_base; + __extension__ unsigned long long int gs_base; + __extension__ unsigned long long int ds; + __extension__ unsigned long long int es; + __extension__ unsigned long long int fs; + __extension__ unsigned long long int gs; +}; diff --git a/com.oracle.max.vm.native/share/c.h b/com.oracle.max.vm.native/share/c.h index c4add88ca4..ed33c77f61 100644 --- a/com.oracle.max.vm.native/share/c.h +++ b/com.oracle.max.vm.native/share/c.h @@ -53,10 +53,12 @@ typedef long long Signed8; typedef float Float4; typedef double Float8; +#define true 1 +#define false 0 #if !defined(false) && !defined(true) typedef enum {false, true} boolean; #else - typedef int boolean; + typedef unsigned char boolean; #endif #define MAX_PATH_LENGTH 2048 diff --git a/com.oracle.max.vm.native/share/condition.c b/com.oracle.max.vm.native/share/condition.c index 90e052fcfe..b8b8feac0c 100644 --- a/com.oracle.max.vm.native/share/condition.c +++ b/com.oracle.max.vm.native/share/condition.c @@ -18,6 +18,15 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if os_WINDOWS +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 // needed for tools like MINGW in order to use condition variables which became available from Windows Vista and on. Visual Studio might define it on its own +#include + +#endif #include #include #include @@ -45,6 +54,10 @@ void condition_initialize(Condition condition) { } #elif os_MAXVE *condition = maxve_condition_create(); +#elif os_WINDOWS + InitializeConditionVariable(condition); + //initialize condtionVariable does not return anything! + #else # error #endif @@ -62,6 +75,8 @@ void condition_destroy(Condition condition) { if (pthread_cond_destroy(condition) != 0) { c_FATAL(); } +#elif os_WINDOWS +//condition variables cannot get destroyed https://stackoverflow.com/questions/28975958/why-does-windows-have-no-deleteconditionvariable-function-to-go-together-with #endif } @@ -80,7 +95,7 @@ void condition_destroy(Condition condition) { * @return false if an error occurred, true otherwise (i.e. the thread was notified or interrupted). * In either case, the current thread has reacquired the lock on 'mutex'. */ -boolean condition_wait(Condition condition, Mutex mutex) { +boolean condition_wait(Condition condition, Mutex mutex) { //mutex is not needed in windows #if log_MONITORS log_println("condition_wait (" THREAD_CONDVAR_MUTEX_FORMAT ")", thread_self(), condition, mutex); #endif @@ -101,6 +116,8 @@ boolean condition_wait(Condition condition, Mutex mutex) { /* (Doug) I assume 1 means EINTR */ return true; } +#elif os_WINDOWS + error = !SleepConditionVariableCS (condition, mutex, INFINITE); // non zero return value means success on Windows! #endif if (error != 0) { log_println("condition_wait (" THREAD_CONDVAR_MUTEX_FORMAT ") unexpected error code %d [%s]", thread_self(), condition, mutex, error, strerror(error)); @@ -112,7 +129,7 @@ boolean condition_wait(Condition condition, Mutex mutex) { return true; } -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) /* * This function is taken from HotSpot (os_linux.cpp). */ @@ -159,7 +176,7 @@ boolean condition_timedWait(Condition condition, Mutex mutex, Unsigned8 timeoutM log_println("condition_timedWait (" THREAD_CONDVAR_MUTEX_FORMAT ", %d)", thread_self(), condition, mutex, timeoutMilliSeconds); #endif int error; -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) struct timeval now; int status = gettimeofday(&now, NULL); c_ASSERT(status != -1); @@ -198,6 +215,8 @@ boolean condition_timedWait(Condition condition, Mutex mutex, Unsigned8 timeoutM /* (Doug) I assume 1 means EINTR */ return true; } +#elif os_WINDOWS + error = !SleepConditionVariableCS (condition, mutex, timeoutMilliSeconds); // non zero return value means success on Windows! #else # error #endif @@ -222,6 +241,9 @@ boolean condition_notify(Condition condition) { return cond_signal(condition) == 0; #elif os_MAXVE return maxve_condition_notify(*condition, 0) == 0; +#elif os_WINDOWS + WakeConditionVariable (condition); //WakeConditionVariable returns nothing + return true; #else # error #endif @@ -231,12 +253,15 @@ boolean condition_notifyAll(Condition condition) { #if log_MONITORS log_println("condition_notifyAll (" THREAD_CONDVAR_FORMAT ")", thread_self(), condition); #endif -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) return pthread_cond_broadcast(condition) == 0; #elif os_SOLARIS return cond_broadcast(condition) == 0; #elif os_MAXVE return maxve_condition_notify(*condition, 1) == 0; +#elif os_WINDOWS + WakeAllConditionVariable (condition); //WakeAllConditionVariable returns nothing + return true; #else # error #endif diff --git a/com.oracle.max.vm.native/share/condition.h b/com.oracle.max.vm.native/share/condition.h index 93c379f5ca..953fa41c4b 100644 --- a/com.oracle.max.vm.native/share/condition.h +++ b/com.oracle.max.vm.native/share/condition.h @@ -36,6 +36,10 @@ #elif os_MAXVE # include "maxve.h" typedef maxve_condition_t condition_Struct; +#elif os_WINDOWS + typedef CONDITION_VARIABLE condition_Struct; + + #endif typedef condition_Struct *Condition; diff --git a/com.oracle.max.vm.native/share/log.c b/com.oracle.max.vm.native/share/log.c index a5bedc320a..5e5a04a828 100644 --- a/com.oracle.max.vm.native/share/log.c +++ b/com.oracle.max.vm.native/share/log.c @@ -18,17 +18,28 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + + #include #include #include #include -#include #include "log.h" +#if os_WINDOWS +#include +#define pthread_self GetCurrentThread +#else +#include + +#endif + #include "jni.h" #include "mutex.h" #include "threads.h" + + #if !os_MAXVE static FILE *fileStream = NULL; #endif @@ -46,14 +57,14 @@ static mutex_Struct allocationProfiler_mutexStruct; void log_initialize(const char *path) { mutex_initialize(&log_mutexStruct); mutex_initialize(&allocationProfiler_mutexStruct); -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS if (path == NULL) { path = "stdout"; } if (strncmp(path, "stdout\0", 7) == 0) { fileStream = stdout; /* Set the file stream to flush whenever a newline character is encountered */ - setlinebuf(fileStream); + // setlinebuf(fileStream); } else if (strncmp(path, "stderr\0", 7) == 0) { fileStream = stderr; } else { @@ -63,7 +74,7 @@ void log_initialize(const char *path) { exit(1); } /* Set the file stream to flush whenever a newline character is encountered */ - setlinebuf(fileStream); + // setlinebuf(fileStream); } #endif } @@ -71,7 +82,7 @@ void log_initialize(const char *path) { void log_lock(void) { int result; if ((result = mutex_enter_nolog(&log_mutexStruct)) != 0) { - log_exit(-1, "Thread %p could not lock mutex %p: %s", thread_self(), &log_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not lock mutex %p: %s", pthread_self(), &log_mutexStruct, strerror(result)); } } @@ -79,14 +90,14 @@ void numaProfiler_lock(void) { int result; result = mutex_enter_nolog(&allocationProfiler_mutexStruct); if (result != 0) { - log_exit(-1, "Thread %p could not lock mutex %p: %s", thread_self(), &allocationProfiler_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not lock mutex %p: %s", pthread_self(), &allocationProfiler_mutexStruct, strerror(result)); } } void log_unlock(void) { int result; if ((result = mutex_exit_nolog(&log_mutexStruct)) != 0) { - log_exit(-1, "Thread %p could not unlock mutex %p: %s", thread_self(), &log_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not unlock mutex %p: %s", pthread_self(), &log_mutexStruct, strerror(result)); } } @@ -94,7 +105,7 @@ void numaProfiler_unlock(void) { int result; result = mutex_exit_nolog(&allocationProfiler_mutexStruct); if (result != 0) { - log_exit(-1, "Thread %p could not unlock mutex %p: %s", thread_self(), &allocationProfiler_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not unlock mutex %p: %s", pthread_self(), &allocationProfiler_mutexStruct, strerror(result)); } } @@ -111,14 +122,14 @@ void log_print_format(const char *format, ...) { } void log_flush() { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS FILE* out = fileStream == NULL ? stdout : fileStream; fflush(out); #endif } void log_print_vformat(const char *format, va_list ap) { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS FILE* out = fileStream == NULL ? stdout : fileStream; vfprintf(out, format, ap); #else @@ -197,8 +208,8 @@ void log_print_newline() { } void log_print_symbol(Address address) { -#if !os_MAXVE - Dl_info info; +#if !os_MAXVE && !os_WINDOWS + Dl_info info; if (dladdr((void *) address, &info) != 0) { if (info.dli_sname == NULL) { log_print("%s (%p+%d)", info.dli_fname, info.dli_fbase, address - (Address) info.dli_fbase); diff --git a/com.oracle.max.vm.native/share/mutex.c b/com.oracle.max.vm.native/share/mutex.c index 4902d146fc..3ed0431939 100644 --- a/com.oracle.max.vm.native/share/mutex.c +++ b/com.oracle.max.vm.native/share/mutex.c @@ -20,6 +20,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +#include "os.h" +#if os_WINDOWS +#include +#endif + #include "mutex.h" #include "log.h" #include "threads.h" @@ -50,6 +55,8 @@ void mutex_initialize(Mutex mutex) { } #elif os_MAXVE *mutex = maxve_monitor_create(); +#elif os_WINDOWS + InitializeCriticalSection(mutex); //windows CS's are recursive be default ,mutex is pointer to Critical section # else c_UNIMPLEMENTED(); # endif @@ -65,6 +72,9 @@ int mutex_enter_nolog(Mutex mutex) { c_ASSERT(false); } return 0; +#elif os_WINDOWS + EnterCriticalSection(mutex); //mutex is pointer to Critical section. EnterCriticalSection returns nothing + return 0; //0 means success for funcs like pthread_mutex_lock #else c_UNIMPLEMENTED(); #endif @@ -73,8 +83,11 @@ int mutex_enter_nolog(Mutex mutex) { int mutex_try_enter(Mutex mutex) { #if os_SOLARIS return mutex_trylock(mutex); -#elif os_LINUX || os_DARWIN +#elif os_LINUX || os_DARWIN return pthread_mutex_trylock(mutex); +#elif os_WINDOWS + return !TryEnterCriticalSection(mutex); //mutex is pointer to Critical section. On windows non zero return value means success that's why we use ! at the result + #else c_UNIMPLEMENTED(); #endif @@ -98,6 +111,9 @@ int mutex_exit_nolog(Mutex mutex) { c_ASSERT(false); } return 0; +#elif os_WINDOWS + LeaveCriticalSection(mutex); //mutex is pointer to Critical section + return 0; #else c_UNIMPLEMENTED(); #endif @@ -124,5 +140,8 @@ void mutex_dispose(Mutex mutex) { } #elif os_MAXVE c_UNIMPLEMENTED(); +#elif os_WINDOWS + DeleteCriticalSection(mutex); //mutex is pointer to Critical section + #endif } diff --git a/com.oracle.max.vm.native/share/mutex.h b/com.oracle.max.vm.native/share/mutex.h index 962941271a..68ebec04de 100644 --- a/com.oracle.max.vm.native/share/mutex.h +++ b/com.oracle.max.vm.native/share/mutex.h @@ -35,8 +35,9 @@ #elif os_MAXVE # include typedef maxve_monitor_t mutex_Struct; +#elif os_WINDOWS +typedef CRITICAL_SECTION mutex_Struct; #endif - typedef mutex_Struct *Mutex; extern void mutex_initialize(Mutex mutex); diff --git a/com.oracle.max.vm.native/share/threadLocals.c b/com.oracle.max.vm.native/share/threadLocals.c index 5868340538..11b7a7ea24 100644 --- a/com.oracle.max.vm.native/share/threadLocals.c +++ b/com.oracle.max.vm.native/share/threadLocals.c @@ -18,7 +18,14 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include + #include "os.h" +#if !os_WINDOWS + #include +#else + #include + #include + #define aligned_alloc(a, b) _aligned_malloc(a, b) +#endif #include #include @@ -48,6 +55,9 @@ typedef maxve_Thread Thread; typedef maxve_SpecificsKey ThreadLocalsKey; typedef void (*ThreadLocalsBlockDestructor)(void *); +#elif os_WINDOWS + typedef DWORD ThreadLocalsKey; + #endif int theTLASize = -1; @@ -86,7 +96,7 @@ static void deallocateThreadLocalBlock(Address tlBlock, Size tlBlockSize) { * lazily commit memory reserved for the initial thread's stack. */ static void commitStackMemoryForInitialThread(Address base, int pageSize) { -#if os_LINUX +#if os_LINUX || os_WINDOWS /* Writing to the bottom page of the reserved stack (appears) not to be * sufficient on Linux. Using alloca() to allocate a chunk approximately * the size of the remaining stack seems to fix it. */ @@ -347,7 +357,7 @@ void threadLocalsBlock_destroy(Address tlBlock) { void tla_initialize(int tlaSize) { theTLASize = tlaSize; #if !TELE -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX int error = pthread_key_create(&theThreadLocalsKey, (ThreadLocalsBlockDestructor)(void *) threadLocalsBlock_destroy); #if log_THREADS log_println("tla_initialize: pthread_key_create returned code = %d", error); @@ -355,6 +365,8 @@ void tla_initialize(int tlaSize) { if (error != 0) { log_exit(-1, "tla_initialize: pthread_key_create returned non zero code = %d", error); } +#elif os_WINDOWS + theThreadLocalsKey = TlsAlloc(); #elif os_SOLARIS thr_keycreate(&theThreadLocalsKey, (ThreadLocalsBlockDestructor) threadLocalsBlock_destroy); #elif os_MAXVE @@ -368,7 +380,7 @@ void tla_initialize(int tlaSize) { Address threadLocalsBlock_current() { Address tlBlock; -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX tlBlock = (Address) pthread_getspecific(theThreadLocalsKey); #elif os_SOLARIS Address value; @@ -379,6 +391,8 @@ Address threadLocalsBlock_current() { tlBlock = value; #elif os_MAXVE tlBlock = (Address) maxve_thread_getSpecific(theThreadLocalsKey); +#elif os_WINDOWS + tlBlock = (Address) TlsGetValue(theThreadLocalsKey); #else c_UNIMPLEMENTED(); #endif @@ -386,12 +400,14 @@ Address threadLocalsBlock_current() { } void threadLocalsBlock_setCurrent(Address tlBlock) { -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) pthread_setspecific(theThreadLocalsKey, (void *) tlBlock); #elif os_SOLARIS thr_setspecific(theThreadLocalsKey, (void *) tlBlock); #elif os_MAXVE maxve_thread_setSpecific(theThreadLocalsKey, (void *) tlBlock); +#elif os_WINDOWS + TlsSetValue(theThreadLocalsKey, (LPVOID) tlBlock); #endif } diff --git a/com.oracle.max.vm.native/share/threads.h b/com.oracle.max.vm.native/share/threads.h index f360882742..63b48db454 100644 --- a/com.oracle.max.vm.native/share/threads.h +++ b/com.oracle.max.vm.native/share/threads.h @@ -80,8 +80,13 @@ typedef void (*VmThreadDetachMethod)(Address tla); * @return true if the sleep was interrupted */ extern jboolean thread_sleep(jlong numberOfMilliSeconds); +#if os_WINDOWS +DWORD WINAPI thread_run(LPVOID param); +#else + +void * thread_run(void *arg); -void *thread_run(void *arg); +#endif int thread_attachCurrent(void **penv, JavaVMAttachArgs* args, boolean daemon); int thread_detachCurrent(); diff --git a/com.oracle.max.vm.native/share/virtualMemory.c b/com.oracle.max.vm.native/share/virtualMemory.c index 1846d69f03..5ef4152e04 100644 --- a/com.oracle.max.vm.native/share/virtualMemory.c +++ b/com.oracle.max.vm.native/share/virtualMemory.c @@ -18,18 +18,28 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + + #include "virtualMemory.h" #include "log.h" + #if defined(MAXVE) -#include + #include /* No mmap function on MaxVE (yet)*/ #else -#include -#include -#include -#include - + #include + #include + #include + #if !os_WINDOWS + #include + #else + #ifdef _WIN32_WINNT + #undef _WIN32_WINNT + #endif + #define _WIN32_WINNT 0x0601 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. + #include + #endif #include "jni.h" #include "unistd.h" @@ -39,7 +49,7 @@ #endif /* There is a problem binding these identifiers in RedHat's include files, so we fake them: */ -#if os_LINUX +#if os_LINUX || os_WINDOWS # ifndef MAP_ANONYMOUS # define MAP_ANONYMOUS 0x20 # endif @@ -58,11 +68,16 @@ # define MAP_32BIT 0 # endif #endif - +#if !os_WINDOWS #define PROT (PROT_EXEC | PROT_READ | PROT_WRITE) +#endif + +#if !os_WINDOWS //we do not use mmap on Windows so this function is not needed. /* mmap returns MAP_FAILED on error, we convert to ALLOC_FAILED */ static Address check_mmap_result(void *result) { + + #if log_MMAP if(result == MAP_FAILED) { switch(errno) { @@ -99,8 +114,11 @@ static Address check_mmap_result(void *result) { } } #endif + return ((Address) (result == (void *) MAP_FAILED ? ALLOC_FAILED : result)); } +#endif + #ifdef arm static int attempt = 0; @@ -125,8 +143,36 @@ Address virtualMemory_allocatePrivateAnon(Address address, Size size, jboolean r address = allocAddress; } #endif +#if os_WINDOWS + //Windows got no Swap space, so jboolean reserveSwap is redundant + Address result; + if(protNone == JNI_TRUE){ + + result = (Address) VirtualAlloc( (void *) address, size, MEM_COMMIT | MEM_RESERVE| PAGE_WRITECOPY, PAGE_NOACCESS); + + //virtualalloc is the only win32 function that supports the PROT_NONE equivalent PAGE_NOACCESS + //PAGE_WRITECOPY is equivalent to MAP_PRIVATE + if(!result) + log_println("%d\n", GetLastError()); + } + else { + //if protnone is not used, we can use CreateFileMappingA + MapViewOfFile combination to emulate mmap() on Windows + //INVALID_HANDLE_VALUE means that we dont use an actual file but the system pagefile, similar to fd= -1 & MPI_ANON in mmap() + HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + //FILE_MAP_COPY is equivalent to MAP_PRIVATE +if(!fmapping) + log_println("%d\n", GetLastError()); + result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, 0, 0, size, (LPVOID)address); + if(!result) + log_println("%d\n", GetLastError()); + + + } + return result; + +#else int flags = MAP_PRIVATE | MAP_ANON; -#if os_LINUX +#if os_LINUX /* For some reason, subsequent calls to mmap to allocate out of the space * reserved here only work if the reserved space is in 32-bit space. */ #endif @@ -153,6 +199,7 @@ Address virtualMemory_allocatePrivateAnon(Address address, Size size, jboolean r #else return check_mmap_result(result); #endif +#endif } @@ -172,6 +219,15 @@ Address virtualMemory_mapFile(Size size, jint fd, Size offset) { address = check_mmap_result(result); allocAddress = address + size; return address; +#elif os_WINDOWS + HANDLE fmapping = CreateFileMappingA( (HANDLE)_get_osfhandle(fd) , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA + Address result = (Address) MapViewOfFile (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size); + //FILE_MAP_COPY is equivalent to mmap's MAP_PRIVATE. It maps a copy-on-write view of the file that is private to the process. + //MapViewOfFile needs lower and high order of offset (last and first 32 bits). We get high and lower orders of the offset (which might be 64bit long) by doing casts to DWORD( 32 BITS) and Binary shifts + if(!result) + log_println("%d\n", GetLastError()); + return result; #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_PRIVATE, fd, (off_t) offset)); #endif @@ -183,7 +239,20 @@ Java_com_sun_max_memory_VirtualMemory_virtualMemory_1mapFile(JNIEnv *env, jclass } Address virtualMemory_mapFileIn31BitSpace(jint size, jint fd, Size offset) { + #if os_WINDOWS //MAP_32BIT is not supported on Windows.... Also in Linux, it is no longer really needed + /*"It was added to allow thread stacks to be + allocated somewhere in the first 2 GB of memory, so as to + improve context-switch performance on some early 64-bit + processors. Modern x86-64 processors no longer have this + performance problem, so use of this flag is not required on + those systems. + + https://man7.org/linux/man-pages/man2/mmap.2.html + */ + return virtualMemory_mapFile(size, fd, offset); + #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_PRIVATE | MAP_32BIT, fd, (off_t) offset)); + #endif } JNIEXPORT jlong JNICALL @@ -192,7 +261,20 @@ Java_com_sun_max_memory_VirtualMemory_virtualMemory_1mapFileIn31BitSpace(JNIEnv } Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, Size offset) { + #if os_WINDOWS + HANDLE fmapping = CreateFileMappingA( (HANDLE)_get_osfhandle(fd) , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,0, NULL); + //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA + if(!fmapping) + log_println("%d\n", GetLastError()); + Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size,(LPVOID) address); + //the only diffrence is that we use MapViewOfFileEx instead MapViewOfFile. The first one allows us to provide an initial base address where the mapping begins (last argument) + + if(!result) + log_println("%d\n", GetLastError()); + return result; + #else return check_mmap_result(mmap((void *) address, (size_t) size, PROT, MAP_PRIVATE | MAP_FIXED, fd, (off_t) offset)); + #endif } // end of conditional exclusion of mmap stuff not available (or used) on MAXVE @@ -202,14 +284,23 @@ Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, Address virtualMemory_allocate(Size size, int type) { #if os_MAXVE return (Address) maxve_virtualMemory_allocate(size, type); +#elif os_WINDOWS + HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + Address result = (Address) MapViewOfFile (fmapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size); + if(!result) + log_println("%d\n", GetLastError()); + return result; #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)); #endif } Address virtualMemory_allocateIn31BitSpace(Size size, int type) { -#if os_LINUX +#if os_LINUX return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1, (off_t) 0)); + +#elif os_WINDOWS + return virtualMemory_allocate(size, type); //windows do not have equivalent of MAP_32BIT, also obsolete in Linux #elif os_MAXVE return (Address) maxve_virtualMemory_allocateIn31BitSpace(size, type); #else @@ -221,6 +312,17 @@ Address virtualMemory_allocateIn31BitSpace(Size size, int type) { Address virtualMemory_deallocate(Address start, Size size, int type) { #if os_MAXVE return (Address) maxve_virtualMemory_deallocate((void *)start, size, type); +#elif os_WINDOWS + if( UnmapViewOfFile((LPVOID) start) == 0){ // VirtualFree will fail for addresses mapped with MapViewOfFile so we use UnmapViewOfFile first + int result = VirtualFree((LPVOID)start, size, type); //if UnmapViewOfFile failed, we try virtualalloc (the memory might got mapped with VirtualAlloc) + //type can be MEM_RELEASE or whatever the user provides. (It was implemented for MAXVE that way) + if (!result) + return result; + else + return start; + } + else + return start; #else int result = munmap((void *) start, (size_t) size); return result == -1 ? 0 : start; @@ -230,6 +332,13 @@ Address virtualMemory_deallocate(Address start, Size size, int type) { boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int type) { #if os_SOLARIS || os_DARWIN || os_LINUX return check_mmap_result(mmap((void *) address, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, (off_t) 0)) != ALLOC_FAILED; +#elif os_WINDOWS + HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA + Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, 0, 0, size,(LPVOID) address); + if(!result) + log_println("%d\n", GetLastError()); + return result; #elif os_MAXVE return (Address) maxve_virtualMemory_allocateAtFixedAddress((unsigned long)address, size, type) != ALLOC_FAILED; #else @@ -241,11 +350,18 @@ boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int typ void virtualMemory_protectPages(Address address, int count) { /* log_println("--- protected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ c_ASSERT(virtualMemory_pageAlign(address) == address); -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_NONE) != 0) { int error = errno; log_exit(error, "protectPages: mprotect(%p) failed: %s", address, strerror(error)); } +#elif os_WINDOWS + DWORD old; //needed for VirtualProtect + int error = GetLastError(); + if(!VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_NOACCESS, &old)) //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) + log_exit(error, "protectPages: VirtualProtect(%p) failed", address); + + #elif os_MAXVE maxve_virtualMemory_protectPages(address, count); #else @@ -256,11 +372,14 @@ void virtualMemory_protectPages(Address address, int count) { void virtualMemory_unprotectPages(Address address, int count) { /* log_println("--- unprotected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ c_ASSERT(virtualMemory_pageAlign(address) == address); -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_READ| PROT_WRITE) != 0) { int error = errno; log_exit(error, "unprotectPages: mprotect(%p) failed: %s", address, strerror(error)); } +#elif os_WINDOWS + DWORD old; //needed for VirtualProtect + VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_READWRITE, &old); //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) #elif os_MAXVE maxve_virtualMemory_unProtectPages(address, count); #else @@ -276,7 +395,13 @@ unsigned int virtualMemory_getPageSize(void) { return maxve_virtualMemory_pageSize(); #else if (pageSize == 0) { + #if os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + pageSize = systemInfo.dwPageSize ; + #else pageSize = getpagesize(); + #endif } return pageSize; #endif @@ -287,9 +412,12 @@ Size virtualMemory_getPhysicalMemorySize(void) { #if os_MAXVE // TODO return 0; -#elif os_SOLARIS || os_LINUX +#elif os_SOLARIS || os_LINUX Size numPhysicalPages = (Size) sysconf(_SC_PHYS_PAGES); physicalMemory = numPhysicalPages * virtualMemory_getPageSize(); +#elif os_WINDOWS + GetPhysicallyInstalledSystemMemory(&physicalMemory); + return physicalMemory * 1024; //we want bytes #elif os_DARWIN int query[2]; query[0] = CTL_HW; diff --git a/com.oracle.max.vm.native/substrate/barrier.c b/com.oracle.max.vm.native/substrate/barrier.c index 86bb92ad9d..20fbdcd928 100644 --- a/com.oracle.max.vm.native/substrate/barrier.c +++ b/com.oracle.max.vm.native/substrate/barrier.c @@ -1,6 +1,4 @@ /* - * Copyright (c) 2020, APT Group, Department of Computer Science, - * School of Engineering, The University of Manchester. All rights reserved. * Copyright (c) 2019, APT Group, School of Computer Science, * The University of Manchester. All rights reserved. * @@ -40,7 +38,7 @@ /* * Pre-processor override for whether to compile in the membarrier system call. - * Currently only affects Aarch64 and RISCV64. See syscall_membarrier() in this compilation + * Currently only affects Aarch64. See syscall_membarrier() in this compilation * unit. */ #ifndef USE_SYS_MEMBARRIER @@ -64,7 +62,7 @@ static int membarrier_init(void) __attribute__ ((unused)); void syscall_membarrier() { -#if isa_AARCH64 || isa_RISCV64 +#if isa_AARCH64 # if USE_SYS_MEMBARRIER static volatile int barrier_kind = 0; if (!barrier_kind) { diff --git a/com.oracle.max.vm.native/substrate/image.c b/com.oracle.max.vm.native/substrate/image.c index 9825dd7ab9..198ea69f91 100644 --- a/com.oracle.max.vm.native/substrate/image.c +++ b/com.oracle.max.vm.native/substrate/image.c @@ -20,10 +20,13 @@ */ #include "os.h" + #include #include #include +#if !os_WINDOWS #include +#endif #include #include @@ -277,7 +280,7 @@ static void checkTrailer(int fd) { if (trailerStructPtr->identification != theHeader->identification || trailerStructPtr->bootImageFormatVersion != theHeader->bootImageFormatVersion || trailerStructPtr->randomID != theHeader->randomID) { log_println("inconsistent trailer"); #if !MEMORY_IMAGE - offset = lseek(fd, -sizeof(trailerStruct), SEEK_END); + offset = lseek(fd, (long int)-sizeof(trailerStruct), SEEK_END); if (offset != fileSize - (off_t) sizeof(trailerStruct)) { log_exit(1, "could not set trailer position at end of file"); } @@ -304,7 +307,7 @@ static void mapHeapAndCode(int fd) { #endif #if MEMORY_IMAGE theHeap = (Address) &maxvm_image_start + heapOffsetInImage; -#elif os_SOLARIS || os_DARWIN || os_LINUX +#elif os_SOLARIS || os_DARWIN || os_LINUX || os_WINDOWS Address reservedVirtualSpace = (Address) 0; size_t virtualSpaceSize = 1024L * theHeader->reservedVirtualSpaceSize; c_ASSERT(virtualMemory_pageAlign((Size) virtualSpaceSize) == (Size) virtualSpaceSize); @@ -332,7 +335,7 @@ static void mapHeapAndCode(int fd) { log_exit(4, "could not reserve virtual space for boot image"); } } - if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { + if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { //CAUTION on Windows, the Base Address must be a multiple of dwAllocationGranularity else mapping fails (UNTESTED since no image file is availabe) log_exit(4, "could not map boot image"); } if (reservedVirtualSpace) { @@ -419,7 +422,7 @@ void image_load(char *imageFileName) { } #endif - readHeader(fd); + readHeader(fd); checkImage(); readStringInfo(fd); checkTrailer(fd); diff --git a/com.oracle.max.vm.native/substrate/jni.c b/com.oracle.max.vm.native/substrate/jni.c index 871108e597..a18a76141b 100644 --- a/com.oracle.max.vm.native/substrate/jni.c +++ b/com.oracle.max.vm.native/substrate/jni.c @@ -26,7 +26,10 @@ * arguments in such an array. This isolates the implementation of such functions * from the platform/compiler dependent way in which varargs are implemented. */ -#include +#include "os.h" +#if os_WINDOWS +#include +#endif #include #include #include @@ -37,7 +40,9 @@ #include "threads.h" #include "vm.h" - +#if !os_WINDOWS +#include +#endif #ifndef JNI_VERSION_1_6 #error The version of jni.h being included must define the JNI_VERSION_1_6 macro #endif @@ -808,11 +813,15 @@ jint JNICALL jni_GetEnv(JavaVM *javaVM, void **penv, jint version) { return JNI_OK; } } - +#if os_WINDOWS +__declspec( dllimport ) +#endif jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) { return c_UNIMPLEMENTED(); } - +#if os_WINDOWS +__declspec( dllimport ) +#endif jint JNICALL jni_DestroyJavaVM(JavaVM *vm) { return c_UNIMPLEMENTED(); } @@ -829,7 +838,9 @@ jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { return thread_detachCurrent(); } - +#if os_WINDOWS +__declspec( dllimport ) +#endif jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { return c_UNIMPLEMENTED(); } @@ -857,7 +868,7 @@ JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs_Impl(JavaVM **vm, jsize vmBufLen, j return JNI_OK; } -JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm, jsize vmBufLen, jsize *nVMs) { +JNIEXPORT jint JNICALL __imp_JNI_GetCreatedJavaVMs(JavaVM **vm, jsize vmBufLen, jsize *nVMs) { return JNI_GetCreatedJavaVMs_Impl(vm, vmBufLen, nVMs); } diff --git a/com.oracle.max.vm.native/substrate/jvm.c b/com.oracle.max.vm.native/substrate/jvm.c index c2eab15fbc..0fd63eb587 100644 --- a/com.oracle.max.vm.native/substrate/jvm.c +++ b/com.oracle.max.vm.native/substrate/jvm.c @@ -26,40 +26,71 @@ * In cases where we bypass JDK's native libraries (@see com.sun.max.vm.jdk) * we can simply omit unneeded JVM interface functions that would otherwise occur here. */ -#include +#include "os.h" +#if os_WINDOWS +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. +#include +#include +#define lseek64 _lseeki64 +#define open _open +#define close _close //open and close work on mingw but are deprecated in MSVC so we better use _ before the name. (Internally, they call win32 funcs like CreateFile() and are added by Microsoft for POSIX compatibility +#define ftruncate _chsize +#define ioctl(a, b, c) ioctlsocket(a, b, (u_long *) c) +#include +#endif + + + + +#include "vm.h" +#include "log.h" +#include "trap.h" +#include "mutex.h" +#include "threads.h" +#include "maxine.h" +#include "memory.h" + +#if !os_WINDOWS + #include #include #include -#include -#include + + #include #include #include #include +#endif +#include + +#include +#include + #if os_DARWIN #include -#else +#elif !os_WINDOWS #include #endif +#if !os_WINDOWS +#include +#endif -#include "vm.h" -#include "log.h" -#include "trap.h" -#include "mutex.h" -#include "threads.h" -#include "maxine.h" -#include "memory.h" #if os_SOLARIS #include #endif -#if os_DARWIN +#if os_DARWIN #define lseek64 lseek #include - #endif +#include + // Platform-independent error return values from OS functions enum OSReturn { @@ -253,7 +284,7 @@ JVM_ActiveProcessorCount(void) { } // Otherwise return number of online cpus return online_cpus; -#elif os_LINUX +#elif os_LINUX cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors int cpus_size = sizeof(cpu_set_t); int processor_count = sysconf(_SC_NPROCESSORS_CONF); @@ -279,6 +310,11 @@ JVM_ActiveProcessorCount(void) { int online_cpus = sysconf(_SC_NPROCESSORS_ONLN); c_ASSERT(online_cpus > 0); return online_cpus; +#elif os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + return systemInfo.dwNumberOfProcessors; //not sure if we need logical or physical processors + //alternatively we can read NUMBER_OF_PROCESSORS environment variable #else UNIMPLEMENTED(); return 0; @@ -287,12 +323,15 @@ JVM_ActiveProcessorCount(void) { #if os_SOLARIS || os_LINUX || os_DARWIN #include + #endif void * JVM_LoadLibrary(const char *name) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN return dlopen(name, RTLD_LAZY); +#elif os_WINDOWS + return LoadLibraryA(name); #else UNIMPLEMENTED(); return 0; @@ -303,6 +342,8 @@ void JVM_UnloadLibrary(void * handle) { #if os_SOLARIS || os_LINUX || os_DARWIN dlclose(handle); +#elif os_WINDOWS + FreeLibrary(handle); #else UNIMPLEMENTED(); #endif @@ -310,8 +351,10 @@ JVM_UnloadLibrary(void * handle) { void * JVM_FindLibraryEntry(void *handle, const char *name) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN return dlsym(handle, name); +#elif os_WINDOWS + return GetProcAddress(handle, name); #else UNIMPLEMENTED(); return 0; @@ -443,7 +486,9 @@ JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name) { /* Same as JDK7u4 (and before): do nothing as not yet implemented on either Solaris / Linux */ #endif } - +#if os_WINDOWS //Microsot uses an empty Yield() Macro (obsolete, not needed) in windows.h which breaks our code so we need to undef it. +#undef Yield +#endif void JVM_Yield(JNIEnv *env, jclass threadClass) { vm.Yield(env); @@ -591,7 +636,7 @@ JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index) { jvalue JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode) { UNIMPLEMENTED_WITH_ENV(); - return (jvalue) 0; + return (jvalue) (jint)0; } void @@ -725,7 +770,9 @@ JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, /* * Reflection support functions */ - +#if os_WINDOWS //Microsot defines GetClassName as GetClassNameA in windows.h which breaks our code so we need to undef it. +#undef GetClassName +#endif jstring JVM_GetClassName(JNIEnv *env, jclass cls) { return vm.GetClassName(env, cls); @@ -1084,36 +1131,37 @@ JVM_RaiseSignal(jint sig) { if (kill(getpid(), sig) < 0) { log_println("error raising signal %d in current process: %s", sig, strerror(errno)); } +#elif os_WINDOWS + if(raise(sig)) + log_println("error raising signal %d in current process: %s", sig, strerror(errno)); + #else UNIMPLEMENTED(); #endif return JNI_TRUE; } -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX || os_WINDOWS typedef struct { const char *name; int number; } Signal; Signal signals[] = { + #if !os_WINDOWS {"HUP", SIGHUP}, - {"INT", SIGINT}, + {"QUIT", SIGQUIT}, {"ILL", SIGILL}, {"TRAP", SIGTRAP}, - {"ABRT", SIGABRT}, #if os_DARWIN {"EMT", SIGEMT}, #endif - {"FPE", SIGFPE}, {"KILL", SIGKILL}, {"BUS", SIGBUS}, - {"SEGV", SIGSEGV}, {"SYS", SIGSYS}, {"PIPE", SIGPIPE}, {"ALRM", SIGALRM}, - {"TERM", SIGTERM}, {"URG", SIGURG}, {"STOP", SIGSTOP}, {"TSTP", SIGTSTP}, @@ -1132,12 +1180,23 @@ Signal signals[] = { #endif {"USR1", SIGUSR1}, {"USR2", SIGUSR2}, + + + #endif + {"ABRT", SIGABRT}, + {"FPE", SIGFPE}, + {"ILL", SIGILL}, + {"INT", SIGINT}, + {"SEGV", SIGSEGV}, + {"TERM", SIGTERM}, + + }; #endif jint JVM_FindSignal(const char *name) { -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX || os_WINDOWS unsigned int i; for (i = 0; i < ARRAY_LENGTH(signals); i++) { if(!strcmp(name, signals[i].name)) { @@ -1804,7 +1863,7 @@ jint JVM_GetLastErrorString(char *buffer, size_t length) { if (errno == 0) { return 0; } -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX || os_WINDOWS const char *s = strerror(errno); size_t n = strlen(s); if (n >= length) { @@ -1826,7 +1885,7 @@ jint JVM_GetLastErrorString(char *buffer, size_t length) { */ char *JVM_NativePath(char *path) { jvmni_log_println("JVM_NativePath(%s)", path); -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX || os_WINDOWS return path; #else UNIMPLEMENTED(); @@ -1902,6 +1961,7 @@ JVM_Write(jint fd, char *buf, jint nbytes) { jint JVM_Available(jint fd, jlong *pbytes) { jlong cur, end; + #if !os_WINDOWS struct stat st; if (fstat(fd, &st) >= 0) { if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { @@ -1912,6 +1972,7 @@ jint JVM_Available(jint fd, jlong *pbytes) { } } } + #endif if ((cur = lseek64(fd, 0L, SEEK_CUR)) == -1) { return 0; } else if ((end = lseek64(fd, 0L, SEEK_END)) == -1) { @@ -1945,7 +2006,9 @@ JVM_Lseek(jint fd, jlong offset, jint whence) { */ jint JVM_SetLength(jint fd, jlong length) { - return ftruncate(fd, length); + return + + ftruncate(fd, length); } /* @@ -1954,7 +2017,12 @@ JVM_SetLength(jint fd, jlong length) { */ jint JVM_Sync(jint fd) { - return fsync(fd); + #if !os_WINDOWS + return fsync(fd); + #else + return !FlushFileBuffers((HANDLE)_get_osfhandle(fd)); //_get_osfhandle transforms fd to HANDLE that is needed by FlushFileBuffers +//Windows return nonzero on success + #endif } /* @@ -1963,7 +2031,7 @@ JVM_Sync(jint fd) { jint JVM_InitializeSocketLibrary(void) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return 0; #else UNIMPLEMENTED(); @@ -1971,16 +2039,15 @@ JVM_InitializeSocketLibrary(void) { #endif } -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS #include -#include #else struct sockaddr; #endif jint JVM_Socket(jint domain, jint type, jint protocol) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return socket(domain, type, protocol); #else UNIMPLEMENTED(); @@ -1990,7 +2057,7 @@ JVM_Socket(jint domain, jint type, jint protocol) { jint JVM_SocketClose(jint fd) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return close(fd); #else UNIMPLEMENTED(); @@ -2000,7 +2067,7 @@ JVM_SocketClose(jint fd) { jint JVM_SocketShutdown(jint fd, jint howto) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return shutdown(fd, howto); #else UNIMPLEMENTED(); @@ -2010,7 +2077,9 @@ JVM_SocketShutdown(jint fd, jint howto) { jint JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS + + return recv(fd, buf, nBytes, flags); #else UNIMPLEMENTED(); @@ -2020,7 +2089,8 @@ JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) { jint JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS + return send(fd, buf, nBytes, flags); #else UNIMPLEMENTED(); @@ -2028,6 +2098,10 @@ JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { #endif } +#if os_WINDOWS +extern int gettimeofday(struct timeval * tp); + +#endif jint JVM_Timeout(int fd, long timeout) { #if os_DARWIN || os_LINUX @@ -2085,6 +2159,36 @@ JVM_Timeout(int fd, long timeout) { } } else return res; } +#elif os_WINDOWS +Unsigned8 prevtime,newtime; + struct timeval t; + + gettimeofday(&t); + prevtime = ((Unsigned8)t.tv_sec * 1000) + t.tv_usec / 1000; + + for(;;) { + WSAPOLLFD pfd; + + pfd.fd = fd; + pfd.events = POLLIN | POLLERR; + + int res = WSAPoll(&pfd, 1, timeout); + + if (res == SOCKET_ERROR && errno == EINTR) { + + // On Windows any value < 0 means "forever" too + + if(timeout >= 0) { + gettimeofday(&t); + newtime = ((Unsigned8)t.tv_sec * 1000) + t.tv_usec / 1000; + timeout -= newtime - prevtime; + if(timeout <= 0) + return OS_OK; + prevtime = newtime; + } + } else + return res; + } #else UNIMPLEMENTED(); return 0; @@ -2093,7 +2197,7 @@ JVM_Timeout(int fd, long timeout) { jint JVM_Listen(jint fd, jint count) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return listen(fd, count); #else UNIMPLEMENTED(); @@ -2103,7 +2207,7 @@ JVM_Listen(jint fd, jint count) { jint JVM_Connect(jint fd, struct sockaddr *him, jint len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return connect(fd, him, len); #else UNIMPLEMENTED(); @@ -2113,7 +2217,7 @@ JVM_Connect(jint fd, struct sockaddr *him, jint len) { jint JVM_Bind(jint fd, struct sockaddr *him, jint len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return bind(fd, him, len); #else UNIMPLEMENTED(); @@ -2123,7 +2227,7 @@ JVM_Bind(jint fd, struct sockaddr *him, jint len) { jint JVM_Accept(jint fd, struct sockaddr *him, jint *len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS if (fd < 0) { return -1; } @@ -2173,7 +2277,8 @@ JVM_SocketAvailable(jint fd, jint *pbytes) { // note ioctl can return 0 when successful, JVM_SocketAvailable // is expected to return 0 on failure and 1 on success to the jdk. return (ret == OS_ERR) ? 0 : 1; -#elif os_LINUX +#elif os_LINUX || os_WINDOWS + // Linux doc says EINTR not returned, unlike Solaris int ret = ioctl(fd, FIONREAD, pbytes); @@ -2189,7 +2294,7 @@ JVM_SocketAvailable(jint fd, jint *pbytes) { jint JVM_GetSockName(jint fd, struct sockaddr *him, int *len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return getsockname(fd, him, (socklen_t*) len); #else UNIMPLEMENTED(); @@ -2199,7 +2304,7 @@ JVM_GetSockName(jint fd, struct sockaddr *him, int *len) { jint JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return getsockopt(fd, level, optname, optval, (socklen_t*) optlen); #else UNIMPLEMENTED(); @@ -2209,7 +2314,7 @@ JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) { jint JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return setsockopt(fd, level, optname, optval, optlen); #else UNIMPLEMENTED(); @@ -2245,7 +2350,7 @@ JVM_GetHostByName(char* name) { int JVM_GetHostName(char* name, int namelen) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return gethostname(name, namelen); #else UNIMPLEMENTED(); diff --git a/com.oracle.max.vm.native/substrate/jvmti.c b/com.oracle.max.vm.native/substrate/jvmti.c index c8b9dc0129..5e6c923371 100644 --- a/com.oracle.max.vm.native/substrate/jvmti.c +++ b/com.oracle.max.vm.native/substrate/jvmti.c @@ -18,7 +18,15 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if os_WINDOWS +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 // needed for tools like MINGW in order to use condition variables which became available from Windows Vista and on. Visual Studio might define it on its own +#include +#endif #include #include #include @@ -28,7 +36,7 @@ // (cwi): Java 7 added a new JVMTI function, so it is necessary to distinguish between Java 6 and Java 7. // This is the only #define that I found in the header files that allows this distinction. -#if os_LINUX || os_SOLARIS +#if os_LINUX || os_SOLARIS || os_WINDOWS #include #endif diff --git a/com.oracle.max.vm.native/substrate/maxine.c b/com.oracle.max.vm.native/substrate/maxine.c index a8a3dbf3bf..c6759acb1a 100644 --- a/com.oracle.max.vm.native/substrate/maxine.c +++ b/com.oracle.max.vm.native/substrate/maxine.c @@ -26,35 +26,61 @@ * hands control over to the VM's compiled code, which has been written in Java, * by calling a VM entry point as a C function. */ -#include + #include "os.h" + + #if !os_WINDOWS + #include + #include + #include + #include + #include + #include + #include +#else + #ifdef _WIN32_WINNT + #undef _WIN32_WINNT + #endif + #define _WIN32_WINNT 0x0600 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. + #include + #include + #include + #include + #include + #define sleep(a) Sleep(a * 1000) + #define strdup _strdup + char last_dl_error [100]; //emulating dlerror() function not available on Windows +#endif + + #include #include -#include -#include + #include -#include #include -#include -#include -#include + #include #include "log.h" #include "isa.h" #include "image.h" #include "threads.h" -#include "os.h" #include "vm.h" #include "virtualMemory.h" #include "maxine.h" #include + + + + #if os_MAXVE #include "maxve.h" #endif -#ifdef arm +#ifdef arm +#if !os_WINDOWS #include #endif +#endif static void max_fd_limit() { @@ -76,7 +102,10 @@ static void max_fd_limit() { log_println("setrlimit failed"); } } +#elif os_WINDOWS + _setmaxstdio(16777216); //windows support setting the max number of fds but they do not have a global max defined. That numer is the theoeretical max fo 64 bit machines #endif + } #define IMAGE_FILE_NAME "maxine.vm" @@ -96,15 +125,18 @@ static void getExecutablePath(char *result) { #elif os_MAXVE result[0] = 0; return; -#elif os_LINUX +#elif os_LINUX char *linkName = "/proc/self/exe"; #elif os_SOLARIS char *linkName = "/proc/self/path/a.out"; +#elif os_WINDOWS + + int numberOfChars = GetModuleFileNameA(NULL,result, MAX_PATH_LENGTH); #else # error getExecutablePath() not supported on other platforms yet #endif -#if os_LINUX || os_SOLARIS +#if os_LINUX || os_SOLARIS // read the symbolic link to figure out what the executable is. int numberOfChars = readlink(linkName, result, MAX_PATH_LENGTH); if (numberOfChars < 0) { @@ -116,7 +148,11 @@ static void getExecutablePath(char *result) { char *p; // chop off the name of the executable for (p = result + (numberOfChars - 1); p >= result; p--) { + #if os_WINDOWS + if (*p == '\\') { + #else if (*p == '/') { + #endif p[1] = 0; break; } @@ -146,7 +182,14 @@ static void *openLibrary(char *path) { log_println("openLibrary(\"%s\")", path); } #endif +#if !os_WINDOWS void *result = dlopen(path, RTLD_LAZY); +#else + void *result = LoadLibraryA(path); + if (result==NULL) { + sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); + } +#endif #if log_LINKER char* errorMessage = dlerror(); if (path == NULL) { @@ -162,8 +205,16 @@ static void *openLibrary(char *path) { } static void* loadSymbol(void* handle, const char* symbol) { + #if os_WINDOWS + void* result = GetProcAddress(handle, symbol); + if (!result) { + sprintf(last_dl_error, "dl function : GetProcAddress error code : %lu", GetLastError ()); + + } + #else void* result = dlsym(handle, symbol); -#if log_LINKER + #endif +#if log_LINKER //NOT IMPLEMENTED FOR WINDOWS, you can get info using the dlerror() function we defined #if os_MAXVE log_println("loadSymbol(%p, \"%s\") = %p", handle, symbol, result); #else @@ -183,7 +234,7 @@ static void* loadSymbol(void* handle, const char* symbol) { return result; } -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX #include #include @@ -194,7 +245,7 @@ static void* loadSymbol(void* handle, const char* symbol) { #if os_DARWIN #include -#elif os_LINUX +#elif os_LINUX #include #elif os_SOLARIS #define _STRUCTURED_PROC 1 /* Use new definitions in procfs.h instead of those in procfs_old.h */ @@ -215,7 +266,7 @@ void debugger_initialize() { char *port = getenv("MAX_AGENT_PORT"); if (port != NULL) { -#if os_LINUX && defined(PR_SET_PTRACER) +#if (os_LINUX ) && defined(PR_SET_PTRACER) /* See info about PR_SET_PTRACER at https://wiki.ubuntu.com/Security/Features#ptrace */ char *val = getenv("MAX_AGENT_PID"); if (val == NULL) { @@ -269,7 +320,7 @@ void debugger_initialize() { #if log_TELE log_println("Stopping VM for debugger"); #endif -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX || os_WINDOWS kill(getpid(), SIGTRAP); #elif os_SOLARIS int ctlfd = open("/proc/self/ctl", O_WRONLY); @@ -284,7 +335,7 @@ void debugger_initialize() { } } #else -#define debugger_initialize() +#define debugger_initialize() //not implemented for WINDOWS #endif /** @@ -293,6 +344,9 @@ void debugger_initialize() { typedef jint (*VMRunMethod)(Address tlBlock, int tlBlockSize, Address bootHeapRegionStart, void *openLibrary(char *), void *dlsym(void *, const char *), char *dlerror(void), void* vmInterface, JNIEnv jniEnv, void *jmmInterface, void *jvmtiInterface, int argc, char *argv[]); +#if os_WINDOWS +__declspec(dllexport) +#endif int maxine(int argc, char *argv[], char *executablePath) { VMRunMethod method; int exitCode = 0; @@ -341,6 +395,13 @@ int maxine(int argc, char *argv[], char *executablePath) { Address tlBlock = threadLocalsBlock_create(PRIMORDIAL_THREAD_ID, 0, 0); NativeThreadLocals ntl = NATIVE_THREAD_LOCALS_FROM_TLBLOCK(tlBlock); +#if os_WINDOWS +char *dlerror(){ + + + return last_dl_error; +} +#endif #if log_LOADER log_println("entering Java by calling MaxineVM.run(tlBlock=%p, bootHeapRegionStart=%p, openLibrary=%p, dlsym=%p, dlerror=%p, vmInterface=%p, jniEnv=%p, jmmInterface=%p, jvmtiInterface=%p, argc=%d, argv=%p)", @@ -405,8 +466,12 @@ void core_dump() { log_print("dumping core....\n heap @ "); log_print_symbol(image_heap()); log_print_newline(); + #if os_WINDOWS + raise(SIGABRT); + #else // Use kill instead of abort so the vm process keeps running after the core is created. kill(getpid(), SIGABRT); + #endif sleep(3); #endif } @@ -444,6 +509,23 @@ void *native_properties(void) { } #if os_MAXVE maxve_native_props(&nativeProperties); +#elif os_WINDOWS + + nativeProperties.user_name = malloc(MAX_PATH_LENGTH); + nativeProperties.user_dir = malloc(MAX_PATH_LENGTH); + nativeProperties.user_home = malloc(MAX_PATH_LENGTH); + + DWORD size = MAX_PATH_LENGTH; + GetUserNameA(nativeProperties.user_name, &size); + size = MAX_PATH_LENGTH; + char * tmp; + SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, (WCHAR **) &tmp); //Unfortunately, windows return home dir only in Unicode (Wide) format, not ANSI + nativeProperties.user_home = (char*) _wcsdup((const wchar_t * ) tmp); + CoTaskMemFree(tmp); //SHGetKnownFolderPath allocated that space and it is our responsibility to free it + GetCurrentDirectory(MAX_PATH_LENGTH, nativeProperties.user_dir); +//CAUTION nativeProperties.user_home contains the path in Unicode format so it cannot be printed with %s but rather with %ls using printf + + #else /* user properties */ { diff --git a/com.oracle.max.vm.native/substrate/maxine.h b/com.oracle.max.vm.native/substrate/maxine.h index 64df50d182..76ef87f53d 100644 --- a/com.oracle.max.vm.native/substrate/maxine.h +++ b/com.oracle.max.vm.native/substrate/maxine.h @@ -27,7 +27,7 @@ extern jlong native_nanoTime(void); extern jlong native_currentTimeMillis(void); extern void *native_executablePath(void); -extern void native_exit(int code); +extern void native_exit(jint code); extern void *native_environment(void); extern int maxine(int argc, char *argv[], char *executablePath); diff --git a/com.oracle.max.vm.native/substrate/memory.c b/com.oracle.max.vm.native/substrate/memory.c index 542f654493..1849aaa863 100644 --- a/com.oracle.max.vm.native/substrate/memory.c +++ b/com.oracle.max.vm.native/substrate/memory.c @@ -19,9 +19,13 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "os.h" - +#if !os_WINDOWS #include #include +#else +#include +#endif + #include #include diff --git a/com.oracle.max.vm.native/substrate/signal.c b/com.oracle.max.vm.native/substrate/signal.c index 9813304e5c..f07eb5cea2 100644 --- a/com.oracle.max.vm.native/substrate/signal.c +++ b/com.oracle.max.vm.native/substrate/signal.c @@ -24,6 +24,10 @@ /** * Native functions for SignalDispatcher.java. */ +#include "os.h" +#if os_WINDOWS +#include +#endif #include #include #include @@ -32,7 +36,9 @@ #include "threads.h" #include "log.h" -#if os_DARWIN +#if os_WINDOWS +static HANDLE signal_sem; +#elif os_DARWIN #include static semaphore_t signal_sem; #elif os_SOLARIS @@ -43,11 +49,11 @@ static semaphore_t signal_sem; #define sem_destroy sema_destroy #define sem_t sema_t static sem_t signal_sem; -#elif os_LINUX +#elif os_MAXVE +#else #include static sem_t signal_sem; -#elif os_MAXVE -// no signals, so nothing necessary + #endif boolean traceSignals = false; @@ -69,10 +75,15 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalNotify(JNIEnv *env, jcl if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_signal failed: %s", mach_error_string(kr)); } -#elif os_LINUX || os_SOLARIS +#elif os_LINUX || os_SOLARIS if (sem_post(&signal_sem) != 0) { log_exit(11, "sem_post failed: %s", strerror(errno)); } +#elif os_WINDOWS + if(!ReleaseSemaphore(signal_sem, 1, NULL)) + log_exit(GetLastError(), "ReleaseSemaphore failed"); + + #elif os_MAXVE #else c_UNIMPLEMENTED(); @@ -113,13 +124,18 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalWait(JNIEnv *env, jclas if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_wait failed: %s", mach_error_string(kr)); } -#elif os_LINUX || os_SOLARIS +#elif os_LINUX || os_SOLARIS int ret; - while ((ret = sem_wait(&signal_sem) == EINTR)) { + while ((ret = sem_wait(&signal_sem) == EINTR)) { //not sure if EINTR can occur on Windows (No sending signals is supported } if (ret != 0) { log_exit(11, "sem_wait failed: %s", strerror(errno)); } +#elif os_WINDOWS + if ( WaitForSingleObject(signal_sem,INFINITE) == WAIT_FAILED) + log_exit(GetLastError(), "WaitForSingleObject failed:"); + + #elif os_MAXVE #else c_UNIMPLEMENTED(); @@ -139,10 +155,13 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalInit(JNIEnv *env, jclas if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_create failed: %s", mach_error_string(kr)); } -#elif os_LINUX +#elif os_LINUX if (sem_init(&signal_sem, 0, 0) != 0) { log_exit(11, "sem_init failed: %s", strerror(errno)); } +#elif os_WINDOWS + signal_sem = CreateSemaphoreA(NULL, 1, 50000,NULL); //Windows Semaphore needs to have initial val 1 not 0 like Linux. If it was 0 no thread could enter +//Unfortunately, Windows Semaphores need a maximum value representing how many can enter it so we use a random big value (50000) #elif os_SOLARIS if (sem_init(&signal_sem, 0, USYNC_THREAD, NULL) != 0) { log_exit(11, "sema_init failed: %s", strerror(errno)); @@ -176,6 +195,8 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalFinalize(JNIEnv *env, j if (sem_destroy(&signal_sem) != 0) { log_exit(11, "sema_destroy failed: %s", strerror(errno)); } +#elif os_WINDOWS + CloseHandle(signal_sem); #endif } diff --git a/com.oracle.max.vm.native/substrate/sync.c b/com.oracle.max.vm.native/substrate/sync.c index bb6f59e38c..d0f4af3ead 100644 --- a/com.oracle.max.vm.native/substrate/sync.c +++ b/com.oracle.max.vm.native/substrate/sync.c @@ -18,6 +18,10 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if os_WINDOWS +#include +#endif #include #include @@ -26,7 +30,6 @@ #include "log.h" #include "jni.h" #include "mutex.h" -#include "os.h" #include "word.h" #include "threads.h" diff --git a/com.oracle.max.vm.native/substrate/threads.c b/com.oracle.max.vm.native/substrate/threads.c index 6d82a2491b..3717429596 100644 --- a/com.oracle.max.vm.native/substrate/threads.c +++ b/com.oracle.max.vm.native/substrate/threads.c @@ -19,11 +19,16 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include "os.h" -#include +#if (!os_WINDOWS) + #include +#else + #include +#endif #include -#include "os.h" #include "isa.h" #include "virtualMemory.h" @@ -41,8 +46,9 @@ #include "trap.h" #include "threads.h" #include "threadLocals.h" +#if !os_WINDOWS #include - +#endif #if (os_DARWIN || os_LINUX) # include # include @@ -56,6 +62,16 @@ # include "maxve.h" typedef maxve_Thread Thread; #define thread_current() (maxve_get_current()) + +#elif os_WINDOWS + + #include + #include + #include + #include + typedef HANDLE Thread; +#define thread_current() ((Thread) GetCurrentThread()) + #endif #if log_NUMA_THREADS @@ -114,6 +130,20 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { } pthread_attr_destroy(&attr); +#elif os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + + NT_TIB *tib = (NT_TIB*)NtCurrentTeb(); + *stackBase = (DWORD_PTR)tib->StackBase - systemInfo.dwPageSize ; //In windows, guard size is always one memory page so we remove it from stacksize. + + + MEMORY_BASIC_INFORMATION mbi = {0}; + if (VirtualQuery((LPCVOID)(stackBase ), &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0) //we use virtualquery to get windows reserved stack size (not committed). + { + DWORD_PTR allocationStart = (DWORD_PTR)mbi.AllocationBase; + *stackSize = (size_t) stackBase - allocationStart; + } #elif os_DARWIN pthread_t self = pthread_self(); void *stackTop = pthread_get_stackaddr_np(self); @@ -146,7 +176,7 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { */ static Thread thread_create(jint id, Size stackSize, int priority) { Thread thread; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS int error; #endif @@ -158,8 +188,10 @@ static Thread thread_create(jint id, Size stackSize, int priority) { #if log_THREADS log_println("thread_create: id = %d, stack size = %ld", id, stackSize); #endif - -#if (os_LINUX || os_DARWIN) +#if os_WINDOWS +#define PTHREAD_STACK_MIN 0 +#endif +#if (os_LINUX || os_DARWIN ) if (stackSize < PTHREAD_STACK_MIN) { stackSize = PTHREAD_STACK_MIN; } @@ -184,7 +216,7 @@ static Thread thread_create(jint id, Size stackSize, int priority) { if (thread == NULL) { return (Thread) 0; } -#elif (os_LINUX || os_DARWIN) +#elif (os_LINUX || os_DARWIN ) pthread_attr_t attributes; pthread_attr_init(&attributes); @@ -200,6 +232,15 @@ static Thread thread_create(jint id, Size stackSize, int priority) { log_println("pthread_create failed with error: %d", error); return (Thread) 0; } +#elif (os_WINDOWS) + thread = CreateThread(NULL, stackSize, thread_run, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL); //we demand explicitly stack size to be reservedd + //Also guard is set automatically + if(!thread){ + log_println("thread_create failed with error: %d", GetLastError()); + return (Thread) 0; + } + //the only way to make thread detached is to invalidate its handle using CloseHandle(). However, this would result in returning an invalid Thread at the end of the function + #elif os_SOLARIS if (stackSize < thr_min_stack()) { stackSize = thr_min_stack(); @@ -226,7 +267,13 @@ void *thread_self() { * * @param arg the pre-allocated, but uninitialized, thread locals block. */ -void *thread_run(void *arg) { + #if os_WINDOWS +DWORD WINAPI thread_run(void *arg) //we prefer this signature in order to avoid compiler waring on Windows. + + #else +void * thread_run(void *arg) +#endif + { Address tlBlock = (Address) arg; TLA etla = ETLA_FROM_TLBLOCK(tlBlock); @@ -307,7 +354,11 @@ void *thread_run(void *arg) { setCurrentThreadSignalMaskOnThreadExit(result == 1); /* Successful thread exit */ - return NULL; + #if os_WINDOWS + return 0; + #else + return NULL; + #endif } /** @@ -478,10 +529,12 @@ Java_com_sun_max_vm_thread_VmThread_nativeYield(JNIEnv *env, jclass c) { thr_yield(); #elif os_DARWIN sched_yield(); -#elif os_LINUX +#elif os_LINUX pthread_yield(); #elif os_MAXVE maxve_yield(); +#elif os_WINDOWS + SwitchToThread(); #else c_UNIMPLEMENTED(); #endif @@ -504,7 +557,7 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre log_exit(11, "Error sending signal SIGUSR1 to native thread %p", nativeThread); } } -#elif os_LINUX || os_DARWIN +#elif os_LINUX || os_DARWIN // Signals the thread int result = pthread_kill((pthread_t) nativeThread, SIGUSR1); if (result != 0) { @@ -517,7 +570,12 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre } } #elif os_MAXVE + maxve_interrupt((void*) nativeThread); +#elif os_WINDOWS + c_UNIMPLEMENTED(); + + #else c_UNIMPLEMENTED(); #endif @@ -526,6 +584,20 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre jboolean thread_sleep(jlong numberOfMilliSeconds) { #if os_MAXVE return maxve_sleep(numberOfMilliSeconds * 1000000); +#elif os_WINDOWS +HANDLE timer; +LARGE_INTEGER li; +if(!(timer = CreateWaitableTimer(NULL, TRUE, NULL))) + return FALSE; + +li.QuadPart = -(numberOfMilliSeconds * 1000000); +if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)){ + CloseHandle(timer); + return FALSE; + } + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); + return TRUE; #else struct timespec time, remainder; diff --git a/com.oracle.max.vm.native/substrate/time.c b/com.oracle.max.vm.native/substrate/time.c index 60e90b0d39..07a86d8b61 100644 --- a/com.oracle.max.vm.native/substrate/time.c +++ b/com.oracle.max.vm.native/substrate/time.c @@ -21,15 +21,47 @@ #include "os.h" #include "jni.h" #include "maxine.h" - #include -#include +#if !os_WINDOWS +#include //MINGW may contain this file but it is not officially part of WINAPI so other SDKs (eg. Visual Studio do not include it) +#endif #if os_DARWIN #include #include #elif os_LINUX #include +#elif os_WINDOWS +#include +#include +int gettimeofday(struct timeval * tp) +{ + // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's + // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) + // until 00:00:00 January 1, 1970 + static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); + + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; + + GetSystemTime( &system_time ); + SystemTimeToFileTime( &system_time, &file_time ); + time = ((uint64_t)file_time.dwLowDateTime ) ; + time += ((uint64_t)file_time.dwHighDateTime) << 32; + + tp->tv_sec = (long) ((time - EPOCH) / 10000000L); + tp->tv_usec = (long) (system_time.wMilliseconds * 1000); + return 0; +} + +int clock_gettime(int x, struct timespec *spec) +{ __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); + wintime -=(int64_t)116444736000000000; //1jan1601 to 1jan1970 + spec->tv_sec =wintime / (int64_t)10000000; //seconds + spec->tv_nsec =wintime % (int64_t)10000000 *100; //nano-seconds + return 0; +} #endif @@ -69,7 +101,7 @@ jlong native_nanoTime(void) { struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)tv.tv_sec * (uint64_t)(1000 * 1000 * 1000) + (uint64_t)(tv.tv_usec * 1000); -#elif os_LINUX +#elif os_LINUX #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC (1) @@ -119,15 +151,23 @@ jlong native_nanoTime(void) { c_ASSERT(status != -1); jlong usecs = ((jlong) time.tv_sec) * (1000 * 1000) + (jlong) time.tv_usec; return 1000 * usecs; +#elif os_WINDOWS + struct timespec time; + clock_gettime(1, &time); + return time.tv_nsec; //NOT 100% TESTED #else return 1; #endif } jlong native_currentTimeMillis(void) { -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX || os_WINDOWS struct timeval tv; + #if os_WINDOWS + gettimeofday(&tv); + #else gettimeofday(&tv, NULL); + #endif // we need to cast to jlong to avoid overflows in ARMv7 return ((jlong) tv.tv_sec * 1000) + ((jlong) tv.tv_usec / 1000); #else diff --git a/com.oracle.max.vm.native/substrate/trap.c b/com.oracle.max.vm.native/substrate/trap.c index 3030b388ae..7501e780fe 100644 --- a/com.oracle.max.vm.native/substrate/trap.c +++ b/com.oracle.max.vm.native/substrate/trap.c @@ -19,13 +19,15 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - +#include "os.h" +#if os_WINDOWS +#include +#endif #include "c.h" #include "threads.h" #include "virtualMemory.h" #include "log.h" #include "jni.h" -#include "os.h" #include "isa.h" #include "image.h" #include "trap.h" @@ -49,7 +51,7 @@ static Address theJavaTrapStub; static boolean traceTraps = false; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS //Windows do not support POSIX signals unfortunately. You can only raise some signals from within your own process/thread but not send it to another process/thread /** * All signals. @@ -77,13 +79,13 @@ static sigset_t blockedOnThreadExitSignals; int getTrapNumber(int signal) { switch (signal) { case SIGSEGV: -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS case SIGBUS: #endif return MEMORY_FAULT; case SIGFPE: return ARITHMETIC_EXCEPTION; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS case SIGUSR1: return ASYNC_INTERRUPT; default: @@ -96,12 +98,12 @@ int getTrapNumber(int signal) { #if os_SOLARIS #include #define thread_setSignalMask thr_sigsetmask -#elif os_DARWIN || os_LINUX +#elif os_DARWIN || os_LINUX #define thread_setSignalMask pthread_sigmask #endif void setCurrentThreadSignalMaskOnThreadExit(boolean isVmOperationThread) { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS if (!isVmOperationThread) { /* disable signals sent by Thread.interrupt() as thread is transitioning to not alive state. */ thread_setSignalMask(SIG_BLOCK, &blockedOnThreadExitSignals, NULL); @@ -110,7 +112,7 @@ void setCurrentThreadSignalMaskOnThreadExit(boolean isVmOperationThread) { } void setCurrentThreadSignalMask(boolean isVmOperationThread) { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS if (isVmOperationThread) { thread_setSignalMask(SIG_SETMASK, &vmAndDefaultSignals, NULL); } else { @@ -120,9 +122,12 @@ void setCurrentThreadSignalMask(boolean isVmOperationThread) { #endif } -void* setSignalHandler(int signal, SignalHandlerFunction handler) { +void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'signal' argument to 'sig' because it overlapped with windows signal() function #if os_MAXVE - maxve_register_fault_handler(signal, handler); + maxve_register_fault_handler(sig, handler); + return NULL; +#elif os_WINDOWS + signal(sig, handler); return NULL; #else struct sigaction newSigaction; @@ -132,14 +137,14 @@ void* setSignalHandler(int signal, SignalHandlerFunction handler) { sigemptyset(&newSigaction.sa_mask); newSigaction.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK; -#if os_SOLARIS || os_LINUX || os_DARWIN - if (signal == SIGUSR1) { +#if os_SOLARIS || os_LINUX || os_DARWIN + if (sig == SIGUSR1) { newSigaction.sa_flags = SA_SIGINFO | SA_ONSTACK; } #endif newSigaction.sa_sigaction = handler; - if (sigaction(signal, &newSigaction, &oldSigaction) != 0) { + if (sigaction(sig, &newSigaction, &oldSigaction) != 0) { log_exit(1, "sigaction failed"); } @@ -147,7 +152,7 @@ void* setSignalHandler(int signal, SignalHandlerFunction handler) { log_lock(); log_print("Registered handler %p [", handler); log_print_symbol((Address) handler); - log_print("] for signal %d", signal); + log_print("] for signal %d", sig); if (oldSigaction.sa_handler != NULL) { log_print(" replacing handler "); log_print_symbol((Address) oldSigaction.sa_handler); @@ -163,7 +168,7 @@ void* setSignalHandler(int signal, SignalHandlerFunction handler) { static Address getInstructionPointer(UContext *ucontext) { #if os_SOLARIS return ucontext->uc_mcontext.gregs[REG_PC]; -#elif os_LINUX +#elif os_LINUX # if isa_AMD64 return ucontext->uc_mcontext.gregs[REG_RIP]; # elif isa_IA32 @@ -179,6 +184,10 @@ static Address getInstructionPointer(UContext *ucontext) { return ucontext->uc_mcontext->__ss.__rip; #elif os_MAXVE return ucontext->rip; +#elif os_WINDOWS +#if isa_AMD64 + return ucontext->Rip; + #endif #else c_UNIMPLEMENTED(); #endif @@ -192,7 +201,7 @@ static void setInstructionPointer(UContext *ucontext, Address stub) { ucontext->uc_mcontext.gregs[REG_PC] = (greg_t) stub; #elif os_DARWIN ucontext->uc_mcontext->__ss.__rip = stub; -#elif os_LINUX +#elif os_LINUX # if isa_AMD64 ucontext->uc_mcontext.gregs[REG_RIP] = (greg_t) stub; # elif isa_IA32 @@ -206,15 +215,19 @@ static void setInstructionPointer(UContext *ucontext, Address stub) { # endif #elif os_MAXVE ucontext->rip = (unsigned long) stub; +#elseif os_WINDOWS +# if isa_AMD64 + ucontext->uc_mcontext.rip = (greg_t) stub; + #endif #else c_UNIMPLEMENTED(); #endif } -static Address getFaultAddress(SigInfo * sigInfo, UContext *ucontext) { +static Address getFaultAddress(SigInfo * sigInfo, UContext *ucontext) { //there is no siginfo_t struct in Windows #if (os_DARWIN || os_SOLARIS || os_LINUX ) return (Address) sigInfo->si_addr; -#elif (os_MAXVE) +#elif (os_MAXVE) || os_WINDOWS return (Address) sigInfo; #endif } @@ -228,7 +241,7 @@ char *vmSignalName(int signal) { case SIGSEGV: return "SIGSEGV"; case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS case SIGUSR1: return "SIGUSR1"; case SIGBUS: return "SIGBUS"; #endif @@ -269,12 +282,15 @@ static boolean handleDivideOverflow(UContext *ucontext) { if (rip[0] == 0xf7) { #if os_SOLARIS Address dividend = ucontext->uc_mcontext.gregs[REG_RAX]; -#elif os_LINUX +#elif os_LINUX Address dividend = ucontext->uc_mcontext.gregs[REG_RAX]; #elif os_DARWIN Address dividend = ucontext->uc_mcontext->__ss.__rax; #elif os_MAXVE Address dividend = ucontext->rax; +#elif os_WINDOWS + Address dividend = ucontext->Rax; + #else c_UNIMPLEMENTED(); #endif @@ -294,12 +310,15 @@ static boolean handleDivideOverflow(UContext *ucontext) { /* Set the remainder to 0. */ #if os_SOLARIS ucontext->uc_mcontext.gregs[REG_RDX] = 0; -#elif os_LINUX +#elif os_LINUX ucontext->uc_mcontext.gregs[REG_RDX] = 0; #elif os_DARWIN ucontext->uc_mcontext->__ss.__rdx = 0; #elif os_MAXVE ucontext->rdx = 0; +#elif os_WINDOWS + ucontext->Rdx = 0; + #else c_UNIMPLEMENTED(); #endif @@ -446,6 +465,9 @@ static void vmSignalHandler(int signal, SigInfo *signalInfo, UContext *ucontext) #elif isa_AMD64 && (os_SOLARIS || os_LINUX) tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->uc_mcontext.gregs[REG_R14]); ucontext->uc_mcontext.gregs[REG_R14] = (Address) dtla; +#elif isa_AMD64 && os_WINDOWS + tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->R14); + ucontext->R14 = (Address) dtla; #elif isa_AMD64 && os_DARWIN tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->uc_mcontext->__ss.__r14); ucontext->uc_mcontext->__ss.__r14 = (Address) dtla; @@ -471,11 +493,17 @@ static void vmSignalHandler(int signal, SigInfo *signalInfo, UContext *ucontext) /** * The handler for signals handled by SignalDispatcher.java. */ + #if os_WINDOWS + static void userSignalHandlerDef(int signal) { + void postSignal(int signal); + postSignal(signal); +} +#else static void userSignalHandlerDef(int signal, SigInfo *signalInfo, UContext *ucontext) { void postSignal(int signal); postSignal(signal); } - +#endif /* Defined global declared in trap.h */ SignalHandlerFunction userSignalHandler = (SignalHandlerFunction) userSignalHandlerDef; @@ -491,7 +519,7 @@ void nativeTrapInitialize(Address javaTrapStub) { setSignalHandler(SIGILL, (SignalHandlerFunction) vmSignalHandler); setSignalHandler(SIGFPE, (SignalHandlerFunction) vmSignalHandler); -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS //no support for windows signals setSignalHandler(SIGBUS, (SignalHandlerFunction) vmSignalHandler); setSignalHandler(SIGUSR1, (SignalHandlerFunction) vmSignalHandler); diff --git a/com.oracle.max.vm.native/substrate/trap.h b/com.oracle.max.vm.native/substrate/trap.h index 620a4b9afe..990f1a582a 100644 --- a/com.oracle.max.vm.native/substrate/trap.h +++ b/com.oracle.max.vm.native/substrate/trap.h @@ -29,14 +29,22 @@ # include # include # include -# include +#if (!os_WINDOWS) + # include # include -#endif +#endif +#endif #include "os.h" -#if os_MAXVE +#if os_MAXVE #define SignalHandlerFunction fault_handler_t +#elif os_WINDOWS +typedef void SigInfo; + +typedef void (*SignalHandlerFunction)(int signal); //Windows want a signal handler with one argument (Remember, Windows do not support POSIX signals. They can only be used as exceptions raised from within the same process. You cannot send them to other threads/ procs) + +typedef CONTEXT UContext; #else typedef ucontext_t UContext; typedef siginfo_t SigInfo; diff --git a/com.oracle.max.vm.native/substrate/vm.h b/com.oracle.max.vm.native/substrate/vm.h index 880df618d4..8a4da41eed 100644 --- a/com.oracle.max.vm.native/substrate/vm.h +++ b/com.oracle.max.vm.native/substrate/vm.h @@ -36,6 +36,10 @@ * A set of VM functions implemented in Java that can (only) be called from C code. * These are defined in VMFunctionsSource.java. */ + #include "os.h" + #if os_WINDOWS + #undef GetClassName + #endif //Microsoft defines GetClassName as GetClassNameA in some header files which breaks our code typedef struct vmInterface_ { // START GENERATED CODE void (JNICALL *Unimplemented) (JNIEnv *env); From f29b6635c1675ad524ecacf2aec8c63cbe0301be Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Wed, 8 Jul 2020 20:52:00 +0300 Subject: [PATCH 02/17] Revert "Added Windows support on com.oracle.max.vm.native, except Tele (code relies exclusively on existing native Windows Libraries, no dependency required)" This reverts commit 8d7ca096969e6ca4bbc92dd59308b2f17c99e748. --- com.oracle.max.vm.native/desktop.ini | 3 - com.oracle.max.vm.native/hosted/platform.c | 18 +- com.oracle.max.vm.native/javatest/javatest.mk | 2 +- com.oracle.max.vm.native/javatest/tests.c | 36 +--- com.oracle.max.vm.native/launch/maxvm.c | 40 +--- com.oracle.max.vm.native/makefile | 2 +- com.oracle.max.vm.native/platform/aarch64.c | 2 +- com.oracle.max.vm.native/platform/aarch64.h | 2 +- com.oracle.max.vm.native/platform/amd64.c | 6 +- com.oracle.max.vm.native/platform/amd64.h | 16 -- com.oracle.max.vm.native/platform/arm.c | 6 +- com.oracle.max.vm.native/platform/platform.mk | 44 +--- .../platform/usercygwinamd64.h | 45 ---- com.oracle.max.vm.native/share/c.h | 4 +- com.oracle.max.vm.native/share/condition.c | 33 +-- com.oracle.max.vm.native/share/condition.h | 4 - com.oracle.max.vm.native/share/log.c | 35 ++- com.oracle.max.vm.native/share/mutex.c | 21 +- com.oracle.max.vm.native/share/mutex.h | 3 +- com.oracle.max.vm.native/share/threadLocals.c | 26 +-- com.oracle.max.vm.native/share/threads.h | 7 +- .../share/virtualMemory.c | 154 ++------------ com.oracle.max.vm.native/substrate/barrier.c | 6 +- com.oracle.max.vm.native/substrate/image.c | 11 +- com.oracle.max.vm.native/substrate/jni.c | 23 +- com.oracle.max.vm.native/substrate/jvm.c | 199 +++++------------- com.oracle.max.vm.native/substrate/jvmti.c | 10 +- com.oracle.max.vm.native/substrate/maxine.c | 116 ++-------- com.oracle.max.vm.native/substrate/maxine.h | 2 +- com.oracle.max.vm.native/substrate/memory.c | 6 +- com.oracle.max.vm.native/substrate/signal.c | 37 +--- com.oracle.max.vm.native/substrate/sync.c | 5 +- com.oracle.max.vm.native/substrate/threads.c | 94 +-------- com.oracle.max.vm.native/substrate/time.c | 48 +---- com.oracle.max.vm.native/substrate/trap.c | 74 ++----- com.oracle.max.vm.native/substrate/trap.h | 14 +- com.oracle.max.vm.native/substrate/vm.h | 4 - 37 files changed, 201 insertions(+), 957 deletions(-) delete mode 100644 com.oracle.max.vm.native/desktop.ini delete mode 100644 com.oracle.max.vm.native/platform/usercygwinamd64.h diff --git a/com.oracle.max.vm.native/desktop.ini b/com.oracle.max.vm.native/desktop.ini deleted file mode 100644 index 4af9750217..0000000000 --- a/com.oracle.max.vm.native/desktop.ini +++ /dev/null @@ -1,3 +0,0 @@ -[.ShellClassInfo] -InfoTip=MEGA synced folder -IconResource=C:\Users\mihalis341\AppData\Local\MEGAsync\MEGAsync.exe,3 diff --git a/com.oracle.max.vm.native/hosted/platform.c b/com.oracle.max.vm.native/hosted/platform.c index b0c02489a3..de3410bb39 100644 --- a/com.oracle.max.vm.native/hosted/platform.c +++ b/com.oracle.max.vm.native/hosted/platform.c @@ -18,21 +18,12 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "os.h" -#if !os_WINDOWS #include -#else - #include - #include -#endif #include "word.h" #include "isa.h" #include "jni.h" #include #include -#include - - JNIEXPORT void JNICALL JVM_OnLoad(JavaVM *vm, char *options, void *arg) @@ -63,14 +54,7 @@ Java_com_sun_max_platform_Platform_nativeGetOS(JNIEnv *env, jclass c) JNIEXPORT jint JNICALL Java_com_sun_max_platform_Platform_nativeGetPageSize(JNIEnv *env, jclass c) { - #if os_WINDOWS - SYSTEM_INFO systemInfo = {0}; - GetSystemInfo(&systemInfo); - return systemInfo.dwPageSize ; - - #else - return (jint) sysconf(_SC_PAGESIZE); - #endif + return (jint) sysconf(_SC_PAGESIZE); } diff --git a/com.oracle.max.vm.native/javatest/javatest.mk b/com.oracle.max.vm.native/javatest/javatest.mk index 7a92b47a1a..6a76e4ed70 100644 --- a/com.oracle.max.vm.native/javatest/javatest.mk +++ b/com.oracle.max.vm.native/javatest/javatest.mk @@ -27,7 +27,7 @@ LIB = javatest include $(PROJECT)/platform/platform.mk -SOURCES = jvmni.c tests.c threads.c jnitests.c jvm.c jni.c threadLocals.c image.c log.c virtualMemory.c mutex.c c.c trap.c time.c jmm.c jvmti.c relocation.c signal.c dataio.c +SOURCES = jvmni.c tests.c threads.c jnitests.c SOURCE_DIRS = javatest jni platform hosted share substrate diff --git a/com.oracle.max.vm.native/javatest/tests.c b/com.oracle.max.vm.native/javatest/tests.c index f700cd6dac..94c9cb4f4b 100644 --- a/com.oracle.max.vm.native/javatest/tests.c +++ b/com.oracle.max.vm.native/javatest/tests.c @@ -24,11 +24,8 @@ * JNI code for any of the JavaTester tests that use native methods. */ #include "os.h" -#if !os_WINDOWS + #include -#else - #include -#endif #include "jni.h" JNIEXPORT void JNICALL @@ -99,42 +96,23 @@ void upcall(jclass cls) { (*env)->DeleteGlobalRef(env, cls); (*vm)->DetachCurrentThread(vm); } -#if os_WINDOWS -DWORD WINAPI thread_function(void *arguments) {//we prefer this signature in order to avoid compiler waring on Windows. -#else + void *thread_function(void *arguments) { -#endif upcall((jclass) arguments); - #if os_WINDOWS - return 0; - #else - return NULL; - #endif + return NULL; } JNIEXPORT void JNICALL Java_test_output_AttachThread_callHelloWorldOnAttachedThread(JNIEnv *env, jclass clazz) { - #if !os_WINDOWS - pthread_t thread_id; - pthread_attr_t attributes; - - #endif + pthread_t thread_id; + pthread_attr_t attributes; + /* Convert argument to be a global handle as it is going to the new thread */ clazz = (*env)->NewGlobalRef(env, clazz); - #if os_WINDOWS - LPVOID - #else - void * - #endif - arguments = clazz; - #if !os_WINDOWS + void *arguments = clazz; pthread_attr_init(&attributes); pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE); pthread_create(&thread_id, &attributes, thread_function, arguments); pthread_attr_destroy(&attributes); - #else - CreateThread(NULL, 0, thread_function, arguments, 0, NULL); - - #endif } diff --git a/com.oracle.max.vm.native/launch/maxvm.c b/com.oracle.max.vm.native/launch/maxvm.c index 214a12a67e..1c45914fff 100644 --- a/com.oracle.max.vm.native/launch/maxvm.c +++ b/com.oracle.max.vm.native/launch/maxvm.c @@ -18,19 +18,13 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "os.h" -#if os_WINDOWS -#include -char last_dl_error [100]; //emulating dlerror() function not available on Windows - -#else #include -#endif #include #include #include #include +#include "os.h" #include "maxine.h" typedef int (*MaxineFunction)(int argc, char *argv[], char *executablePath); @@ -64,15 +58,6 @@ typedef int (*MaxineFunction)(int argc, char *argv[], char *executablePath); #include const CFNullRef initializeCoreFoundationOnMainThread; -#elif os_WINDOWS -#define LIBRARY_NAME "jvm.dll" -#define MAIN_EXTRA_ARGS -#define PROG_PATH argv[0] -char *dlerror(){ - - - return last_dl_error; -} #else #define LIBRARY_NAME "libjvm.so" #define MAIN_EXTRA_ARGS @@ -123,42 +108,23 @@ int main(int argc, char *argv[] MAIN_EXTRA_ARGS) { strncpy(libraryPath, programPath, prefixLength); strcpy(libraryPath + prefixLength, LIBRARY_NAME); #endif - #if os_WINDOWS - void *result = LoadLibraryA(libraryPath); - if (result==NULL) { - sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); - fprintf(stderr, "could not load %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); - exit(1); - - } - MaxineFunction maxine = (MaxineFunction) GetProcAddress(result, "maxine"); - if (maxine == 0) { - sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); - fprintf(stderr, "could not find symbol 'maxine' in %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); - exit(1); - } - - return (*maxine)(argc, argv, NULL); - #else void *handle = dlopen(libraryPath, RTLD_LAZY | RTLD_GLOBAL); if (handle == 0) { - fprintf(stderr, "could not load %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); + fprintf(stderr, "could not load %s: %s\n", LIBRARY_NAME, dlerror()); exit(1); } MaxineFunction maxine = (MaxineFunction) dlsym(handle, "maxine"); if (maxine == 0) { - fprintf(stderr, "could not find symbol 'maxine' in %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); + fprintf(stderr, "could not find symbol 'maxine' in %s: %s\n", LIBRARY_NAME, dlerror()); exit(1); } - #endif #if os_DARWIN return (*maxine)(argc, argv, programPath); #else free(libraryPath); - return (*maxine)(argc, argv, NULL); #endif } diff --git a/com.oracle.max.vm.native/makefile b/com.oracle.max.vm.native/makefile index e5c253f008..cab187f58c 100644 --- a/com.oracle.max.vm.native/makefile +++ b/com.oracle.max.vm.native/makefile @@ -28,7 +28,7 @@ include platform/platform.mk -all : hosted substrate launch javatest tele +all : hosted substrate launch tele javatest hosted : build/$(OS)/hosted/makefile $(AT) (cd build/$(OS)/hosted; $(MAKE) all) diff --git a/com.oracle.max.vm.native/platform/aarch64.c b/com.oracle.max.vm.native/platform/aarch64.c index b8ca765cf4..3b946e3ff8 100644 --- a/com.oracle.max.vm.native/platform/aarch64.c +++ b/com.oracle.max.vm.native/platform/aarch64.c @@ -23,7 +23,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_CanonicalIntegerRegisters c) { -#if os_LINUX || os_WINDOWS +#if os_LINUX #define CANONICALIZE(reg) c->r##reg = (Word) os->regs[reg] #else #define CANONICALIZE(reg, ucReg) c_UNIMPLEMENTED() diff --git a/com.oracle.max.vm.native/platform/aarch64.h b/com.oracle.max.vm.native/platform/aarch64.h index 5efd40fd8d..75303f0b13 100644 --- a/com.oracle.max.vm.native/platform/aarch64.h +++ b/com.oracle.max.vm.native/platform/aarch64.h @@ -23,7 +23,7 @@ #include "word.h" -#if (os_LINUX || os_WINDOWS) +#if os_LINUX # include # include typedef struct user_regs_struct *aarch64_OsTeleIntegerRegisters; diff --git a/com.oracle.max.vm.native/platform/amd64.c b/com.oracle.max.vm.native/platform/amd64.c index df6edd7508..5db518c005 100644 --- a/com.oracle.max.vm.native/platform/amd64.c +++ b/com.oracle.max.vm.native/platform/amd64.c @@ -27,7 +27,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can #if os_DARWIN #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->__##reg -#elif os_LINUX || os_MAXVE || os_WINDOWS +#elif os_LINUX || os_MAXVE #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->reg #elif os_SOLARIS #define CANONICALIZE(reg, ucReg) c->reg = (Word) os[REG_##ucReg] @@ -58,7 +58,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can void isa_canonicalizeTeleFloatingPointRegisters(isa_OsTeleFloatingPointRegisters os, isa_CanonicalFloatingPointRegisters c) { #if os_DARWIN #define CANONICALIZE(reg) c->xmm##reg = (*((Word *) (&os->__fpu_xmm##reg))) -#elif os_LINUX || os_WINDOWS +#elif os_LINUX #define CANONICALIZE(reg) c->xmm##reg = (Word) ((XMMRegister *) &os->xmm_space)[reg].low #elif os_SOLARIS #define CANONICALIZE(reg) c->xmm##reg = (Word) *((Word *) &os->fp_reg_set.fpchip_state.xmm[reg]) @@ -92,7 +92,7 @@ void isa_canonicalizeTeleStateRegisters(isa_OsTeleStateRegisters os, isa_Canonic #if os_DARWIN c->rip = (Word) os->__rip; c->flags = (Word) os->__rflags; -#elif os_LINUX || os_WINDOWS +#elif os_LINUX c->rip = (Word) os->rip; c->flags = (Word) os->eflags; #elif os_SOLARIS diff --git a/com.oracle.max.vm.native/platform/amd64.h b/com.oracle.max.vm.native/platform/amd64.h index 731be34164..25f1015604 100644 --- a/com.oracle.max.vm.native/platform/amd64.h +++ b/com.oracle.max.vm.native/platform/amd64.h @@ -40,16 +40,6 @@ Word low; Word high; } XMMRegister; -#elif os_WINDOWS -//# include -# include "usercygwinamd64.h" - typedef struct user_regs_struct *amd64_OsTeleIntegerRegisters; - typedef struct user_fpregs_struct *amd64_OsTeleFloatingPointRegisters; - typedef struct user_regs_struct *amd64_OsTeleStateRegisters; - typedef struct { - Word low; - Word high; - } XMMRegister; #elif os_SOLARIS # include typedef prgreg_t *amd64_OsTeleIntegerRegisters; @@ -57,12 +47,6 @@ typedef prgreg_t *amd64_OsTeleStateRegisters; #elif os_MAXVE # include -# include - typedef struct db_regs* amd64_OsTeleIntegerRegisters; - typedef struct db_regs* amd64_OsTeleStateRegisters; - typedef struct db_regs* amd64_OsTeleFloatingPointRegisters; -#elif os_WINDOWS -# include # include typedef struct db_regs* amd64_OsTeleIntegerRegisters; typedef struct db_regs* amd64_OsTeleStateRegisters; diff --git a/com.oracle.max.vm.native/platform/arm.c b/com.oracle.max.vm.native/platform/arm.c index 8ca37e79bc..6b73ec0f9d 100644 --- a/com.oracle.max.vm.native/platform/arm.c +++ b/com.oracle.max.vm.native/platform/arm.c @@ -25,7 +25,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can #if os_DARWIN #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->__##reg -#elif os_LINUX || os_MAXVE || os_WINDOWS +#elif os_LINUX || os_MAXVE #ifdef __arm__ #define CANONICALIZE(reg, intpos) c->reg = (Word) os->uregs[intpos] #else @@ -79,7 +79,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can void isa_canonicalizeTeleFloatingPointRegisters(isa_OsTeleFloatingPointRegisters os, isa_CanonicalFloatingPointRegisters c) { #if os_DARWIN #define CANONICALIZE(reg) c->xmm##reg = (*((Word *) (&os->__fpu_xmm##reg))) -#elif os_LINUX || os_WINDOWS +#elif os_LINUX #define CANONICALIZE(reg) c->xmm##reg = (Word) ((XMMRegister *) &os->xmm_space)[reg].low #elif os_SOLARIS #define CANONICALIZE(reg) c->xmm##reg = (Word) *((Word *) &os->fp_reg_set.fpchip_state.xmm[reg]) @@ -116,7 +116,7 @@ void isa_canonicalizeTeleStateRegisters(isa_OsTeleStateRegisters os, isa_Canonic #if os_DARWIN c->rip = (Word) os->__rip; c->flags = (Word) os->__rflags; -#elif os_LINUX || os_WINDOWS +#elif os_LINUX #ifdef __arm__ log_println("ARM: isa_canonicalizeTeleStateRegisters is not implemented!"); #else diff --git a/com.oracle.max.vm.native/platform/platform.mk b/com.oracle.max.vm.native/platform/platform.mk index fe15588ab0..69221735ef 100644 --- a/com.oracle.max.vm.native/platform/platform.mk +++ b/com.oracle.max.vm.native/platform/platform.mk @@ -22,7 +22,6 @@ # # Print verbose output only when MX_VERBOSE is set to y (i.e. mx -V command is used) - ifneq ($(MX_VERBOSE), y) AT := @ MAKE := $(MAKE) -s @@ -55,8 +54,6 @@ ifneq ($(MAIN),) TARGET := LAUNCH endif -OS := windows -ISA := amd64 # HOSTOS is the platform we are compiling on HOSTOS = $(shell uname -s) # TARGETOS is the platform we are compiling for (usually the same as HOSTOS) @@ -154,9 +151,9 @@ ifeq ($(TARGETOS),SunOS) endif endif -ifeq ($(TARGETOS),WindowsNT) +ifeq ($(findstring CYGWIN,$(TARGETOS)),CYGWIN) OS := windows - ISA := amd64 + ISA := ia32 endif # There are three variants for Maxine VE, owing to the 32/64 dom0 variants @@ -313,33 +310,20 @@ ifeq ($(OS),solaris) endif ifeq ($(OS),windows) + # determine predefined macros: touch foo.c; gcc -E -dD foo.c ifneq "$(findstring def, $(origin CC))" "" # origin of CC is either undefined or default, so set it here CC = gcc endif ifneq "$(findstring def, $(origin CFLAGS))" "" # origin of CFLAGS is either undefined or default, so set it here - CFLAGS = -g -Wall -Wno-long-long -Wextra -Wno-main -Wno-unused-parameter -fPIC -D_GNU_SOURCE -D$(ISA) -DWINDOWS -D__int64=int64_t -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) $(OTHER_CFLAGS) + CFLAGS = -g -ansi -Wall -pedantic -Wno-long-long -mno-cygwin -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) endif - C_DEPENDENCIES_FLAGS = -M -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) - # The '-rpath' linker option is used so that LD_LIBRARY_PATH does not have to be configured at runtime to - # find Maxine's version of the libjvm.so library. - # The '-z execstack' is a workaround that stops the runtime dynamic linker from - # changing the protection of the main thread's stack (via mprotect) *after* the - # yellow guard page (for detecting stack overflow) has been mprotected. Without - # this flag, the main thread's complete stack (including the guard page) is - # mprotected with PROT_READ, PROT_WRITE, PROT_EXEC when dlopen() is called to - # open libjava.so. - LINK_MAIN = $(CC) -g -Xlinker -rpath -Xlinker $(shell cd $(PROJECT)/generated/$(OS) && /bin/pwd) -o $(MAIN) - - LINK_LIB = $(CC) -g -shared -mwindows - LINK_LIB_POSTFIX += -lole32 -lws2_32 - - - + C_DEPENDENCIES_FLAGS = -MM -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) + LINK_MAIN = $(CC) -g -mno-cygwin -Wall -W1,----add-stdcall-alias -ldl + LINK_LIB = $(CC) -g -shared -mno-cygwin -Wall -W1,----add-stdcall-alias LIB_PREFIX = - LIB_SUFFIX = .dll - + LIB_SUFFIX = .dll endif ifeq ($(OS),maxve) @@ -429,15 +413,9 @@ else endif JNI_INCLUDES = -I $(dir $(JNI_H_PATH)) endif - else - ifeq ($(OS),windows) - JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/win32/ - JNI_H_PATH = $(JAVA_HOME)/include/win32/jni.h - else - JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) - JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) - endif - + else + JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) + JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) endif endif diff --git a/com.oracle.max.vm.native/platform/usercygwinamd64.h b/com.oracle.max.vm.native/platform/usercygwinamd64.h deleted file mode 100644 index e1a4c0d496..0000000000 --- a/com.oracle.max.vm.native/platform/usercygwinamd64.h +++ /dev/null @@ -1,45 +0,0 @@ -struct user_fpregs_struct -{ - unsigned short int cwd; - unsigned short int swd; - unsigned short int ftw; - unsigned short int fop; - __extension__ unsigned long long int rip; - __extension__ unsigned long long int rdp; - unsigned int mxcsr; - unsigned int mxcr_mask; - unsigned int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ - unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ - unsigned int padding[24]; -}; - -struct user_regs_struct -{ - __extension__ unsigned long long int r15; - __extension__ unsigned long long int r14; - __extension__ unsigned long long int r13; - __extension__ unsigned long long int r12; - __extension__ unsigned long long int rbp; - __extension__ unsigned long long int rbx; - __extension__ unsigned long long int r11; - __extension__ unsigned long long int r10; - __extension__ unsigned long long int r9; - __extension__ unsigned long long int r8; - __extension__ unsigned long long int rax; - __extension__ unsigned long long int rcx; - __extension__ unsigned long long int rdx; - __extension__ unsigned long long int rsi; - __extension__ unsigned long long int rdi; - __extension__ unsigned long long int orig_rax; - __extension__ unsigned long long int rip; - __extension__ unsigned long long int cs; - __extension__ unsigned long long int eflags; - __extension__ unsigned long long int rsp; - __extension__ unsigned long long int ss; - __extension__ unsigned long long int fs_base; - __extension__ unsigned long long int gs_base; - __extension__ unsigned long long int ds; - __extension__ unsigned long long int es; - __extension__ unsigned long long int fs; - __extension__ unsigned long long int gs; -}; diff --git a/com.oracle.max.vm.native/share/c.h b/com.oracle.max.vm.native/share/c.h index ed33c77f61..c4add88ca4 100644 --- a/com.oracle.max.vm.native/share/c.h +++ b/com.oracle.max.vm.native/share/c.h @@ -53,12 +53,10 @@ typedef long long Signed8; typedef float Float4; typedef double Float8; -#define true 1 -#define false 0 #if !defined(false) && !defined(true) typedef enum {false, true} boolean; #else - typedef unsigned char boolean; + typedef int boolean; #endif #define MAX_PATH_LENGTH 2048 diff --git a/com.oracle.max.vm.native/share/condition.c b/com.oracle.max.vm.native/share/condition.c index b8b8feac0c..90e052fcfe 100644 --- a/com.oracle.max.vm.native/share/condition.c +++ b/com.oracle.max.vm.native/share/condition.c @@ -18,15 +18,6 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "os.h" -#if os_WINDOWS -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT 0x0600 // needed for tools like MINGW in order to use condition variables which became available from Windows Vista and on. Visual Studio might define it on its own -#include - -#endif #include #include #include @@ -54,10 +45,6 @@ void condition_initialize(Condition condition) { } #elif os_MAXVE *condition = maxve_condition_create(); -#elif os_WINDOWS - InitializeConditionVariable(condition); - //initialize condtionVariable does not return anything! - #else # error #endif @@ -75,8 +62,6 @@ void condition_destroy(Condition condition) { if (pthread_cond_destroy(condition) != 0) { c_FATAL(); } -#elif os_WINDOWS -//condition variables cannot get destroyed https://stackoverflow.com/questions/28975958/why-does-windows-have-no-deleteconditionvariable-function-to-go-together-with #endif } @@ -95,7 +80,7 @@ void condition_destroy(Condition condition) { * @return false if an error occurred, true otherwise (i.e. the thread was notified or interrupted). * In either case, the current thread has reacquired the lock on 'mutex'. */ -boolean condition_wait(Condition condition, Mutex mutex) { //mutex is not needed in windows +boolean condition_wait(Condition condition, Mutex mutex) { #if log_MONITORS log_println("condition_wait (" THREAD_CONDVAR_MUTEX_FORMAT ")", thread_self(), condition, mutex); #endif @@ -116,8 +101,6 @@ boolean condition_wait(Condition condition, Mutex mutex) { //mutex is not needed /* (Doug) I assume 1 means EINTR */ return true; } -#elif os_WINDOWS - error = !SleepConditionVariableCS (condition, mutex, INFINITE); // non zero return value means success on Windows! #endif if (error != 0) { log_println("condition_wait (" THREAD_CONDVAR_MUTEX_FORMAT ") unexpected error code %d [%s]", thread_self(), condition, mutex, error, strerror(error)); @@ -129,7 +112,7 @@ boolean condition_wait(Condition condition, Mutex mutex) { //mutex is not needed return true; } -#if (os_DARWIN || os_LINUX ) +#if (os_DARWIN || os_LINUX) /* * This function is taken from HotSpot (os_linux.cpp). */ @@ -176,7 +159,7 @@ boolean condition_timedWait(Condition condition, Mutex mutex, Unsigned8 timeoutM log_println("condition_timedWait (" THREAD_CONDVAR_MUTEX_FORMAT ", %d)", thread_self(), condition, mutex, timeoutMilliSeconds); #endif int error; -#if (os_DARWIN || os_LINUX ) +#if (os_DARWIN || os_LINUX) struct timeval now; int status = gettimeofday(&now, NULL); c_ASSERT(status != -1); @@ -215,8 +198,6 @@ boolean condition_timedWait(Condition condition, Mutex mutex, Unsigned8 timeoutM /* (Doug) I assume 1 means EINTR */ return true; } -#elif os_WINDOWS - error = !SleepConditionVariableCS (condition, mutex, timeoutMilliSeconds); // non zero return value means success on Windows! #else # error #endif @@ -241,9 +222,6 @@ boolean condition_notify(Condition condition) { return cond_signal(condition) == 0; #elif os_MAXVE return maxve_condition_notify(*condition, 0) == 0; -#elif os_WINDOWS - WakeConditionVariable (condition); //WakeConditionVariable returns nothing - return true; #else # error #endif @@ -253,15 +231,12 @@ boolean condition_notifyAll(Condition condition) { #if log_MONITORS log_println("condition_notifyAll (" THREAD_CONDVAR_FORMAT ")", thread_self(), condition); #endif -#if (os_DARWIN || os_LINUX ) +#if (os_DARWIN || os_LINUX) return pthread_cond_broadcast(condition) == 0; #elif os_SOLARIS return cond_broadcast(condition) == 0; #elif os_MAXVE return maxve_condition_notify(*condition, 1) == 0; -#elif os_WINDOWS - WakeAllConditionVariable (condition); //WakeAllConditionVariable returns nothing - return true; #else # error #endif diff --git a/com.oracle.max.vm.native/share/condition.h b/com.oracle.max.vm.native/share/condition.h index 953fa41c4b..93c379f5ca 100644 --- a/com.oracle.max.vm.native/share/condition.h +++ b/com.oracle.max.vm.native/share/condition.h @@ -36,10 +36,6 @@ #elif os_MAXVE # include "maxve.h" typedef maxve_condition_t condition_Struct; -#elif os_WINDOWS - typedef CONDITION_VARIABLE condition_Struct; - - #endif typedef condition_Struct *Condition; diff --git a/com.oracle.max.vm.native/share/log.c b/com.oracle.max.vm.native/share/log.c index 5e5a04a828..a5bedc320a 100644 --- a/com.oracle.max.vm.native/share/log.c +++ b/com.oracle.max.vm.native/share/log.c @@ -18,28 +18,17 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - - #include #include #include #include - -#include "log.h" -#if os_WINDOWS -#include -#define pthread_self GetCurrentThread -#else #include -#endif - +#include "log.h" #include "jni.h" #include "mutex.h" #include "threads.h" - - #if !os_MAXVE static FILE *fileStream = NULL; #endif @@ -57,14 +46,14 @@ static mutex_Struct allocationProfiler_mutexStruct; void log_initialize(const char *path) { mutex_initialize(&log_mutexStruct); mutex_initialize(&allocationProfiler_mutexStruct); -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE if (path == NULL) { path = "stdout"; } if (strncmp(path, "stdout\0", 7) == 0) { fileStream = stdout; /* Set the file stream to flush whenever a newline character is encountered */ - // setlinebuf(fileStream); + setlinebuf(fileStream); } else if (strncmp(path, "stderr\0", 7) == 0) { fileStream = stderr; } else { @@ -74,7 +63,7 @@ void log_initialize(const char *path) { exit(1); } /* Set the file stream to flush whenever a newline character is encountered */ - // setlinebuf(fileStream); + setlinebuf(fileStream); } #endif } @@ -82,7 +71,7 @@ void log_initialize(const char *path) { void log_lock(void) { int result; if ((result = mutex_enter_nolog(&log_mutexStruct)) != 0) { - log_exit(-1, "Thread %d could not lock mutex %p: %s", pthread_self(), &log_mutexStruct, strerror(result)); + log_exit(-1, "Thread %p could not lock mutex %p: %s", thread_self(), &log_mutexStruct, strerror(result)); } } @@ -90,14 +79,14 @@ void numaProfiler_lock(void) { int result; result = mutex_enter_nolog(&allocationProfiler_mutexStruct); if (result != 0) { - log_exit(-1, "Thread %d could not lock mutex %p: %s", pthread_self(), &allocationProfiler_mutexStruct, strerror(result)); + log_exit(-1, "Thread %p could not lock mutex %p: %s", thread_self(), &allocationProfiler_mutexStruct, strerror(result)); } } void log_unlock(void) { int result; if ((result = mutex_exit_nolog(&log_mutexStruct)) != 0) { - log_exit(-1, "Thread %d could not unlock mutex %p: %s", pthread_self(), &log_mutexStruct, strerror(result)); + log_exit(-1, "Thread %p could not unlock mutex %p: %s", thread_self(), &log_mutexStruct, strerror(result)); } } @@ -105,7 +94,7 @@ void numaProfiler_unlock(void) { int result; result = mutex_exit_nolog(&allocationProfiler_mutexStruct); if (result != 0) { - log_exit(-1, "Thread %d could not unlock mutex %p: %s", pthread_self(), &allocationProfiler_mutexStruct, strerror(result)); + log_exit(-1, "Thread %p could not unlock mutex %p: %s", thread_self(), &allocationProfiler_mutexStruct, strerror(result)); } } @@ -122,14 +111,14 @@ void log_print_format(const char *format, ...) { } void log_flush() { -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE FILE* out = fileStream == NULL ? stdout : fileStream; fflush(out); #endif } void log_print_vformat(const char *format, va_list ap) { -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE FILE* out = fileStream == NULL ? stdout : fileStream; vfprintf(out, format, ap); #else @@ -208,8 +197,8 @@ void log_print_newline() { } void log_print_symbol(Address address) { -#if !os_MAXVE && !os_WINDOWS - Dl_info info; +#if !os_MAXVE + Dl_info info; if (dladdr((void *) address, &info) != 0) { if (info.dli_sname == NULL) { log_print("%s (%p+%d)", info.dli_fname, info.dli_fbase, address - (Address) info.dli_fbase); diff --git a/com.oracle.max.vm.native/share/mutex.c b/com.oracle.max.vm.native/share/mutex.c index 3ed0431939..4902d146fc 100644 --- a/com.oracle.max.vm.native/share/mutex.c +++ b/com.oracle.max.vm.native/share/mutex.c @@ -20,11 +20,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -#include "os.h" -#if os_WINDOWS -#include -#endif - #include "mutex.h" #include "log.h" #include "threads.h" @@ -55,8 +50,6 @@ void mutex_initialize(Mutex mutex) { } #elif os_MAXVE *mutex = maxve_monitor_create(); -#elif os_WINDOWS - InitializeCriticalSection(mutex); //windows CS's are recursive be default ,mutex is pointer to Critical section # else c_UNIMPLEMENTED(); # endif @@ -72,9 +65,6 @@ int mutex_enter_nolog(Mutex mutex) { c_ASSERT(false); } return 0; -#elif os_WINDOWS - EnterCriticalSection(mutex); //mutex is pointer to Critical section. EnterCriticalSection returns nothing - return 0; //0 means success for funcs like pthread_mutex_lock #else c_UNIMPLEMENTED(); #endif @@ -83,11 +73,8 @@ int mutex_enter_nolog(Mutex mutex) { int mutex_try_enter(Mutex mutex) { #if os_SOLARIS return mutex_trylock(mutex); -#elif os_LINUX || os_DARWIN +#elif os_LINUX || os_DARWIN return pthread_mutex_trylock(mutex); -#elif os_WINDOWS - return !TryEnterCriticalSection(mutex); //mutex is pointer to Critical section. On windows non zero return value means success that's why we use ! at the result - #else c_UNIMPLEMENTED(); #endif @@ -111,9 +98,6 @@ int mutex_exit_nolog(Mutex mutex) { c_ASSERT(false); } return 0; -#elif os_WINDOWS - LeaveCriticalSection(mutex); //mutex is pointer to Critical section - return 0; #else c_UNIMPLEMENTED(); #endif @@ -140,8 +124,5 @@ void mutex_dispose(Mutex mutex) { } #elif os_MAXVE c_UNIMPLEMENTED(); -#elif os_WINDOWS - DeleteCriticalSection(mutex); //mutex is pointer to Critical section - #endif } diff --git a/com.oracle.max.vm.native/share/mutex.h b/com.oracle.max.vm.native/share/mutex.h index 68ebec04de..962941271a 100644 --- a/com.oracle.max.vm.native/share/mutex.h +++ b/com.oracle.max.vm.native/share/mutex.h @@ -35,9 +35,8 @@ #elif os_MAXVE # include typedef maxve_monitor_t mutex_Struct; -#elif os_WINDOWS -typedef CRITICAL_SECTION mutex_Struct; #endif + typedef mutex_Struct *Mutex; extern void mutex_initialize(Mutex mutex); diff --git a/com.oracle.max.vm.native/share/threadLocals.c b/com.oracle.max.vm.native/share/threadLocals.c index 11b7a7ea24..5868340538 100644 --- a/com.oracle.max.vm.native/share/threadLocals.c +++ b/com.oracle.max.vm.native/share/threadLocals.c @@ -18,14 +18,7 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "os.h" -#if !os_WINDOWS - #include -#else - #include - #include - #define aligned_alloc(a, b) _aligned_malloc(a, b) -#endif +#include #include #include @@ -55,9 +48,6 @@ typedef maxve_Thread Thread; typedef maxve_SpecificsKey ThreadLocalsKey; typedef void (*ThreadLocalsBlockDestructor)(void *); -#elif os_WINDOWS - typedef DWORD ThreadLocalsKey; - #endif int theTLASize = -1; @@ -96,7 +86,7 @@ static void deallocateThreadLocalBlock(Address tlBlock, Size tlBlockSize) { * lazily commit memory reserved for the initial thread's stack. */ static void commitStackMemoryForInitialThread(Address base, int pageSize) { -#if os_LINUX || os_WINDOWS +#if os_LINUX /* Writing to the bottom page of the reserved stack (appears) not to be * sufficient on Linux. Using alloca() to allocate a chunk approximately * the size of the remaining stack seems to fix it. */ @@ -357,7 +347,7 @@ void threadLocalsBlock_destroy(Address tlBlock) { void tla_initialize(int tlaSize) { theTLASize = tlaSize; #if !TELE -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX int error = pthread_key_create(&theThreadLocalsKey, (ThreadLocalsBlockDestructor)(void *) threadLocalsBlock_destroy); #if log_THREADS log_println("tla_initialize: pthread_key_create returned code = %d", error); @@ -365,8 +355,6 @@ void tla_initialize(int tlaSize) { if (error != 0) { log_exit(-1, "tla_initialize: pthread_key_create returned non zero code = %d", error); } -#elif os_WINDOWS - theThreadLocalsKey = TlsAlloc(); #elif os_SOLARIS thr_keycreate(&theThreadLocalsKey, (ThreadLocalsBlockDestructor) threadLocalsBlock_destroy); #elif os_MAXVE @@ -380,7 +368,7 @@ void tla_initialize(int tlaSize) { Address threadLocalsBlock_current() { Address tlBlock; -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX tlBlock = (Address) pthread_getspecific(theThreadLocalsKey); #elif os_SOLARIS Address value; @@ -391,8 +379,6 @@ Address threadLocalsBlock_current() { tlBlock = value; #elif os_MAXVE tlBlock = (Address) maxve_thread_getSpecific(theThreadLocalsKey); -#elif os_WINDOWS - tlBlock = (Address) TlsGetValue(theThreadLocalsKey); #else c_UNIMPLEMENTED(); #endif @@ -400,14 +386,12 @@ Address threadLocalsBlock_current() { } void threadLocalsBlock_setCurrent(Address tlBlock) { -#if (os_DARWIN || os_LINUX ) +#if (os_DARWIN || os_LINUX) pthread_setspecific(theThreadLocalsKey, (void *) tlBlock); #elif os_SOLARIS thr_setspecific(theThreadLocalsKey, (void *) tlBlock); #elif os_MAXVE maxve_thread_setSpecific(theThreadLocalsKey, (void *) tlBlock); -#elif os_WINDOWS - TlsSetValue(theThreadLocalsKey, (LPVOID) tlBlock); #endif } diff --git a/com.oracle.max.vm.native/share/threads.h b/com.oracle.max.vm.native/share/threads.h index 63b48db454..f360882742 100644 --- a/com.oracle.max.vm.native/share/threads.h +++ b/com.oracle.max.vm.native/share/threads.h @@ -80,13 +80,8 @@ typedef void (*VmThreadDetachMethod)(Address tla); * @return true if the sleep was interrupted */ extern jboolean thread_sleep(jlong numberOfMilliSeconds); -#if os_WINDOWS -DWORD WINAPI thread_run(LPVOID param); -#else - -void * thread_run(void *arg); -#endif +void *thread_run(void *arg); int thread_attachCurrent(void **penv, JavaVMAttachArgs* args, boolean daemon); int thread_detachCurrent(); diff --git a/com.oracle.max.vm.native/share/virtualMemory.c b/com.oracle.max.vm.native/share/virtualMemory.c index 5ef4152e04..1846d69f03 100644 --- a/com.oracle.max.vm.native/share/virtualMemory.c +++ b/com.oracle.max.vm.native/share/virtualMemory.c @@ -18,28 +18,18 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - - #include "virtualMemory.h" #include "log.h" - #if defined(MAXVE) - #include +#include /* No mmap function on MaxVE (yet)*/ #else - #include - #include - #include - #if !os_WINDOWS - #include - #else - #ifdef _WIN32_WINNT - #undef _WIN32_WINNT - #endif - #define _WIN32_WINNT 0x0601 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. - #include - #endif +#include +#include +#include +#include + #include "jni.h" #include "unistd.h" @@ -49,7 +39,7 @@ #endif /* There is a problem binding these identifiers in RedHat's include files, so we fake them: */ -#if os_LINUX || os_WINDOWS +#if os_LINUX # ifndef MAP_ANONYMOUS # define MAP_ANONYMOUS 0x20 # endif @@ -68,16 +58,11 @@ # define MAP_32BIT 0 # endif #endif -#if !os_WINDOWS -#define PROT (PROT_EXEC | PROT_READ | PROT_WRITE) -#endif -#if !os_WINDOWS //we do not use mmap on Windows so this function is not needed. +#define PROT (PROT_EXEC | PROT_READ | PROT_WRITE) /* mmap returns MAP_FAILED on error, we convert to ALLOC_FAILED */ static Address check_mmap_result(void *result) { - - #if log_MMAP if(result == MAP_FAILED) { switch(errno) { @@ -114,11 +99,8 @@ static Address check_mmap_result(void *result) { } } #endif - return ((Address) (result == (void *) MAP_FAILED ? ALLOC_FAILED : result)); } -#endif - #ifdef arm static int attempt = 0; @@ -143,36 +125,8 @@ Address virtualMemory_allocatePrivateAnon(Address address, Size size, jboolean r address = allocAddress; } #endif -#if os_WINDOWS - //Windows got no Swap space, so jboolean reserveSwap is redundant - Address result; - if(protNone == JNI_TRUE){ - - result = (Address) VirtualAlloc( (void *) address, size, MEM_COMMIT | MEM_RESERVE| PAGE_WRITECOPY, PAGE_NOACCESS); - - //virtualalloc is the only win32 function that supports the PROT_NONE equivalent PAGE_NOACCESS - //PAGE_WRITECOPY is equivalent to MAP_PRIVATE - if(!result) - log_println("%d\n", GetLastError()); - } - else { - //if protnone is not used, we can use CreateFileMappingA + MapViewOfFile combination to emulate mmap() on Windows - //INVALID_HANDLE_VALUE means that we dont use an actual file but the system pagefile, similar to fd= -1 & MPI_ANON in mmap() - HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); - //FILE_MAP_COPY is equivalent to MAP_PRIVATE -if(!fmapping) - log_println("%d\n", GetLastError()); - result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, 0, 0, size, (LPVOID)address); - if(!result) - log_println("%d\n", GetLastError()); - - - } - return result; - -#else int flags = MAP_PRIVATE | MAP_ANON; -#if os_LINUX +#if os_LINUX /* For some reason, subsequent calls to mmap to allocate out of the space * reserved here only work if the reserved space is in 32-bit space. */ #endif @@ -199,7 +153,6 @@ if(!fmapping) #else return check_mmap_result(result); #endif -#endif } @@ -219,15 +172,6 @@ Address virtualMemory_mapFile(Size size, jint fd, Size offset) { address = check_mmap_result(result); allocAddress = address + size; return address; -#elif os_WINDOWS - HANDLE fmapping = CreateFileMappingA( (HANDLE)_get_osfhandle(fd) , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); - //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA - Address result = (Address) MapViewOfFile (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size); - //FILE_MAP_COPY is equivalent to mmap's MAP_PRIVATE. It maps a copy-on-write view of the file that is private to the process. - //MapViewOfFile needs lower and high order of offset (last and first 32 bits). We get high and lower orders of the offset (which might be 64bit long) by doing casts to DWORD( 32 BITS) and Binary shifts - if(!result) - log_println("%d\n", GetLastError()); - return result; #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_PRIVATE, fd, (off_t) offset)); #endif @@ -239,20 +183,7 @@ Java_com_sun_max_memory_VirtualMemory_virtualMemory_1mapFile(JNIEnv *env, jclass } Address virtualMemory_mapFileIn31BitSpace(jint size, jint fd, Size offset) { - #if os_WINDOWS //MAP_32BIT is not supported on Windows.... Also in Linux, it is no longer really needed - /*"It was added to allow thread stacks to be - allocated somewhere in the first 2 GB of memory, so as to - improve context-switch performance on some early 64-bit - processors. Modern x86-64 processors no longer have this - performance problem, so use of this flag is not required on - those systems. - - https://man7.org/linux/man-pages/man2/mmap.2.html - */ - return virtualMemory_mapFile(size, fd, offset); - #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_PRIVATE | MAP_32BIT, fd, (off_t) offset)); - #endif } JNIEXPORT jlong JNICALL @@ -261,20 +192,7 @@ Java_com_sun_max_memory_VirtualMemory_virtualMemory_1mapFileIn31BitSpace(JNIEnv } Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, Size offset) { - #if os_WINDOWS - HANDLE fmapping = CreateFileMappingA( (HANDLE)_get_osfhandle(fd) , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,0, NULL); - //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA - if(!fmapping) - log_println("%d\n", GetLastError()); - Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size,(LPVOID) address); - //the only diffrence is that we use MapViewOfFileEx instead MapViewOfFile. The first one allows us to provide an initial base address where the mapping begins (last argument) - - if(!result) - log_println("%d\n", GetLastError()); - return result; - #else return check_mmap_result(mmap((void *) address, (size_t) size, PROT, MAP_PRIVATE | MAP_FIXED, fd, (off_t) offset)); - #endif } // end of conditional exclusion of mmap stuff not available (or used) on MAXVE @@ -284,23 +202,14 @@ Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, Address virtualMemory_allocate(Size size, int type) { #if os_MAXVE return (Address) maxve_virtualMemory_allocate(size, type); -#elif os_WINDOWS - HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); - Address result = (Address) MapViewOfFile (fmapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size); - if(!result) - log_println("%d\n", GetLastError()); - return result; #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)); #endif } Address virtualMemory_allocateIn31BitSpace(Size size, int type) { -#if os_LINUX +#if os_LINUX return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1, (off_t) 0)); - -#elif os_WINDOWS - return virtualMemory_allocate(size, type); //windows do not have equivalent of MAP_32BIT, also obsolete in Linux #elif os_MAXVE return (Address) maxve_virtualMemory_allocateIn31BitSpace(size, type); #else @@ -312,17 +221,6 @@ Address virtualMemory_allocateIn31BitSpace(Size size, int type) { Address virtualMemory_deallocate(Address start, Size size, int type) { #if os_MAXVE return (Address) maxve_virtualMemory_deallocate((void *)start, size, type); -#elif os_WINDOWS - if( UnmapViewOfFile((LPVOID) start) == 0){ // VirtualFree will fail for addresses mapped with MapViewOfFile so we use UnmapViewOfFile first - int result = VirtualFree((LPVOID)start, size, type); //if UnmapViewOfFile failed, we try virtualalloc (the memory might got mapped with VirtualAlloc) - //type can be MEM_RELEASE or whatever the user provides. (It was implemented for MAXVE that way) - if (!result) - return result; - else - return start; - } - else - return start; #else int result = munmap((void *) start, (size_t) size); return result == -1 ? 0 : start; @@ -332,13 +230,6 @@ Address virtualMemory_deallocate(Address start, Size size, int type) { boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int type) { #if os_SOLARIS || os_DARWIN || os_LINUX return check_mmap_result(mmap((void *) address, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, (off_t) 0)) != ALLOC_FAILED; -#elif os_WINDOWS - HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); - //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA - Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, 0, 0, size,(LPVOID) address); - if(!result) - log_println("%d\n", GetLastError()); - return result; #elif os_MAXVE return (Address) maxve_virtualMemory_allocateAtFixedAddress((unsigned long)address, size, type) != ALLOC_FAILED; #else @@ -350,18 +241,11 @@ boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int typ void virtualMemory_protectPages(Address address, int count) { /* log_println("--- protected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ c_ASSERT(virtualMemory_pageAlign(address) == address); -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_NONE) != 0) { int error = errno; log_exit(error, "protectPages: mprotect(%p) failed: %s", address, strerror(error)); } -#elif os_WINDOWS - DWORD old; //needed for VirtualProtect - int error = GetLastError(); - if(!VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_NOACCESS, &old)) //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) - log_exit(error, "protectPages: VirtualProtect(%p) failed", address); - - #elif os_MAXVE maxve_virtualMemory_protectPages(address, count); #else @@ -372,14 +256,11 @@ void virtualMemory_protectPages(Address address, int count) { void virtualMemory_unprotectPages(Address address, int count) { /* log_println("--- unprotected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ c_ASSERT(virtualMemory_pageAlign(address) == address); -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_READ| PROT_WRITE) != 0) { int error = errno; log_exit(error, "unprotectPages: mprotect(%p) failed: %s", address, strerror(error)); } -#elif os_WINDOWS - DWORD old; //needed for VirtualProtect - VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_READWRITE, &old); //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) #elif os_MAXVE maxve_virtualMemory_unProtectPages(address, count); #else @@ -395,13 +276,7 @@ unsigned int virtualMemory_getPageSize(void) { return maxve_virtualMemory_pageSize(); #else if (pageSize == 0) { - #if os_WINDOWS - SYSTEM_INFO systemInfo = {0}; - GetSystemInfo(&systemInfo); - pageSize = systemInfo.dwPageSize ; - #else pageSize = getpagesize(); - #endif } return pageSize; #endif @@ -412,12 +287,9 @@ Size virtualMemory_getPhysicalMemorySize(void) { #if os_MAXVE // TODO return 0; -#elif os_SOLARIS || os_LINUX +#elif os_SOLARIS || os_LINUX Size numPhysicalPages = (Size) sysconf(_SC_PHYS_PAGES); physicalMemory = numPhysicalPages * virtualMemory_getPageSize(); -#elif os_WINDOWS - GetPhysicallyInstalledSystemMemory(&physicalMemory); - return physicalMemory * 1024; //we want bytes #elif os_DARWIN int query[2]; query[0] = CTL_HW; diff --git a/com.oracle.max.vm.native/substrate/barrier.c b/com.oracle.max.vm.native/substrate/barrier.c index 20fbdcd928..86bb92ad9d 100644 --- a/com.oracle.max.vm.native/substrate/barrier.c +++ b/com.oracle.max.vm.native/substrate/barrier.c @@ -1,4 +1,6 @@ /* + * Copyright (c) 2020, APT Group, Department of Computer Science, + * School of Engineering, The University of Manchester. All rights reserved. * Copyright (c) 2019, APT Group, School of Computer Science, * The University of Manchester. All rights reserved. * @@ -38,7 +40,7 @@ /* * Pre-processor override for whether to compile in the membarrier system call. - * Currently only affects Aarch64. See syscall_membarrier() in this compilation + * Currently only affects Aarch64 and RISCV64. See syscall_membarrier() in this compilation * unit. */ #ifndef USE_SYS_MEMBARRIER @@ -62,7 +64,7 @@ static int membarrier_init(void) __attribute__ ((unused)); void syscall_membarrier() { -#if isa_AARCH64 +#if isa_AARCH64 || isa_RISCV64 # if USE_SYS_MEMBARRIER static volatile int barrier_kind = 0; if (!barrier_kind) { diff --git a/com.oracle.max.vm.native/substrate/image.c b/com.oracle.max.vm.native/substrate/image.c index 198ea69f91..9825dd7ab9 100644 --- a/com.oracle.max.vm.native/substrate/image.c +++ b/com.oracle.max.vm.native/substrate/image.c @@ -20,13 +20,10 @@ */ #include "os.h" - #include #include #include -#if !os_WINDOWS #include -#endif #include #include @@ -280,7 +277,7 @@ static void checkTrailer(int fd) { if (trailerStructPtr->identification != theHeader->identification || trailerStructPtr->bootImageFormatVersion != theHeader->bootImageFormatVersion || trailerStructPtr->randomID != theHeader->randomID) { log_println("inconsistent trailer"); #if !MEMORY_IMAGE - offset = lseek(fd, (long int)-sizeof(trailerStruct), SEEK_END); + offset = lseek(fd, -sizeof(trailerStruct), SEEK_END); if (offset != fileSize - (off_t) sizeof(trailerStruct)) { log_exit(1, "could not set trailer position at end of file"); } @@ -307,7 +304,7 @@ static void mapHeapAndCode(int fd) { #endif #if MEMORY_IMAGE theHeap = (Address) &maxvm_image_start + heapOffsetInImage; -#elif os_SOLARIS || os_DARWIN || os_LINUX || os_WINDOWS +#elif os_SOLARIS || os_DARWIN || os_LINUX Address reservedVirtualSpace = (Address) 0; size_t virtualSpaceSize = 1024L * theHeader->reservedVirtualSpaceSize; c_ASSERT(virtualMemory_pageAlign((Size) virtualSpaceSize) == (Size) virtualSpaceSize); @@ -335,7 +332,7 @@ static void mapHeapAndCode(int fd) { log_exit(4, "could not reserve virtual space for boot image"); } } - if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { //CAUTION on Windows, the Base Address must be a multiple of dwAllocationGranularity else mapping fails (UNTESTED since no image file is availabe) + if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { log_exit(4, "could not map boot image"); } if (reservedVirtualSpace) { @@ -422,7 +419,7 @@ void image_load(char *imageFileName) { } #endif - readHeader(fd); + readHeader(fd); checkImage(); readStringInfo(fd); checkTrailer(fd); diff --git a/com.oracle.max.vm.native/substrate/jni.c b/com.oracle.max.vm.native/substrate/jni.c index a18a76141b..871108e597 100644 --- a/com.oracle.max.vm.native/substrate/jni.c +++ b/com.oracle.max.vm.native/substrate/jni.c @@ -26,10 +26,7 @@ * arguments in such an array. This isolates the implementation of such functions * from the platform/compiler dependent way in which varargs are implemented. */ -#include "os.h" -#if os_WINDOWS -#include -#endif +#include #include #include #include @@ -40,9 +37,7 @@ #include "threads.h" #include "vm.h" -#if !os_WINDOWS -#include -#endif + #ifndef JNI_VERSION_1_6 #error The version of jni.h being included must define the JNI_VERSION_1_6 macro #endif @@ -813,15 +808,11 @@ jint JNICALL jni_GetEnv(JavaVM *javaVM, void **penv, jint version) { return JNI_OK; } } -#if os_WINDOWS -__declspec( dllimport ) -#endif + jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) { return c_UNIMPLEMENTED(); } -#if os_WINDOWS -__declspec( dllimport ) -#endif + jint JNICALL jni_DestroyJavaVM(JavaVM *vm) { return c_UNIMPLEMENTED(); } @@ -838,9 +829,7 @@ jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { return thread_detachCurrent(); } -#if os_WINDOWS -__declspec( dllimport ) -#endif + jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { return c_UNIMPLEMENTED(); } @@ -868,7 +857,7 @@ JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs_Impl(JavaVM **vm, jsize vmBufLen, j return JNI_OK; } -JNIEXPORT jint JNICALL __imp_JNI_GetCreatedJavaVMs(JavaVM **vm, jsize vmBufLen, jsize *nVMs) { +JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm, jsize vmBufLen, jsize *nVMs) { return JNI_GetCreatedJavaVMs_Impl(vm, vmBufLen, nVMs); } diff --git a/com.oracle.max.vm.native/substrate/jvm.c b/com.oracle.max.vm.native/substrate/jvm.c index 0fd63eb587..c2eab15fbc 100644 --- a/com.oracle.max.vm.native/substrate/jvm.c +++ b/com.oracle.max.vm.native/substrate/jvm.c @@ -26,70 +26,39 @@ * In cases where we bypass JDK's native libraries (@see com.sun.max.vm.jdk) * we can simply omit unneeded JVM interface functions that would otherwise occur here. */ -#include "os.h" -#if os_WINDOWS -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT 0x0600 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. -#include -#include -#define lseek64 _lseeki64 -#define open _open -#define close _close //open and close work on mingw but are deprecated in MSVC so we better use _ before the name. (Internally, they call win32 funcs like CreateFile() and are added by Microsoft for POSIX compatibility -#define ftruncate _chsize -#define ioctl(a, b, c) ioctlsocket(a, b, (u_long *) c) -#include -#endif - - - - -#include "vm.h" -#include "log.h" -#include "trap.h" -#include "mutex.h" -#include "threads.h" -#include "maxine.h" -#include "memory.h" - -#if !os_WINDOWS - +#include #include #include #include - - +#include +#include #include #include #include #include -#endif -#include - -#include -#include - #if os_DARWIN #include -#elif !os_WINDOWS +#else #include #endif -#if !os_WINDOWS -#include -#endif +#include "vm.h" +#include "log.h" +#include "trap.h" +#include "mutex.h" +#include "threads.h" +#include "maxine.h" +#include "memory.h" #if os_SOLARIS #include #endif -#if os_DARWIN +#if os_DARWIN #define lseek64 lseek #include -#endif -#include +#endif // Platform-independent error return values from OS functions @@ -284,7 +253,7 @@ JVM_ActiveProcessorCount(void) { } // Otherwise return number of online cpus return online_cpus; -#elif os_LINUX +#elif os_LINUX cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors int cpus_size = sizeof(cpu_set_t); int processor_count = sysconf(_SC_NPROCESSORS_CONF); @@ -310,11 +279,6 @@ JVM_ActiveProcessorCount(void) { int online_cpus = sysconf(_SC_NPROCESSORS_ONLN); c_ASSERT(online_cpus > 0); return online_cpus; -#elif os_WINDOWS - SYSTEM_INFO systemInfo = {0}; - GetSystemInfo(&systemInfo); - return systemInfo.dwNumberOfProcessors; //not sure if we need logical or physical processors - //alternatively we can read NUMBER_OF_PROCESSORS environment variable #else UNIMPLEMENTED(); return 0; @@ -323,15 +287,12 @@ JVM_ActiveProcessorCount(void) { #if os_SOLARIS || os_LINUX || os_DARWIN #include - #endif void * JVM_LoadLibrary(const char *name) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN return dlopen(name, RTLD_LAZY); -#elif os_WINDOWS - return LoadLibraryA(name); #else UNIMPLEMENTED(); return 0; @@ -342,8 +303,6 @@ void JVM_UnloadLibrary(void * handle) { #if os_SOLARIS || os_LINUX || os_DARWIN dlclose(handle); -#elif os_WINDOWS - FreeLibrary(handle); #else UNIMPLEMENTED(); #endif @@ -351,10 +310,8 @@ JVM_UnloadLibrary(void * handle) { void * JVM_FindLibraryEntry(void *handle, const char *name) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN return dlsym(handle, name); -#elif os_WINDOWS - return GetProcAddress(handle, name); #else UNIMPLEMENTED(); return 0; @@ -486,9 +443,7 @@ JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name) { /* Same as JDK7u4 (and before): do nothing as not yet implemented on either Solaris / Linux */ #endif } -#if os_WINDOWS //Microsot uses an empty Yield() Macro (obsolete, not needed) in windows.h which breaks our code so we need to undef it. -#undef Yield -#endif + void JVM_Yield(JNIEnv *env, jclass threadClass) { vm.Yield(env); @@ -636,7 +591,7 @@ JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index) { jvalue JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode) { UNIMPLEMENTED_WITH_ENV(); - return (jvalue) (jint)0; + return (jvalue) 0; } void @@ -770,9 +725,7 @@ JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, /* * Reflection support functions */ -#if os_WINDOWS //Microsot defines GetClassName as GetClassNameA in windows.h which breaks our code so we need to undef it. -#undef GetClassName -#endif + jstring JVM_GetClassName(JNIEnv *env, jclass cls) { return vm.GetClassName(env, cls); @@ -1131,37 +1084,36 @@ JVM_RaiseSignal(jint sig) { if (kill(getpid(), sig) < 0) { log_println("error raising signal %d in current process: %s", sig, strerror(errno)); } -#elif os_WINDOWS - if(raise(sig)) - log_println("error raising signal %d in current process: %s", sig, strerror(errno)); - #else UNIMPLEMENTED(); #endif return JNI_TRUE; } -#if os_DARWIN || os_LINUX || os_WINDOWS +#if os_DARWIN || os_LINUX typedef struct { const char *name; int number; } Signal; Signal signals[] = { - #if !os_WINDOWS {"HUP", SIGHUP}, - + {"INT", SIGINT}, {"QUIT", SIGQUIT}, {"ILL", SIGILL}, {"TRAP", SIGTRAP}, + {"ABRT", SIGABRT}, #if os_DARWIN {"EMT", SIGEMT}, #endif + {"FPE", SIGFPE}, {"KILL", SIGKILL}, {"BUS", SIGBUS}, + {"SEGV", SIGSEGV}, {"SYS", SIGSYS}, {"PIPE", SIGPIPE}, {"ALRM", SIGALRM}, + {"TERM", SIGTERM}, {"URG", SIGURG}, {"STOP", SIGSTOP}, {"TSTP", SIGTSTP}, @@ -1180,23 +1132,12 @@ Signal signals[] = { #endif {"USR1", SIGUSR1}, {"USR2", SIGUSR2}, - - - #endif - {"ABRT", SIGABRT}, - {"FPE", SIGFPE}, - {"ILL", SIGILL}, - {"INT", SIGINT}, - {"SEGV", SIGSEGV}, - {"TERM", SIGTERM}, - - }; #endif jint JVM_FindSignal(const char *name) { -#if os_DARWIN || os_LINUX || os_WINDOWS +#if os_DARWIN || os_LINUX unsigned int i; for (i = 0; i < ARRAY_LENGTH(signals); i++) { if(!strcmp(name, signals[i].name)) { @@ -1863,7 +1804,7 @@ jint JVM_GetLastErrorString(char *buffer, size_t length) { if (errno == 0) { return 0; } -#if os_DARWIN || os_SOLARIS || os_LINUX || os_WINDOWS +#if os_DARWIN || os_SOLARIS || os_LINUX const char *s = strerror(errno); size_t n = strlen(s); if (n >= length) { @@ -1885,7 +1826,7 @@ jint JVM_GetLastErrorString(char *buffer, size_t length) { */ char *JVM_NativePath(char *path) { jvmni_log_println("JVM_NativePath(%s)", path); -#if os_DARWIN || os_SOLARIS || os_LINUX || os_WINDOWS +#if os_DARWIN || os_SOLARIS || os_LINUX return path; #else UNIMPLEMENTED(); @@ -1961,7 +1902,6 @@ JVM_Write(jint fd, char *buf, jint nbytes) { jint JVM_Available(jint fd, jlong *pbytes) { jlong cur, end; - #if !os_WINDOWS struct stat st; if (fstat(fd, &st) >= 0) { if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { @@ -1972,7 +1912,6 @@ jint JVM_Available(jint fd, jlong *pbytes) { } } } - #endif if ((cur = lseek64(fd, 0L, SEEK_CUR)) == -1) { return 0; } else if ((end = lseek64(fd, 0L, SEEK_END)) == -1) { @@ -2006,9 +1945,7 @@ JVM_Lseek(jint fd, jlong offset, jint whence) { */ jint JVM_SetLength(jint fd, jlong length) { - return - - ftruncate(fd, length); + return ftruncate(fd, length); } /* @@ -2017,12 +1954,7 @@ JVM_SetLength(jint fd, jlong length) { */ jint JVM_Sync(jint fd) { - #if !os_WINDOWS - return fsync(fd); - #else - return !FlushFileBuffers((HANDLE)_get_osfhandle(fd)); //_get_osfhandle transforms fd to HANDLE that is needed by FlushFileBuffers -//Windows return nonzero on success - #endif + return fsync(fd); } /* @@ -2031,7 +1963,7 @@ JVM_Sync(jint fd) { jint JVM_InitializeSocketLibrary(void) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return 0; #else UNIMPLEMENTED(); @@ -2039,15 +1971,16 @@ JVM_InitializeSocketLibrary(void) { #endif } -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN #include +#include #else struct sockaddr; #endif jint JVM_Socket(jint domain, jint type, jint protocol) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return socket(domain, type, protocol); #else UNIMPLEMENTED(); @@ -2057,7 +1990,7 @@ JVM_Socket(jint domain, jint type, jint protocol) { jint JVM_SocketClose(jint fd) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return close(fd); #else UNIMPLEMENTED(); @@ -2067,7 +2000,7 @@ JVM_SocketClose(jint fd) { jint JVM_SocketShutdown(jint fd, jint howto) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return shutdown(fd, howto); #else UNIMPLEMENTED(); @@ -2077,9 +2010,7 @@ JVM_SocketShutdown(jint fd, jint howto) { jint JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS - - +#if os_SOLARIS || os_LINUX || os_DARWIN return recv(fd, buf, nBytes, flags); #else UNIMPLEMENTED(); @@ -2089,8 +2020,7 @@ JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) { jint JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS - +#if os_SOLARIS || os_LINUX || os_DARWIN return send(fd, buf, nBytes, flags); #else UNIMPLEMENTED(); @@ -2098,10 +2028,6 @@ JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { #endif } -#if os_WINDOWS -extern int gettimeofday(struct timeval * tp); - -#endif jint JVM_Timeout(int fd, long timeout) { #if os_DARWIN || os_LINUX @@ -2159,36 +2085,6 @@ JVM_Timeout(int fd, long timeout) { } } else return res; } -#elif os_WINDOWS -Unsigned8 prevtime,newtime; - struct timeval t; - - gettimeofday(&t); - prevtime = ((Unsigned8)t.tv_sec * 1000) + t.tv_usec / 1000; - - for(;;) { - WSAPOLLFD pfd; - - pfd.fd = fd; - pfd.events = POLLIN | POLLERR; - - int res = WSAPoll(&pfd, 1, timeout); - - if (res == SOCKET_ERROR && errno == EINTR) { - - // On Windows any value < 0 means "forever" too - - if(timeout >= 0) { - gettimeofday(&t); - newtime = ((Unsigned8)t.tv_sec * 1000) + t.tv_usec / 1000; - timeout -= newtime - prevtime; - if(timeout <= 0) - return OS_OK; - prevtime = newtime; - } - } else - return res; - } #else UNIMPLEMENTED(); return 0; @@ -2197,7 +2093,7 @@ Unsigned8 prevtime,newtime; jint JVM_Listen(jint fd, jint count) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return listen(fd, count); #else UNIMPLEMENTED(); @@ -2207,7 +2103,7 @@ JVM_Listen(jint fd, jint count) { jint JVM_Connect(jint fd, struct sockaddr *him, jint len) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return connect(fd, him, len); #else UNIMPLEMENTED(); @@ -2217,7 +2113,7 @@ JVM_Connect(jint fd, struct sockaddr *him, jint len) { jint JVM_Bind(jint fd, struct sockaddr *him, jint len) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return bind(fd, him, len); #else UNIMPLEMENTED(); @@ -2227,7 +2123,7 @@ JVM_Bind(jint fd, struct sockaddr *him, jint len) { jint JVM_Accept(jint fd, struct sockaddr *him, jint *len) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN if (fd < 0) { return -1; } @@ -2277,8 +2173,7 @@ JVM_SocketAvailable(jint fd, jint *pbytes) { // note ioctl can return 0 when successful, JVM_SocketAvailable // is expected to return 0 on failure and 1 on success to the jdk. return (ret == OS_ERR) ? 0 : 1; -#elif os_LINUX || os_WINDOWS - +#elif os_LINUX // Linux doc says EINTR not returned, unlike Solaris int ret = ioctl(fd, FIONREAD, pbytes); @@ -2294,7 +2189,7 @@ JVM_SocketAvailable(jint fd, jint *pbytes) { jint JVM_GetSockName(jint fd, struct sockaddr *him, int *len) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return getsockname(fd, him, (socklen_t*) len); #else UNIMPLEMENTED(); @@ -2304,7 +2199,7 @@ JVM_GetSockName(jint fd, struct sockaddr *him, int *len) { jint JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return getsockopt(fd, level, optname, optval, (socklen_t*) optlen); #else UNIMPLEMENTED(); @@ -2314,7 +2209,7 @@ JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) { jint JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return setsockopt(fd, level, optname, optval, optlen); #else UNIMPLEMENTED(); @@ -2350,7 +2245,7 @@ JVM_GetHostByName(char* name) { int JVM_GetHostName(char* name, int namelen) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return gethostname(name, namelen); #else UNIMPLEMENTED(); diff --git a/com.oracle.max.vm.native/substrate/jvmti.c b/com.oracle.max.vm.native/substrate/jvmti.c index 5e6c923371..c8b9dc0129 100644 --- a/com.oracle.max.vm.native/substrate/jvmti.c +++ b/com.oracle.max.vm.native/substrate/jvmti.c @@ -18,15 +18,7 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "os.h" -#if os_WINDOWS -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT 0x0600 // needed for tools like MINGW in order to use condition variables which became available from Windows Vista and on. Visual Studio might define it on its own -#include -#endif #include #include #include @@ -36,7 +28,7 @@ // (cwi): Java 7 added a new JVMTI function, so it is necessary to distinguish between Java 6 and Java 7. // This is the only #define that I found in the header files that allows this distinction. -#if os_LINUX || os_SOLARIS || os_WINDOWS +#if os_LINUX || os_SOLARIS #include #endif diff --git a/com.oracle.max.vm.native/substrate/maxine.c b/com.oracle.max.vm.native/substrate/maxine.c index c6759acb1a..a8a3dbf3bf 100644 --- a/com.oracle.max.vm.native/substrate/maxine.c +++ b/com.oracle.max.vm.native/substrate/maxine.c @@ -26,61 +26,35 @@ * hands control over to the VM's compiled code, which has been written in Java, * by calling a VM entry point as a C function. */ - #include "os.h" - - #if !os_WINDOWS - #include - #include - #include - #include - #include - #include - #include -#else - #ifdef _WIN32_WINNT - #undef _WIN32_WINNT - #endif - #define _WIN32_WINNT 0x0600 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. - #include - #include - #include - #include - #include - #define sleep(a) Sleep(a * 1000) - #define strdup _strdup - char last_dl_error [100]; //emulating dlerror() function not available on Windows -#endif - - +#include #include #include - +#include +#include #include +#include #include - +#include +#include +#include #include #include "log.h" #include "isa.h" #include "image.h" #include "threads.h" +#include "os.h" #include "vm.h" #include "virtualMemory.h" #include "maxine.h" #include - - - - #if os_MAXVE #include "maxve.h" #endif -#ifdef arm -#if !os_WINDOWS +#ifdef arm #include #endif -#endif static void max_fd_limit() { @@ -102,10 +76,7 @@ static void max_fd_limit() { log_println("setrlimit failed"); } } -#elif os_WINDOWS - _setmaxstdio(16777216); //windows support setting the max number of fds but they do not have a global max defined. That numer is the theoeretical max fo 64 bit machines #endif - } #define IMAGE_FILE_NAME "maxine.vm" @@ -125,18 +96,15 @@ static void getExecutablePath(char *result) { #elif os_MAXVE result[0] = 0; return; -#elif os_LINUX +#elif os_LINUX char *linkName = "/proc/self/exe"; #elif os_SOLARIS char *linkName = "/proc/self/path/a.out"; -#elif os_WINDOWS - - int numberOfChars = GetModuleFileNameA(NULL,result, MAX_PATH_LENGTH); #else # error getExecutablePath() not supported on other platforms yet #endif -#if os_LINUX || os_SOLARIS +#if os_LINUX || os_SOLARIS // read the symbolic link to figure out what the executable is. int numberOfChars = readlink(linkName, result, MAX_PATH_LENGTH); if (numberOfChars < 0) { @@ -148,11 +116,7 @@ static void getExecutablePath(char *result) { char *p; // chop off the name of the executable for (p = result + (numberOfChars - 1); p >= result; p--) { - #if os_WINDOWS - if (*p == '\\') { - #else if (*p == '/') { - #endif p[1] = 0; break; } @@ -182,14 +146,7 @@ static void *openLibrary(char *path) { log_println("openLibrary(\"%s\")", path); } #endif -#if !os_WINDOWS void *result = dlopen(path, RTLD_LAZY); -#else - void *result = LoadLibraryA(path); - if (result==NULL) { - sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); - } -#endif #if log_LINKER char* errorMessage = dlerror(); if (path == NULL) { @@ -205,16 +162,8 @@ static void *openLibrary(char *path) { } static void* loadSymbol(void* handle, const char* symbol) { - #if os_WINDOWS - void* result = GetProcAddress(handle, symbol); - if (!result) { - sprintf(last_dl_error, "dl function : GetProcAddress error code : %lu", GetLastError ()); - - } - #else void* result = dlsym(handle, symbol); - #endif -#if log_LINKER //NOT IMPLEMENTED FOR WINDOWS, you can get info using the dlerror() function we defined +#if log_LINKER #if os_MAXVE log_println("loadSymbol(%p, \"%s\") = %p", handle, symbol, result); #else @@ -234,7 +183,7 @@ static void* loadSymbol(void* handle, const char* symbol) { return result; } -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX #include #include @@ -245,7 +194,7 @@ static void* loadSymbol(void* handle, const char* symbol) { #if os_DARWIN #include -#elif os_LINUX +#elif os_LINUX #include #elif os_SOLARIS #define _STRUCTURED_PROC 1 /* Use new definitions in procfs.h instead of those in procfs_old.h */ @@ -266,7 +215,7 @@ void debugger_initialize() { char *port = getenv("MAX_AGENT_PORT"); if (port != NULL) { -#if (os_LINUX ) && defined(PR_SET_PTRACER) +#if os_LINUX && defined(PR_SET_PTRACER) /* See info about PR_SET_PTRACER at https://wiki.ubuntu.com/Security/Features#ptrace */ char *val = getenv("MAX_AGENT_PID"); if (val == NULL) { @@ -320,7 +269,7 @@ void debugger_initialize() { #if log_TELE log_println("Stopping VM for debugger"); #endif -#if os_DARWIN || os_LINUX || os_WINDOWS +#if os_DARWIN || os_LINUX kill(getpid(), SIGTRAP); #elif os_SOLARIS int ctlfd = open("/proc/self/ctl", O_WRONLY); @@ -335,7 +284,7 @@ void debugger_initialize() { } } #else -#define debugger_initialize() //not implemented for WINDOWS +#define debugger_initialize() #endif /** @@ -344,9 +293,6 @@ void debugger_initialize() { typedef jint (*VMRunMethod)(Address tlBlock, int tlBlockSize, Address bootHeapRegionStart, void *openLibrary(char *), void *dlsym(void *, const char *), char *dlerror(void), void* vmInterface, JNIEnv jniEnv, void *jmmInterface, void *jvmtiInterface, int argc, char *argv[]); -#if os_WINDOWS -__declspec(dllexport) -#endif int maxine(int argc, char *argv[], char *executablePath) { VMRunMethod method; int exitCode = 0; @@ -395,13 +341,6 @@ int maxine(int argc, char *argv[], char *executablePath) { Address tlBlock = threadLocalsBlock_create(PRIMORDIAL_THREAD_ID, 0, 0); NativeThreadLocals ntl = NATIVE_THREAD_LOCALS_FROM_TLBLOCK(tlBlock); -#if os_WINDOWS -char *dlerror(){ - - - return last_dl_error; -} -#endif #if log_LOADER log_println("entering Java by calling MaxineVM.run(tlBlock=%p, bootHeapRegionStart=%p, openLibrary=%p, dlsym=%p, dlerror=%p, vmInterface=%p, jniEnv=%p, jmmInterface=%p, jvmtiInterface=%p, argc=%d, argv=%p)", @@ -466,12 +405,8 @@ void core_dump() { log_print("dumping core....\n heap @ "); log_print_symbol(image_heap()); log_print_newline(); - #if os_WINDOWS - raise(SIGABRT); - #else // Use kill instead of abort so the vm process keeps running after the core is created. kill(getpid(), SIGABRT); - #endif sleep(3); #endif } @@ -509,23 +444,6 @@ void *native_properties(void) { } #if os_MAXVE maxve_native_props(&nativeProperties); -#elif os_WINDOWS - - nativeProperties.user_name = malloc(MAX_PATH_LENGTH); - nativeProperties.user_dir = malloc(MAX_PATH_LENGTH); - nativeProperties.user_home = malloc(MAX_PATH_LENGTH); - - DWORD size = MAX_PATH_LENGTH; - GetUserNameA(nativeProperties.user_name, &size); - size = MAX_PATH_LENGTH; - char * tmp; - SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, (WCHAR **) &tmp); //Unfortunately, windows return home dir only in Unicode (Wide) format, not ANSI - nativeProperties.user_home = (char*) _wcsdup((const wchar_t * ) tmp); - CoTaskMemFree(tmp); //SHGetKnownFolderPath allocated that space and it is our responsibility to free it - GetCurrentDirectory(MAX_PATH_LENGTH, nativeProperties.user_dir); -//CAUTION nativeProperties.user_home contains the path in Unicode format so it cannot be printed with %s but rather with %ls using printf - - #else /* user properties */ { diff --git a/com.oracle.max.vm.native/substrate/maxine.h b/com.oracle.max.vm.native/substrate/maxine.h index 76ef87f53d..64df50d182 100644 --- a/com.oracle.max.vm.native/substrate/maxine.h +++ b/com.oracle.max.vm.native/substrate/maxine.h @@ -27,7 +27,7 @@ extern jlong native_nanoTime(void); extern jlong native_currentTimeMillis(void); extern void *native_executablePath(void); -extern void native_exit(jint code); +extern void native_exit(int code); extern void *native_environment(void); extern int maxine(int argc, char *argv[], char *executablePath); diff --git a/com.oracle.max.vm.native/substrate/memory.c b/com.oracle.max.vm.native/substrate/memory.c index 1849aaa863..542f654493 100644 --- a/com.oracle.max.vm.native/substrate/memory.c +++ b/com.oracle.max.vm.native/substrate/memory.c @@ -19,13 +19,9 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "os.h" -#if !os_WINDOWS + #include #include -#else -#include -#endif - #include #include diff --git a/com.oracle.max.vm.native/substrate/signal.c b/com.oracle.max.vm.native/substrate/signal.c index f07eb5cea2..9813304e5c 100644 --- a/com.oracle.max.vm.native/substrate/signal.c +++ b/com.oracle.max.vm.native/substrate/signal.c @@ -24,10 +24,6 @@ /** * Native functions for SignalDispatcher.java. */ -#include "os.h" -#if os_WINDOWS -#include -#endif #include #include #include @@ -36,9 +32,7 @@ #include "threads.h" #include "log.h" -#if os_WINDOWS -static HANDLE signal_sem; -#elif os_DARWIN +#if os_DARWIN #include static semaphore_t signal_sem; #elif os_SOLARIS @@ -49,11 +43,11 @@ static semaphore_t signal_sem; #define sem_destroy sema_destroy #define sem_t sema_t static sem_t signal_sem; -#elif os_MAXVE -#else +#elif os_LINUX #include static sem_t signal_sem; - +#elif os_MAXVE +// no signals, so nothing necessary #endif boolean traceSignals = false; @@ -75,15 +69,10 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalNotify(JNIEnv *env, jcl if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_signal failed: %s", mach_error_string(kr)); } -#elif os_LINUX || os_SOLARIS +#elif os_LINUX || os_SOLARIS if (sem_post(&signal_sem) != 0) { log_exit(11, "sem_post failed: %s", strerror(errno)); } -#elif os_WINDOWS - if(!ReleaseSemaphore(signal_sem, 1, NULL)) - log_exit(GetLastError(), "ReleaseSemaphore failed"); - - #elif os_MAXVE #else c_UNIMPLEMENTED(); @@ -124,18 +113,13 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalWait(JNIEnv *env, jclas if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_wait failed: %s", mach_error_string(kr)); } -#elif os_LINUX || os_SOLARIS +#elif os_LINUX || os_SOLARIS int ret; - while ((ret = sem_wait(&signal_sem) == EINTR)) { //not sure if EINTR can occur on Windows (No sending signals is supported + while ((ret = sem_wait(&signal_sem) == EINTR)) { } if (ret != 0) { log_exit(11, "sem_wait failed: %s", strerror(errno)); } -#elif os_WINDOWS - if ( WaitForSingleObject(signal_sem,INFINITE) == WAIT_FAILED) - log_exit(GetLastError(), "WaitForSingleObject failed:"); - - #elif os_MAXVE #else c_UNIMPLEMENTED(); @@ -155,13 +139,10 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalInit(JNIEnv *env, jclas if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_create failed: %s", mach_error_string(kr)); } -#elif os_LINUX +#elif os_LINUX if (sem_init(&signal_sem, 0, 0) != 0) { log_exit(11, "sem_init failed: %s", strerror(errno)); } -#elif os_WINDOWS - signal_sem = CreateSemaphoreA(NULL, 1, 50000,NULL); //Windows Semaphore needs to have initial val 1 not 0 like Linux. If it was 0 no thread could enter -//Unfortunately, Windows Semaphores need a maximum value representing how many can enter it so we use a random big value (50000) #elif os_SOLARIS if (sem_init(&signal_sem, 0, USYNC_THREAD, NULL) != 0) { log_exit(11, "sema_init failed: %s", strerror(errno)); @@ -195,8 +176,6 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalFinalize(JNIEnv *env, j if (sem_destroy(&signal_sem) != 0) { log_exit(11, "sema_destroy failed: %s", strerror(errno)); } -#elif os_WINDOWS - CloseHandle(signal_sem); #endif } diff --git a/com.oracle.max.vm.native/substrate/sync.c b/com.oracle.max.vm.native/substrate/sync.c index d0f4af3ead..bb6f59e38c 100644 --- a/com.oracle.max.vm.native/substrate/sync.c +++ b/com.oracle.max.vm.native/substrate/sync.c @@ -18,10 +18,6 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "os.h" -#if os_WINDOWS -#include -#endif #include #include @@ -30,6 +26,7 @@ #include "log.h" #include "jni.h" #include "mutex.h" +#include "os.h" #include "word.h" #include "threads.h" diff --git a/com.oracle.max.vm.native/substrate/threads.c b/com.oracle.max.vm.native/substrate/threads.c index 3717429596..6d82a2491b 100644 --- a/com.oracle.max.vm.native/substrate/threads.c +++ b/com.oracle.max.vm.native/substrate/threads.c @@ -19,16 +19,11 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "os.h" -#if (!os_WINDOWS) - #include -#else - #include -#endif +#include #include +#include "os.h" #include "isa.h" #include "virtualMemory.h" @@ -46,9 +41,8 @@ #include "trap.h" #include "threads.h" #include "threadLocals.h" -#if !os_WINDOWS #include -#endif + #if (os_DARWIN || os_LINUX) # include # include @@ -62,16 +56,6 @@ # include "maxve.h" typedef maxve_Thread Thread; #define thread_current() (maxve_get_current()) - -#elif os_WINDOWS - - #include - #include - #include - #include - typedef HANDLE Thread; -#define thread_current() ((Thread) GetCurrentThread()) - #endif #if log_NUMA_THREADS @@ -130,20 +114,6 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { } pthread_attr_destroy(&attr); -#elif os_WINDOWS - SYSTEM_INFO systemInfo = {0}; - GetSystemInfo(&systemInfo); - - NT_TIB *tib = (NT_TIB*)NtCurrentTeb(); - *stackBase = (DWORD_PTR)tib->StackBase - systemInfo.dwPageSize ; //In windows, guard size is always one memory page so we remove it from stacksize. - - - MEMORY_BASIC_INFORMATION mbi = {0}; - if (VirtualQuery((LPCVOID)(stackBase ), &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0) //we use virtualquery to get windows reserved stack size (not committed). - { - DWORD_PTR allocationStart = (DWORD_PTR)mbi.AllocationBase; - *stackSize = (size_t) stackBase - allocationStart; - } #elif os_DARWIN pthread_t self = pthread_self(); void *stackTop = pthread_get_stackaddr_np(self); @@ -176,7 +146,7 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { */ static Thread thread_create(jint id, Size stackSize, int priority) { Thread thread; -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE int error; #endif @@ -188,10 +158,8 @@ static Thread thread_create(jint id, Size stackSize, int priority) { #if log_THREADS log_println("thread_create: id = %d, stack size = %ld", id, stackSize); #endif -#if os_WINDOWS -#define PTHREAD_STACK_MIN 0 -#endif -#if (os_LINUX || os_DARWIN ) + +#if (os_LINUX || os_DARWIN) if (stackSize < PTHREAD_STACK_MIN) { stackSize = PTHREAD_STACK_MIN; } @@ -216,7 +184,7 @@ static Thread thread_create(jint id, Size stackSize, int priority) { if (thread == NULL) { return (Thread) 0; } -#elif (os_LINUX || os_DARWIN ) +#elif (os_LINUX || os_DARWIN) pthread_attr_t attributes; pthread_attr_init(&attributes); @@ -232,15 +200,6 @@ static Thread thread_create(jint id, Size stackSize, int priority) { log_println("pthread_create failed with error: %d", error); return (Thread) 0; } -#elif (os_WINDOWS) - thread = CreateThread(NULL, stackSize, thread_run, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL); //we demand explicitly stack size to be reservedd - //Also guard is set automatically - if(!thread){ - log_println("thread_create failed with error: %d", GetLastError()); - return (Thread) 0; - } - //the only way to make thread detached is to invalidate its handle using CloseHandle(). However, this would result in returning an invalid Thread at the end of the function - #elif os_SOLARIS if (stackSize < thr_min_stack()) { stackSize = thr_min_stack(); @@ -267,13 +226,7 @@ void *thread_self() { * * @param arg the pre-allocated, but uninitialized, thread locals block. */ - #if os_WINDOWS -DWORD WINAPI thread_run(void *arg) //we prefer this signature in order to avoid compiler waring on Windows. - - #else -void * thread_run(void *arg) -#endif - { +void *thread_run(void *arg) { Address tlBlock = (Address) arg; TLA etla = ETLA_FROM_TLBLOCK(tlBlock); @@ -354,11 +307,7 @@ void * thread_run(void *arg) setCurrentThreadSignalMaskOnThreadExit(result == 1); /* Successful thread exit */ - #if os_WINDOWS - return 0; - #else - return NULL; - #endif + return NULL; } /** @@ -529,12 +478,10 @@ Java_com_sun_max_vm_thread_VmThread_nativeYield(JNIEnv *env, jclass c) { thr_yield(); #elif os_DARWIN sched_yield(); -#elif os_LINUX +#elif os_LINUX pthread_yield(); #elif os_MAXVE maxve_yield(); -#elif os_WINDOWS - SwitchToThread(); #else c_UNIMPLEMENTED(); #endif @@ -557,7 +504,7 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre log_exit(11, "Error sending signal SIGUSR1 to native thread %p", nativeThread); } } -#elif os_LINUX || os_DARWIN +#elif os_LINUX || os_DARWIN // Signals the thread int result = pthread_kill((pthread_t) nativeThread, SIGUSR1); if (result != 0) { @@ -570,12 +517,7 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre } } #elif os_MAXVE - maxve_interrupt((void*) nativeThread); -#elif os_WINDOWS - c_UNIMPLEMENTED(); - - #else c_UNIMPLEMENTED(); #endif @@ -584,20 +526,6 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre jboolean thread_sleep(jlong numberOfMilliSeconds) { #if os_MAXVE return maxve_sleep(numberOfMilliSeconds * 1000000); -#elif os_WINDOWS -HANDLE timer; -LARGE_INTEGER li; -if(!(timer = CreateWaitableTimer(NULL, TRUE, NULL))) - return FALSE; - -li.QuadPart = -(numberOfMilliSeconds * 1000000); -if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)){ - CloseHandle(timer); - return FALSE; - } - WaitForSingleObject(timer, INFINITE); - CloseHandle(timer); - return TRUE; #else struct timespec time, remainder; diff --git a/com.oracle.max.vm.native/substrate/time.c b/com.oracle.max.vm.native/substrate/time.c index 07a86d8b61..60e90b0d39 100644 --- a/com.oracle.max.vm.native/substrate/time.c +++ b/com.oracle.max.vm.native/substrate/time.c @@ -21,47 +21,15 @@ #include "os.h" #include "jni.h" #include "maxine.h" + #include +#include -#if !os_WINDOWS -#include //MINGW may contain this file but it is not officially part of WINAPI so other SDKs (eg. Visual Studio do not include it) -#endif #if os_DARWIN #include #include #elif os_LINUX #include -#elif os_WINDOWS -#include -#include -int gettimeofday(struct timeval * tp) -{ - // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's - // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) - // until 00:00:00 January 1, 1970 - static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); - - SYSTEMTIME system_time; - FILETIME file_time; - uint64_t time; - - GetSystemTime( &system_time ); - SystemTimeToFileTime( &system_time, &file_time ); - time = ((uint64_t)file_time.dwLowDateTime ) ; - time += ((uint64_t)file_time.dwHighDateTime) << 32; - - tp->tv_sec = (long) ((time - EPOCH) / 10000000L); - tp->tv_usec = (long) (system_time.wMilliseconds * 1000); - return 0; -} - -int clock_gettime(int x, struct timespec *spec) -{ __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); - wintime -=(int64_t)116444736000000000; //1jan1601 to 1jan1970 - spec->tv_sec =wintime / (int64_t)10000000; //seconds - spec->tv_nsec =wintime % (int64_t)10000000 *100; //nano-seconds - return 0; -} #endif @@ -101,7 +69,7 @@ jlong native_nanoTime(void) { struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)tv.tv_sec * (uint64_t)(1000 * 1000 * 1000) + (uint64_t)(tv.tv_usec * 1000); -#elif os_LINUX +#elif os_LINUX #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC (1) @@ -151,23 +119,15 @@ jlong native_nanoTime(void) { c_ASSERT(status != -1); jlong usecs = ((jlong) time.tv_sec) * (1000 * 1000) + (jlong) time.tv_usec; return 1000 * usecs; -#elif os_WINDOWS - struct timespec time; - clock_gettime(1, &time); - return time.tv_nsec; //NOT 100% TESTED #else return 1; #endif } jlong native_currentTimeMillis(void) { -#if os_SOLARIS || os_DARWIN || os_LINUX || os_WINDOWS +#if os_SOLARIS || os_DARWIN || os_LINUX struct timeval tv; - #if os_WINDOWS - gettimeofday(&tv); - #else gettimeofday(&tv, NULL); - #endif // we need to cast to jlong to avoid overflows in ARMv7 return ((jlong) tv.tv_sec * 1000) + ((jlong) tv.tv_usec / 1000); #else diff --git a/com.oracle.max.vm.native/substrate/trap.c b/com.oracle.max.vm.native/substrate/trap.c index 7501e780fe..3030b388ae 100644 --- a/com.oracle.max.vm.native/substrate/trap.c +++ b/com.oracle.max.vm.native/substrate/trap.c @@ -19,15 +19,13 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "os.h" -#if os_WINDOWS -#include -#endif + #include "c.h" #include "threads.h" #include "virtualMemory.h" #include "log.h" #include "jni.h" +#include "os.h" #include "isa.h" #include "image.h" #include "trap.h" @@ -51,7 +49,7 @@ static Address theJavaTrapStub; static boolean traceTraps = false; -#if !os_MAXVE && !os_WINDOWS //Windows do not support POSIX signals unfortunately. You can only raise some signals from within your own process/thread but not send it to another process/thread +#if !os_MAXVE /** * All signals. @@ -79,13 +77,13 @@ static sigset_t blockedOnThreadExitSignals; int getTrapNumber(int signal) { switch (signal) { case SIGSEGV: -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE case SIGBUS: #endif return MEMORY_FAULT; case SIGFPE: return ARITHMETIC_EXCEPTION; -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE case SIGUSR1: return ASYNC_INTERRUPT; default: @@ -98,12 +96,12 @@ int getTrapNumber(int signal) { #if os_SOLARIS #include #define thread_setSignalMask thr_sigsetmask -#elif os_DARWIN || os_LINUX +#elif os_DARWIN || os_LINUX #define thread_setSignalMask pthread_sigmask #endif void setCurrentThreadSignalMaskOnThreadExit(boolean isVmOperationThread) { -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE if (!isVmOperationThread) { /* disable signals sent by Thread.interrupt() as thread is transitioning to not alive state. */ thread_setSignalMask(SIG_BLOCK, &blockedOnThreadExitSignals, NULL); @@ -112,7 +110,7 @@ void setCurrentThreadSignalMaskOnThreadExit(boolean isVmOperationThread) { } void setCurrentThreadSignalMask(boolean isVmOperationThread) { -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE if (isVmOperationThread) { thread_setSignalMask(SIG_SETMASK, &vmAndDefaultSignals, NULL); } else { @@ -122,12 +120,9 @@ void setCurrentThreadSignalMask(boolean isVmOperationThread) { #endif } -void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'signal' argument to 'sig' because it overlapped with windows signal() function +void* setSignalHandler(int signal, SignalHandlerFunction handler) { #if os_MAXVE - maxve_register_fault_handler(sig, handler); - return NULL; -#elif os_WINDOWS - signal(sig, handler); + maxve_register_fault_handler(signal, handler); return NULL; #else struct sigaction newSigaction; @@ -137,14 +132,14 @@ void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'sign sigemptyset(&newSigaction.sa_mask); newSigaction.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK; -#if os_SOLARIS || os_LINUX || os_DARWIN - if (sig == SIGUSR1) { +#if os_SOLARIS || os_LINUX || os_DARWIN + if (signal == SIGUSR1) { newSigaction.sa_flags = SA_SIGINFO | SA_ONSTACK; } #endif newSigaction.sa_sigaction = handler; - if (sigaction(sig, &newSigaction, &oldSigaction) != 0) { + if (sigaction(signal, &newSigaction, &oldSigaction) != 0) { log_exit(1, "sigaction failed"); } @@ -152,7 +147,7 @@ void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'sign log_lock(); log_print("Registered handler %p [", handler); log_print_symbol((Address) handler); - log_print("] for signal %d", sig); + log_print("] for signal %d", signal); if (oldSigaction.sa_handler != NULL) { log_print(" replacing handler "); log_print_symbol((Address) oldSigaction.sa_handler); @@ -168,7 +163,7 @@ void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'sign static Address getInstructionPointer(UContext *ucontext) { #if os_SOLARIS return ucontext->uc_mcontext.gregs[REG_PC]; -#elif os_LINUX +#elif os_LINUX # if isa_AMD64 return ucontext->uc_mcontext.gregs[REG_RIP]; # elif isa_IA32 @@ -184,10 +179,6 @@ static Address getInstructionPointer(UContext *ucontext) { return ucontext->uc_mcontext->__ss.__rip; #elif os_MAXVE return ucontext->rip; -#elif os_WINDOWS -#if isa_AMD64 - return ucontext->Rip; - #endif #else c_UNIMPLEMENTED(); #endif @@ -201,7 +192,7 @@ static void setInstructionPointer(UContext *ucontext, Address stub) { ucontext->uc_mcontext.gregs[REG_PC] = (greg_t) stub; #elif os_DARWIN ucontext->uc_mcontext->__ss.__rip = stub; -#elif os_LINUX +#elif os_LINUX # if isa_AMD64 ucontext->uc_mcontext.gregs[REG_RIP] = (greg_t) stub; # elif isa_IA32 @@ -215,19 +206,15 @@ static void setInstructionPointer(UContext *ucontext, Address stub) { # endif #elif os_MAXVE ucontext->rip = (unsigned long) stub; -#elseif os_WINDOWS -# if isa_AMD64 - ucontext->uc_mcontext.rip = (greg_t) stub; - #endif #else c_UNIMPLEMENTED(); #endif } -static Address getFaultAddress(SigInfo * sigInfo, UContext *ucontext) { //there is no siginfo_t struct in Windows +static Address getFaultAddress(SigInfo * sigInfo, UContext *ucontext) { #if (os_DARWIN || os_SOLARIS || os_LINUX ) return (Address) sigInfo->si_addr; -#elif (os_MAXVE) || os_WINDOWS +#elif (os_MAXVE) return (Address) sigInfo; #endif } @@ -241,7 +228,7 @@ char *vmSignalName(int signal) { case SIGSEGV: return "SIGSEGV"; case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE case SIGUSR1: return "SIGUSR1"; case SIGBUS: return "SIGBUS"; #endif @@ -282,15 +269,12 @@ static boolean handleDivideOverflow(UContext *ucontext) { if (rip[0] == 0xf7) { #if os_SOLARIS Address dividend = ucontext->uc_mcontext.gregs[REG_RAX]; -#elif os_LINUX +#elif os_LINUX Address dividend = ucontext->uc_mcontext.gregs[REG_RAX]; #elif os_DARWIN Address dividend = ucontext->uc_mcontext->__ss.__rax; #elif os_MAXVE Address dividend = ucontext->rax; -#elif os_WINDOWS - Address dividend = ucontext->Rax; - #else c_UNIMPLEMENTED(); #endif @@ -310,15 +294,12 @@ static boolean handleDivideOverflow(UContext *ucontext) { /* Set the remainder to 0. */ #if os_SOLARIS ucontext->uc_mcontext.gregs[REG_RDX] = 0; -#elif os_LINUX +#elif os_LINUX ucontext->uc_mcontext.gregs[REG_RDX] = 0; #elif os_DARWIN ucontext->uc_mcontext->__ss.__rdx = 0; #elif os_MAXVE ucontext->rdx = 0; -#elif os_WINDOWS - ucontext->Rdx = 0; - #else c_UNIMPLEMENTED(); #endif @@ -465,9 +446,6 @@ static void vmSignalHandler(int signal, SigInfo *signalInfo, UContext *ucontext) #elif isa_AMD64 && (os_SOLARIS || os_LINUX) tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->uc_mcontext.gregs[REG_R14]); ucontext->uc_mcontext.gregs[REG_R14] = (Address) dtla; -#elif isa_AMD64 && os_WINDOWS - tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->R14); - ucontext->R14 = (Address) dtla; #elif isa_AMD64 && os_DARWIN tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->uc_mcontext->__ss.__r14); ucontext->uc_mcontext->__ss.__r14 = (Address) dtla; @@ -493,17 +471,11 @@ static void vmSignalHandler(int signal, SigInfo *signalInfo, UContext *ucontext) /** * The handler for signals handled by SignalDispatcher.java. */ - #if os_WINDOWS - static void userSignalHandlerDef(int signal) { - void postSignal(int signal); - postSignal(signal); -} -#else static void userSignalHandlerDef(int signal, SigInfo *signalInfo, UContext *ucontext) { void postSignal(int signal); postSignal(signal); } -#endif + /* Defined global declared in trap.h */ SignalHandlerFunction userSignalHandler = (SignalHandlerFunction) userSignalHandlerDef; @@ -519,7 +491,7 @@ void nativeTrapInitialize(Address javaTrapStub) { setSignalHandler(SIGILL, (SignalHandlerFunction) vmSignalHandler); setSignalHandler(SIGFPE, (SignalHandlerFunction) vmSignalHandler); -#if !os_MAXVE && !os_WINDOWS //no support for windows signals +#if !os_MAXVE setSignalHandler(SIGBUS, (SignalHandlerFunction) vmSignalHandler); setSignalHandler(SIGUSR1, (SignalHandlerFunction) vmSignalHandler); diff --git a/com.oracle.max.vm.native/substrate/trap.h b/com.oracle.max.vm.native/substrate/trap.h index 990f1a582a..620a4b9afe 100644 --- a/com.oracle.max.vm.native/substrate/trap.h +++ b/com.oracle.max.vm.native/substrate/trap.h @@ -29,22 +29,14 @@ # include # include # include -#if (!os_WINDOWS) - # include +# include # include - -#endif #endif + #include "os.h" -#if os_MAXVE +#if os_MAXVE #define SignalHandlerFunction fault_handler_t -#elif os_WINDOWS -typedef void SigInfo; - -typedef void (*SignalHandlerFunction)(int signal); //Windows want a signal handler with one argument (Remember, Windows do not support POSIX signals. They can only be used as exceptions raised from within the same process. You cannot send them to other threads/ procs) - -typedef CONTEXT UContext; #else typedef ucontext_t UContext; typedef siginfo_t SigInfo; diff --git a/com.oracle.max.vm.native/substrate/vm.h b/com.oracle.max.vm.native/substrate/vm.h index 8a4da41eed..880df618d4 100644 --- a/com.oracle.max.vm.native/substrate/vm.h +++ b/com.oracle.max.vm.native/substrate/vm.h @@ -36,10 +36,6 @@ * A set of VM functions implemented in Java that can (only) be called from C code. * These are defined in VMFunctionsSource.java. */ - #include "os.h" - #if os_WINDOWS - #undef GetClassName - #endif //Microsoft defines GetClassName as GetClassNameA in some header files which breaks our code typedef struct vmInterface_ { // START GENERATED CODE void (JNICALL *Unimplemented) (JNIEnv *env); From 1f966b0ba87113b321e329f33cc4beaa9ea20372 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Wed, 8 Jul 2020 21:10:10 +0300 Subject: [PATCH 03/17] Added Windows support for com.oracle.max.vm.native Added code for the creation of the following shared libraries/executables on Windows: jvm.dll (substrate), javatest.dll, hosted.dll, maxvm.exe (launch) -Only tele.dll excluded Code depends entirely on native Windows DLLs- no other dependencies required to compile and run) The only thing left unimplemented (besides Tele) is the sending of signals to different threds/processes (ie. kill() ) as Windows do not support that functionality. Windows Signals can only be raised from within the same process that receives them (like Exceptions). --- com.oracle.max.vm.native/hosted/platform.c | 18 +- com.oracle.max.vm.native/javatest/javatest.mk | 2 +- com.oracle.max.vm.native/javatest/tests.c | 36 +++- com.oracle.max.vm.native/launch/maxvm.c | 40 +++- com.oracle.max.vm.native/makefile | 2 +- com.oracle.max.vm.native/platform/aarch64.c | 2 +- com.oracle.max.vm.native/platform/aarch64.h | 2 +- com.oracle.max.vm.native/platform/amd64.c | 6 +- com.oracle.max.vm.native/platform/amd64.h | 16 ++ com.oracle.max.vm.native/platform/arm.c | 6 +- com.oracle.max.vm.native/platform/platform.mk | 44 +++- .../platform/usercygwinamd64.h | 45 ++++ com.oracle.max.vm.native/share/c.h | 4 +- com.oracle.max.vm.native/share/condition.c | 33 ++- com.oracle.max.vm.native/share/condition.h | 4 + com.oracle.max.vm.native/share/log.c | 35 +-- com.oracle.max.vm.native/share/mutex.c | 21 +- com.oracle.max.vm.native/share/mutex.h | 3 +- com.oracle.max.vm.native/share/threadLocals.c | 26 ++- com.oracle.max.vm.native/share/threads.h | 7 +- .../share/virtualMemory.c | 154 ++++++++++++-- com.oracle.max.vm.native/substrate/barrier.c | 6 +- com.oracle.max.vm.native/substrate/image.c | 11 +- com.oracle.max.vm.native/substrate/jni.c | 23 +- com.oracle.max.vm.native/substrate/jvm.c | 199 +++++++++++++----- com.oracle.max.vm.native/substrate/jvmti.c | 10 +- com.oracle.max.vm.native/substrate/maxine.c | 116 ++++++++-- com.oracle.max.vm.native/substrate/maxine.h | 2 +- com.oracle.max.vm.native/substrate/memory.c | 6 +- com.oracle.max.vm.native/substrate/signal.c | 37 +++- com.oracle.max.vm.native/substrate/sync.c | 5 +- com.oracle.max.vm.native/substrate/threads.c | 94 ++++++++- com.oracle.max.vm.native/substrate/time.c | 49 ++++- com.oracle.max.vm.native/substrate/trap.c | 74 +++++-- com.oracle.max.vm.native/substrate/trap.h | 14 +- com.oracle.max.vm.native/substrate/vm.h | 4 + 36 files changed, 955 insertions(+), 201 deletions(-) create mode 100644 com.oracle.max.vm.native/platform/usercygwinamd64.h diff --git a/com.oracle.max.vm.native/hosted/platform.c b/com.oracle.max.vm.native/hosted/platform.c index de3410bb39..b0c02489a3 100644 --- a/com.oracle.max.vm.native/hosted/platform.c +++ b/com.oracle.max.vm.native/hosted/platform.c @@ -18,12 +18,21 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if !os_WINDOWS #include +#else + #include + #include +#endif #include "word.h" #include "isa.h" #include "jni.h" #include #include +#include + + JNIEXPORT void JNICALL JVM_OnLoad(JavaVM *vm, char *options, void *arg) @@ -54,7 +63,14 @@ Java_com_sun_max_platform_Platform_nativeGetOS(JNIEnv *env, jclass c) JNIEXPORT jint JNICALL Java_com_sun_max_platform_Platform_nativeGetPageSize(JNIEnv *env, jclass c) { - return (jint) sysconf(_SC_PAGESIZE); + #if os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + return systemInfo.dwPageSize ; + + #else + return (jint) sysconf(_SC_PAGESIZE); + #endif } diff --git a/com.oracle.max.vm.native/javatest/javatest.mk b/com.oracle.max.vm.native/javatest/javatest.mk index 6a76e4ed70..7a92b47a1a 100644 --- a/com.oracle.max.vm.native/javatest/javatest.mk +++ b/com.oracle.max.vm.native/javatest/javatest.mk @@ -27,7 +27,7 @@ LIB = javatest include $(PROJECT)/platform/platform.mk -SOURCES = jvmni.c tests.c threads.c jnitests.c +SOURCES = jvmni.c tests.c threads.c jnitests.c jvm.c jni.c threadLocals.c image.c log.c virtualMemory.c mutex.c c.c trap.c time.c jmm.c jvmti.c relocation.c signal.c dataio.c SOURCE_DIRS = javatest jni platform hosted share substrate diff --git a/com.oracle.max.vm.native/javatest/tests.c b/com.oracle.max.vm.native/javatest/tests.c index 94c9cb4f4b..f700cd6dac 100644 --- a/com.oracle.max.vm.native/javatest/tests.c +++ b/com.oracle.max.vm.native/javatest/tests.c @@ -24,8 +24,11 @@ * JNI code for any of the JavaTester tests that use native methods. */ #include "os.h" - +#if !os_WINDOWS #include +#else + #include +#endif #include "jni.h" JNIEXPORT void JNICALL @@ -96,23 +99,42 @@ void upcall(jclass cls) { (*env)->DeleteGlobalRef(env, cls); (*vm)->DetachCurrentThread(vm); } - +#if os_WINDOWS +DWORD WINAPI thread_function(void *arguments) {//we prefer this signature in order to avoid compiler waring on Windows. +#else void *thread_function(void *arguments) { +#endif upcall((jclass) arguments); - return NULL; + #if os_WINDOWS + return 0; + #else + return NULL; + #endif } JNIEXPORT void JNICALL Java_test_output_AttachThread_callHelloWorldOnAttachedThread(JNIEnv *env, jclass clazz) { - pthread_t thread_id; - pthread_attr_t attributes; - + #if !os_WINDOWS + pthread_t thread_id; + pthread_attr_t attributes; + + #endif /* Convert argument to be a global handle as it is going to the new thread */ clazz = (*env)->NewGlobalRef(env, clazz); - void *arguments = clazz; + #if os_WINDOWS + LPVOID + #else + void * + #endif + arguments = clazz; + #if !os_WINDOWS pthread_attr_init(&attributes); pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE); pthread_create(&thread_id, &attributes, thread_function, arguments); pthread_attr_destroy(&attributes); + #else + CreateThread(NULL, 0, thread_function, arguments, 0, NULL); + + #endif } diff --git a/com.oracle.max.vm.native/launch/maxvm.c b/com.oracle.max.vm.native/launch/maxvm.c index 1c45914fff..214a12a67e 100644 --- a/com.oracle.max.vm.native/launch/maxvm.c +++ b/com.oracle.max.vm.native/launch/maxvm.c @@ -18,13 +18,19 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + #include "os.h" +#if os_WINDOWS +#include +char last_dl_error [100]; //emulating dlerror() function not available on Windows + +#else #include +#endif #include #include #include #include -#include "os.h" #include "maxine.h" typedef int (*MaxineFunction)(int argc, char *argv[], char *executablePath); @@ -58,6 +64,15 @@ typedef int (*MaxineFunction)(int argc, char *argv[], char *executablePath); #include const CFNullRef initializeCoreFoundationOnMainThread; +#elif os_WINDOWS +#define LIBRARY_NAME "jvm.dll" +#define MAIN_EXTRA_ARGS +#define PROG_PATH argv[0] +char *dlerror(){ + + + return last_dl_error; +} #else #define LIBRARY_NAME "libjvm.so" #define MAIN_EXTRA_ARGS @@ -108,23 +123,42 @@ int main(int argc, char *argv[] MAIN_EXTRA_ARGS) { strncpy(libraryPath, programPath, prefixLength); strcpy(libraryPath + prefixLength, LIBRARY_NAME); #endif + #if os_WINDOWS + void *result = LoadLibraryA(libraryPath); + if (result==NULL) { + sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); + fprintf(stderr, "could not load %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); + exit(1); + + } + MaxineFunction maxine = (MaxineFunction) GetProcAddress(result, "maxine"); + if (maxine == 0) { + sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); + fprintf(stderr, "could not find symbol 'maxine' in %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); + exit(1); + } + + return (*maxine)(argc, argv, NULL); + #else void *handle = dlopen(libraryPath, RTLD_LAZY | RTLD_GLOBAL); if (handle == 0) { - fprintf(stderr, "could not load %s: %s\n", LIBRARY_NAME, dlerror()); + fprintf(stderr, "could not load %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); exit(1); } MaxineFunction maxine = (MaxineFunction) dlsym(handle, "maxine"); if (maxine == 0) { - fprintf(stderr, "could not find symbol 'maxine' in %s: %s\n", LIBRARY_NAME, dlerror()); + fprintf(stderr, "could not find symbol 'maxine' in %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); exit(1); } + #endif #if os_DARWIN return (*maxine)(argc, argv, programPath); #else free(libraryPath); + return (*maxine)(argc, argv, NULL); #endif } diff --git a/com.oracle.max.vm.native/makefile b/com.oracle.max.vm.native/makefile index cab187f58c..e5c253f008 100644 --- a/com.oracle.max.vm.native/makefile +++ b/com.oracle.max.vm.native/makefile @@ -28,7 +28,7 @@ include platform/platform.mk -all : hosted substrate launch tele javatest +all : hosted substrate launch javatest tele hosted : build/$(OS)/hosted/makefile $(AT) (cd build/$(OS)/hosted; $(MAKE) all) diff --git a/com.oracle.max.vm.native/platform/aarch64.c b/com.oracle.max.vm.native/platform/aarch64.c index 3b946e3ff8..b8ca765cf4 100644 --- a/com.oracle.max.vm.native/platform/aarch64.c +++ b/com.oracle.max.vm.native/platform/aarch64.c @@ -23,7 +23,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_CanonicalIntegerRegisters c) { -#if os_LINUX +#if os_LINUX || os_WINDOWS #define CANONICALIZE(reg) c->r##reg = (Word) os->regs[reg] #else #define CANONICALIZE(reg, ucReg) c_UNIMPLEMENTED() diff --git a/com.oracle.max.vm.native/platform/aarch64.h b/com.oracle.max.vm.native/platform/aarch64.h index 75303f0b13..5efd40fd8d 100644 --- a/com.oracle.max.vm.native/platform/aarch64.h +++ b/com.oracle.max.vm.native/platform/aarch64.h @@ -23,7 +23,7 @@ #include "word.h" -#if os_LINUX +#if (os_LINUX || os_WINDOWS) # include # include typedef struct user_regs_struct *aarch64_OsTeleIntegerRegisters; diff --git a/com.oracle.max.vm.native/platform/amd64.c b/com.oracle.max.vm.native/platform/amd64.c index 5db518c005..df6edd7508 100644 --- a/com.oracle.max.vm.native/platform/amd64.c +++ b/com.oracle.max.vm.native/platform/amd64.c @@ -27,7 +27,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can #if os_DARWIN #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->__##reg -#elif os_LINUX || os_MAXVE +#elif os_LINUX || os_MAXVE || os_WINDOWS #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->reg #elif os_SOLARIS #define CANONICALIZE(reg, ucReg) c->reg = (Word) os[REG_##ucReg] @@ -58,7 +58,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can void isa_canonicalizeTeleFloatingPointRegisters(isa_OsTeleFloatingPointRegisters os, isa_CanonicalFloatingPointRegisters c) { #if os_DARWIN #define CANONICALIZE(reg) c->xmm##reg = (*((Word *) (&os->__fpu_xmm##reg))) -#elif os_LINUX +#elif os_LINUX || os_WINDOWS #define CANONICALIZE(reg) c->xmm##reg = (Word) ((XMMRegister *) &os->xmm_space)[reg].low #elif os_SOLARIS #define CANONICALIZE(reg) c->xmm##reg = (Word) *((Word *) &os->fp_reg_set.fpchip_state.xmm[reg]) @@ -92,7 +92,7 @@ void isa_canonicalizeTeleStateRegisters(isa_OsTeleStateRegisters os, isa_Canonic #if os_DARWIN c->rip = (Word) os->__rip; c->flags = (Word) os->__rflags; -#elif os_LINUX +#elif os_LINUX || os_WINDOWS c->rip = (Word) os->rip; c->flags = (Word) os->eflags; #elif os_SOLARIS diff --git a/com.oracle.max.vm.native/platform/amd64.h b/com.oracle.max.vm.native/platform/amd64.h index 25f1015604..731be34164 100644 --- a/com.oracle.max.vm.native/platform/amd64.h +++ b/com.oracle.max.vm.native/platform/amd64.h @@ -40,6 +40,16 @@ Word low; Word high; } XMMRegister; +#elif os_WINDOWS +//# include +# include "usercygwinamd64.h" + typedef struct user_regs_struct *amd64_OsTeleIntegerRegisters; + typedef struct user_fpregs_struct *amd64_OsTeleFloatingPointRegisters; + typedef struct user_regs_struct *amd64_OsTeleStateRegisters; + typedef struct { + Word low; + Word high; + } XMMRegister; #elif os_SOLARIS # include typedef prgreg_t *amd64_OsTeleIntegerRegisters; @@ -47,6 +57,12 @@ typedef prgreg_t *amd64_OsTeleStateRegisters; #elif os_MAXVE # include +# include + typedef struct db_regs* amd64_OsTeleIntegerRegisters; + typedef struct db_regs* amd64_OsTeleStateRegisters; + typedef struct db_regs* amd64_OsTeleFloatingPointRegisters; +#elif os_WINDOWS +# include # include typedef struct db_regs* amd64_OsTeleIntegerRegisters; typedef struct db_regs* amd64_OsTeleStateRegisters; diff --git a/com.oracle.max.vm.native/platform/arm.c b/com.oracle.max.vm.native/platform/arm.c index 6b73ec0f9d..8ca37e79bc 100644 --- a/com.oracle.max.vm.native/platform/arm.c +++ b/com.oracle.max.vm.native/platform/arm.c @@ -25,7 +25,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can #if os_DARWIN #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->__##reg -#elif os_LINUX || os_MAXVE +#elif os_LINUX || os_MAXVE || os_WINDOWS #ifdef __arm__ #define CANONICALIZE(reg, intpos) c->reg = (Word) os->uregs[intpos] #else @@ -79,7 +79,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can void isa_canonicalizeTeleFloatingPointRegisters(isa_OsTeleFloatingPointRegisters os, isa_CanonicalFloatingPointRegisters c) { #if os_DARWIN #define CANONICALIZE(reg) c->xmm##reg = (*((Word *) (&os->__fpu_xmm##reg))) -#elif os_LINUX +#elif os_LINUX || os_WINDOWS #define CANONICALIZE(reg) c->xmm##reg = (Word) ((XMMRegister *) &os->xmm_space)[reg].low #elif os_SOLARIS #define CANONICALIZE(reg) c->xmm##reg = (Word) *((Word *) &os->fp_reg_set.fpchip_state.xmm[reg]) @@ -116,7 +116,7 @@ void isa_canonicalizeTeleStateRegisters(isa_OsTeleStateRegisters os, isa_Canonic #if os_DARWIN c->rip = (Word) os->__rip; c->flags = (Word) os->__rflags; -#elif os_LINUX +#elif os_LINUX || os_WINDOWS #ifdef __arm__ log_println("ARM: isa_canonicalizeTeleStateRegisters is not implemented!"); #else diff --git a/com.oracle.max.vm.native/platform/platform.mk b/com.oracle.max.vm.native/platform/platform.mk index 69221735ef..fe15588ab0 100644 --- a/com.oracle.max.vm.native/platform/platform.mk +++ b/com.oracle.max.vm.native/platform/platform.mk @@ -22,6 +22,7 @@ # # Print verbose output only when MX_VERBOSE is set to y (i.e. mx -V command is used) + ifneq ($(MX_VERBOSE), y) AT := @ MAKE := $(MAKE) -s @@ -54,6 +55,8 @@ ifneq ($(MAIN),) TARGET := LAUNCH endif +OS := windows +ISA := amd64 # HOSTOS is the platform we are compiling on HOSTOS = $(shell uname -s) # TARGETOS is the platform we are compiling for (usually the same as HOSTOS) @@ -151,9 +154,9 @@ ifeq ($(TARGETOS),SunOS) endif endif -ifeq ($(findstring CYGWIN,$(TARGETOS)),CYGWIN) +ifeq ($(TARGETOS),WindowsNT) OS := windows - ISA := ia32 + ISA := amd64 endif # There are three variants for Maxine VE, owing to the 32/64 dom0 variants @@ -310,20 +313,33 @@ ifeq ($(OS),solaris) endif ifeq ($(OS),windows) - # determine predefined macros: touch foo.c; gcc -E -dD foo.c ifneq "$(findstring def, $(origin CC))" "" # origin of CC is either undefined or default, so set it here CC = gcc endif ifneq "$(findstring def, $(origin CFLAGS))" "" # origin of CFLAGS is either undefined or default, so set it here - CFLAGS = -g -ansi -Wall -pedantic -Wno-long-long -mno-cygwin -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) + CFLAGS = -g -Wall -Wno-long-long -Wextra -Wno-main -Wno-unused-parameter -fPIC -D_GNU_SOURCE -D$(ISA) -DWINDOWS -D__int64=int64_t -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) $(OTHER_CFLAGS) endif - C_DEPENDENCIES_FLAGS = -MM -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) - LINK_MAIN = $(CC) -g -mno-cygwin -Wall -W1,----add-stdcall-alias -ldl - LINK_LIB = $(CC) -g -shared -mno-cygwin -Wall -W1,----add-stdcall-alias + C_DEPENDENCIES_FLAGS = -M -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) + # The '-rpath' linker option is used so that LD_LIBRARY_PATH does not have to be configured at runtime to + # find Maxine's version of the libjvm.so library. + # The '-z execstack' is a workaround that stops the runtime dynamic linker from + # changing the protection of the main thread's stack (via mprotect) *after* the + # yellow guard page (for detecting stack overflow) has been mprotected. Without + # this flag, the main thread's complete stack (including the guard page) is + # mprotected with PROT_READ, PROT_WRITE, PROT_EXEC when dlopen() is called to + # open libjava.so. + LINK_MAIN = $(CC) -g -Xlinker -rpath -Xlinker $(shell cd $(PROJECT)/generated/$(OS) && /bin/pwd) -o $(MAIN) + + LINK_LIB = $(CC) -g -shared -mwindows + LINK_LIB_POSTFIX += -lole32 -lws2_32 + + + LIB_PREFIX = - LIB_SUFFIX = .dll + LIB_SUFFIX = .dll + endif ifeq ($(OS),maxve) @@ -413,9 +429,15 @@ else endif JNI_INCLUDES = -I $(dir $(JNI_H_PATH)) endif - else - JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) - JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) + else + ifeq ($(OS),windows) + JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/win32/ + JNI_H_PATH = $(JAVA_HOME)/include/win32/jni.h + else + JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) + JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) + endif + endif endif diff --git a/com.oracle.max.vm.native/platform/usercygwinamd64.h b/com.oracle.max.vm.native/platform/usercygwinamd64.h new file mode 100644 index 0000000000..e1a4c0d496 --- /dev/null +++ b/com.oracle.max.vm.native/platform/usercygwinamd64.h @@ -0,0 +1,45 @@ +struct user_fpregs_struct +{ + unsigned short int cwd; + unsigned short int swd; + unsigned short int ftw; + unsigned short int fop; + __extension__ unsigned long long int rip; + __extension__ unsigned long long int rdp; + unsigned int mxcsr; + unsigned int mxcr_mask; + unsigned int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ + unsigned int padding[24]; +}; + +struct user_regs_struct +{ + __extension__ unsigned long long int r15; + __extension__ unsigned long long int r14; + __extension__ unsigned long long int r13; + __extension__ unsigned long long int r12; + __extension__ unsigned long long int rbp; + __extension__ unsigned long long int rbx; + __extension__ unsigned long long int r11; + __extension__ unsigned long long int r10; + __extension__ unsigned long long int r9; + __extension__ unsigned long long int r8; + __extension__ unsigned long long int rax; + __extension__ unsigned long long int rcx; + __extension__ unsigned long long int rdx; + __extension__ unsigned long long int rsi; + __extension__ unsigned long long int rdi; + __extension__ unsigned long long int orig_rax; + __extension__ unsigned long long int rip; + __extension__ unsigned long long int cs; + __extension__ unsigned long long int eflags; + __extension__ unsigned long long int rsp; + __extension__ unsigned long long int ss; + __extension__ unsigned long long int fs_base; + __extension__ unsigned long long int gs_base; + __extension__ unsigned long long int ds; + __extension__ unsigned long long int es; + __extension__ unsigned long long int fs; + __extension__ unsigned long long int gs; +}; diff --git a/com.oracle.max.vm.native/share/c.h b/com.oracle.max.vm.native/share/c.h index c4add88ca4..ed33c77f61 100644 --- a/com.oracle.max.vm.native/share/c.h +++ b/com.oracle.max.vm.native/share/c.h @@ -53,10 +53,12 @@ typedef long long Signed8; typedef float Float4; typedef double Float8; +#define true 1 +#define false 0 #if !defined(false) && !defined(true) typedef enum {false, true} boolean; #else - typedef int boolean; + typedef unsigned char boolean; #endif #define MAX_PATH_LENGTH 2048 diff --git a/com.oracle.max.vm.native/share/condition.c b/com.oracle.max.vm.native/share/condition.c index 90e052fcfe..b8b8feac0c 100644 --- a/com.oracle.max.vm.native/share/condition.c +++ b/com.oracle.max.vm.native/share/condition.c @@ -18,6 +18,15 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if os_WINDOWS +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 // needed for tools like MINGW in order to use condition variables which became available from Windows Vista and on. Visual Studio might define it on its own +#include + +#endif #include #include #include @@ -45,6 +54,10 @@ void condition_initialize(Condition condition) { } #elif os_MAXVE *condition = maxve_condition_create(); +#elif os_WINDOWS + InitializeConditionVariable(condition); + //initialize condtionVariable does not return anything! + #else # error #endif @@ -62,6 +75,8 @@ void condition_destroy(Condition condition) { if (pthread_cond_destroy(condition) != 0) { c_FATAL(); } +#elif os_WINDOWS +//condition variables cannot get destroyed https://stackoverflow.com/questions/28975958/why-does-windows-have-no-deleteconditionvariable-function-to-go-together-with #endif } @@ -80,7 +95,7 @@ void condition_destroy(Condition condition) { * @return false if an error occurred, true otherwise (i.e. the thread was notified or interrupted). * In either case, the current thread has reacquired the lock on 'mutex'. */ -boolean condition_wait(Condition condition, Mutex mutex) { +boolean condition_wait(Condition condition, Mutex mutex) { //mutex is not needed in windows #if log_MONITORS log_println("condition_wait (" THREAD_CONDVAR_MUTEX_FORMAT ")", thread_self(), condition, mutex); #endif @@ -101,6 +116,8 @@ boolean condition_wait(Condition condition, Mutex mutex) { /* (Doug) I assume 1 means EINTR */ return true; } +#elif os_WINDOWS + error = !SleepConditionVariableCS (condition, mutex, INFINITE); // non zero return value means success on Windows! #endif if (error != 0) { log_println("condition_wait (" THREAD_CONDVAR_MUTEX_FORMAT ") unexpected error code %d [%s]", thread_self(), condition, mutex, error, strerror(error)); @@ -112,7 +129,7 @@ boolean condition_wait(Condition condition, Mutex mutex) { return true; } -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) /* * This function is taken from HotSpot (os_linux.cpp). */ @@ -159,7 +176,7 @@ boolean condition_timedWait(Condition condition, Mutex mutex, Unsigned8 timeoutM log_println("condition_timedWait (" THREAD_CONDVAR_MUTEX_FORMAT ", %d)", thread_self(), condition, mutex, timeoutMilliSeconds); #endif int error; -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) struct timeval now; int status = gettimeofday(&now, NULL); c_ASSERT(status != -1); @@ -198,6 +215,8 @@ boolean condition_timedWait(Condition condition, Mutex mutex, Unsigned8 timeoutM /* (Doug) I assume 1 means EINTR */ return true; } +#elif os_WINDOWS + error = !SleepConditionVariableCS (condition, mutex, timeoutMilliSeconds); // non zero return value means success on Windows! #else # error #endif @@ -222,6 +241,9 @@ boolean condition_notify(Condition condition) { return cond_signal(condition) == 0; #elif os_MAXVE return maxve_condition_notify(*condition, 0) == 0; +#elif os_WINDOWS + WakeConditionVariable (condition); //WakeConditionVariable returns nothing + return true; #else # error #endif @@ -231,12 +253,15 @@ boolean condition_notifyAll(Condition condition) { #if log_MONITORS log_println("condition_notifyAll (" THREAD_CONDVAR_FORMAT ")", thread_self(), condition); #endif -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) return pthread_cond_broadcast(condition) == 0; #elif os_SOLARIS return cond_broadcast(condition) == 0; #elif os_MAXVE return maxve_condition_notify(*condition, 1) == 0; +#elif os_WINDOWS + WakeAllConditionVariable (condition); //WakeAllConditionVariable returns nothing + return true; #else # error #endif diff --git a/com.oracle.max.vm.native/share/condition.h b/com.oracle.max.vm.native/share/condition.h index 93c379f5ca..953fa41c4b 100644 --- a/com.oracle.max.vm.native/share/condition.h +++ b/com.oracle.max.vm.native/share/condition.h @@ -36,6 +36,10 @@ #elif os_MAXVE # include "maxve.h" typedef maxve_condition_t condition_Struct; +#elif os_WINDOWS + typedef CONDITION_VARIABLE condition_Struct; + + #endif typedef condition_Struct *Condition; diff --git a/com.oracle.max.vm.native/share/log.c b/com.oracle.max.vm.native/share/log.c index a5bedc320a..5e5a04a828 100644 --- a/com.oracle.max.vm.native/share/log.c +++ b/com.oracle.max.vm.native/share/log.c @@ -18,17 +18,28 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + + #include #include #include #include -#include #include "log.h" +#if os_WINDOWS +#include +#define pthread_self GetCurrentThread +#else +#include + +#endif + #include "jni.h" #include "mutex.h" #include "threads.h" + + #if !os_MAXVE static FILE *fileStream = NULL; #endif @@ -46,14 +57,14 @@ static mutex_Struct allocationProfiler_mutexStruct; void log_initialize(const char *path) { mutex_initialize(&log_mutexStruct); mutex_initialize(&allocationProfiler_mutexStruct); -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS if (path == NULL) { path = "stdout"; } if (strncmp(path, "stdout\0", 7) == 0) { fileStream = stdout; /* Set the file stream to flush whenever a newline character is encountered */ - setlinebuf(fileStream); + // setlinebuf(fileStream); } else if (strncmp(path, "stderr\0", 7) == 0) { fileStream = stderr; } else { @@ -63,7 +74,7 @@ void log_initialize(const char *path) { exit(1); } /* Set the file stream to flush whenever a newline character is encountered */ - setlinebuf(fileStream); + // setlinebuf(fileStream); } #endif } @@ -71,7 +82,7 @@ void log_initialize(const char *path) { void log_lock(void) { int result; if ((result = mutex_enter_nolog(&log_mutexStruct)) != 0) { - log_exit(-1, "Thread %p could not lock mutex %p: %s", thread_self(), &log_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not lock mutex %p: %s", pthread_self(), &log_mutexStruct, strerror(result)); } } @@ -79,14 +90,14 @@ void numaProfiler_lock(void) { int result; result = mutex_enter_nolog(&allocationProfiler_mutexStruct); if (result != 0) { - log_exit(-1, "Thread %p could not lock mutex %p: %s", thread_self(), &allocationProfiler_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not lock mutex %p: %s", pthread_self(), &allocationProfiler_mutexStruct, strerror(result)); } } void log_unlock(void) { int result; if ((result = mutex_exit_nolog(&log_mutexStruct)) != 0) { - log_exit(-1, "Thread %p could not unlock mutex %p: %s", thread_self(), &log_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not unlock mutex %p: %s", pthread_self(), &log_mutexStruct, strerror(result)); } } @@ -94,7 +105,7 @@ void numaProfiler_unlock(void) { int result; result = mutex_exit_nolog(&allocationProfiler_mutexStruct); if (result != 0) { - log_exit(-1, "Thread %p could not unlock mutex %p: %s", thread_self(), &allocationProfiler_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not unlock mutex %p: %s", pthread_self(), &allocationProfiler_mutexStruct, strerror(result)); } } @@ -111,14 +122,14 @@ void log_print_format(const char *format, ...) { } void log_flush() { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS FILE* out = fileStream == NULL ? stdout : fileStream; fflush(out); #endif } void log_print_vformat(const char *format, va_list ap) { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS FILE* out = fileStream == NULL ? stdout : fileStream; vfprintf(out, format, ap); #else @@ -197,8 +208,8 @@ void log_print_newline() { } void log_print_symbol(Address address) { -#if !os_MAXVE - Dl_info info; +#if !os_MAXVE && !os_WINDOWS + Dl_info info; if (dladdr((void *) address, &info) != 0) { if (info.dli_sname == NULL) { log_print("%s (%p+%d)", info.dli_fname, info.dli_fbase, address - (Address) info.dli_fbase); diff --git a/com.oracle.max.vm.native/share/mutex.c b/com.oracle.max.vm.native/share/mutex.c index 4902d146fc..3ed0431939 100644 --- a/com.oracle.max.vm.native/share/mutex.c +++ b/com.oracle.max.vm.native/share/mutex.c @@ -20,6 +20,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +#include "os.h" +#if os_WINDOWS +#include +#endif + #include "mutex.h" #include "log.h" #include "threads.h" @@ -50,6 +55,8 @@ void mutex_initialize(Mutex mutex) { } #elif os_MAXVE *mutex = maxve_monitor_create(); +#elif os_WINDOWS + InitializeCriticalSection(mutex); //windows CS's are recursive be default ,mutex is pointer to Critical section # else c_UNIMPLEMENTED(); # endif @@ -65,6 +72,9 @@ int mutex_enter_nolog(Mutex mutex) { c_ASSERT(false); } return 0; +#elif os_WINDOWS + EnterCriticalSection(mutex); //mutex is pointer to Critical section. EnterCriticalSection returns nothing + return 0; //0 means success for funcs like pthread_mutex_lock #else c_UNIMPLEMENTED(); #endif @@ -73,8 +83,11 @@ int mutex_enter_nolog(Mutex mutex) { int mutex_try_enter(Mutex mutex) { #if os_SOLARIS return mutex_trylock(mutex); -#elif os_LINUX || os_DARWIN +#elif os_LINUX || os_DARWIN return pthread_mutex_trylock(mutex); +#elif os_WINDOWS + return !TryEnterCriticalSection(mutex); //mutex is pointer to Critical section. On windows non zero return value means success that's why we use ! at the result + #else c_UNIMPLEMENTED(); #endif @@ -98,6 +111,9 @@ int mutex_exit_nolog(Mutex mutex) { c_ASSERT(false); } return 0; +#elif os_WINDOWS + LeaveCriticalSection(mutex); //mutex is pointer to Critical section + return 0; #else c_UNIMPLEMENTED(); #endif @@ -124,5 +140,8 @@ void mutex_dispose(Mutex mutex) { } #elif os_MAXVE c_UNIMPLEMENTED(); +#elif os_WINDOWS + DeleteCriticalSection(mutex); //mutex is pointer to Critical section + #endif } diff --git a/com.oracle.max.vm.native/share/mutex.h b/com.oracle.max.vm.native/share/mutex.h index 962941271a..68ebec04de 100644 --- a/com.oracle.max.vm.native/share/mutex.h +++ b/com.oracle.max.vm.native/share/mutex.h @@ -35,8 +35,9 @@ #elif os_MAXVE # include typedef maxve_monitor_t mutex_Struct; +#elif os_WINDOWS +typedef CRITICAL_SECTION mutex_Struct; #endif - typedef mutex_Struct *Mutex; extern void mutex_initialize(Mutex mutex); diff --git a/com.oracle.max.vm.native/share/threadLocals.c b/com.oracle.max.vm.native/share/threadLocals.c index 5868340538..11b7a7ea24 100644 --- a/com.oracle.max.vm.native/share/threadLocals.c +++ b/com.oracle.max.vm.native/share/threadLocals.c @@ -18,7 +18,14 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include + #include "os.h" +#if !os_WINDOWS + #include +#else + #include + #include + #define aligned_alloc(a, b) _aligned_malloc(a, b) +#endif #include #include @@ -48,6 +55,9 @@ typedef maxve_Thread Thread; typedef maxve_SpecificsKey ThreadLocalsKey; typedef void (*ThreadLocalsBlockDestructor)(void *); +#elif os_WINDOWS + typedef DWORD ThreadLocalsKey; + #endif int theTLASize = -1; @@ -86,7 +96,7 @@ static void deallocateThreadLocalBlock(Address tlBlock, Size tlBlockSize) { * lazily commit memory reserved for the initial thread's stack. */ static void commitStackMemoryForInitialThread(Address base, int pageSize) { -#if os_LINUX +#if os_LINUX || os_WINDOWS /* Writing to the bottom page of the reserved stack (appears) not to be * sufficient on Linux. Using alloca() to allocate a chunk approximately * the size of the remaining stack seems to fix it. */ @@ -347,7 +357,7 @@ void threadLocalsBlock_destroy(Address tlBlock) { void tla_initialize(int tlaSize) { theTLASize = tlaSize; #if !TELE -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX int error = pthread_key_create(&theThreadLocalsKey, (ThreadLocalsBlockDestructor)(void *) threadLocalsBlock_destroy); #if log_THREADS log_println("tla_initialize: pthread_key_create returned code = %d", error); @@ -355,6 +365,8 @@ void tla_initialize(int tlaSize) { if (error != 0) { log_exit(-1, "tla_initialize: pthread_key_create returned non zero code = %d", error); } +#elif os_WINDOWS + theThreadLocalsKey = TlsAlloc(); #elif os_SOLARIS thr_keycreate(&theThreadLocalsKey, (ThreadLocalsBlockDestructor) threadLocalsBlock_destroy); #elif os_MAXVE @@ -368,7 +380,7 @@ void tla_initialize(int tlaSize) { Address threadLocalsBlock_current() { Address tlBlock; -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX tlBlock = (Address) pthread_getspecific(theThreadLocalsKey); #elif os_SOLARIS Address value; @@ -379,6 +391,8 @@ Address threadLocalsBlock_current() { tlBlock = value; #elif os_MAXVE tlBlock = (Address) maxve_thread_getSpecific(theThreadLocalsKey); +#elif os_WINDOWS + tlBlock = (Address) TlsGetValue(theThreadLocalsKey); #else c_UNIMPLEMENTED(); #endif @@ -386,12 +400,14 @@ Address threadLocalsBlock_current() { } void threadLocalsBlock_setCurrent(Address tlBlock) { -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) pthread_setspecific(theThreadLocalsKey, (void *) tlBlock); #elif os_SOLARIS thr_setspecific(theThreadLocalsKey, (void *) tlBlock); #elif os_MAXVE maxve_thread_setSpecific(theThreadLocalsKey, (void *) tlBlock); +#elif os_WINDOWS + TlsSetValue(theThreadLocalsKey, (LPVOID) tlBlock); #endif } diff --git a/com.oracle.max.vm.native/share/threads.h b/com.oracle.max.vm.native/share/threads.h index f360882742..63b48db454 100644 --- a/com.oracle.max.vm.native/share/threads.h +++ b/com.oracle.max.vm.native/share/threads.h @@ -80,8 +80,13 @@ typedef void (*VmThreadDetachMethod)(Address tla); * @return true if the sleep was interrupted */ extern jboolean thread_sleep(jlong numberOfMilliSeconds); +#if os_WINDOWS +DWORD WINAPI thread_run(LPVOID param); +#else + +void * thread_run(void *arg); -void *thread_run(void *arg); +#endif int thread_attachCurrent(void **penv, JavaVMAttachArgs* args, boolean daemon); int thread_detachCurrent(); diff --git a/com.oracle.max.vm.native/share/virtualMemory.c b/com.oracle.max.vm.native/share/virtualMemory.c index 1846d69f03..5ef4152e04 100644 --- a/com.oracle.max.vm.native/share/virtualMemory.c +++ b/com.oracle.max.vm.native/share/virtualMemory.c @@ -18,18 +18,28 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + + #include "virtualMemory.h" #include "log.h" + #if defined(MAXVE) -#include + #include /* No mmap function on MaxVE (yet)*/ #else -#include -#include -#include -#include - + #include + #include + #include + #if !os_WINDOWS + #include + #else + #ifdef _WIN32_WINNT + #undef _WIN32_WINNT + #endif + #define _WIN32_WINNT 0x0601 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. + #include + #endif #include "jni.h" #include "unistd.h" @@ -39,7 +49,7 @@ #endif /* There is a problem binding these identifiers in RedHat's include files, so we fake them: */ -#if os_LINUX +#if os_LINUX || os_WINDOWS # ifndef MAP_ANONYMOUS # define MAP_ANONYMOUS 0x20 # endif @@ -58,11 +68,16 @@ # define MAP_32BIT 0 # endif #endif - +#if !os_WINDOWS #define PROT (PROT_EXEC | PROT_READ | PROT_WRITE) +#endif + +#if !os_WINDOWS //we do not use mmap on Windows so this function is not needed. /* mmap returns MAP_FAILED on error, we convert to ALLOC_FAILED */ static Address check_mmap_result(void *result) { + + #if log_MMAP if(result == MAP_FAILED) { switch(errno) { @@ -99,8 +114,11 @@ static Address check_mmap_result(void *result) { } } #endif + return ((Address) (result == (void *) MAP_FAILED ? ALLOC_FAILED : result)); } +#endif + #ifdef arm static int attempt = 0; @@ -125,8 +143,36 @@ Address virtualMemory_allocatePrivateAnon(Address address, Size size, jboolean r address = allocAddress; } #endif +#if os_WINDOWS + //Windows got no Swap space, so jboolean reserveSwap is redundant + Address result; + if(protNone == JNI_TRUE){ + + result = (Address) VirtualAlloc( (void *) address, size, MEM_COMMIT | MEM_RESERVE| PAGE_WRITECOPY, PAGE_NOACCESS); + + //virtualalloc is the only win32 function that supports the PROT_NONE equivalent PAGE_NOACCESS + //PAGE_WRITECOPY is equivalent to MAP_PRIVATE + if(!result) + log_println("%d\n", GetLastError()); + } + else { + //if protnone is not used, we can use CreateFileMappingA + MapViewOfFile combination to emulate mmap() on Windows + //INVALID_HANDLE_VALUE means that we dont use an actual file but the system pagefile, similar to fd= -1 & MPI_ANON in mmap() + HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + //FILE_MAP_COPY is equivalent to MAP_PRIVATE +if(!fmapping) + log_println("%d\n", GetLastError()); + result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, 0, 0, size, (LPVOID)address); + if(!result) + log_println("%d\n", GetLastError()); + + + } + return result; + +#else int flags = MAP_PRIVATE | MAP_ANON; -#if os_LINUX +#if os_LINUX /* For some reason, subsequent calls to mmap to allocate out of the space * reserved here only work if the reserved space is in 32-bit space. */ #endif @@ -153,6 +199,7 @@ Address virtualMemory_allocatePrivateAnon(Address address, Size size, jboolean r #else return check_mmap_result(result); #endif +#endif } @@ -172,6 +219,15 @@ Address virtualMemory_mapFile(Size size, jint fd, Size offset) { address = check_mmap_result(result); allocAddress = address + size; return address; +#elif os_WINDOWS + HANDLE fmapping = CreateFileMappingA( (HANDLE)_get_osfhandle(fd) , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA + Address result = (Address) MapViewOfFile (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size); + //FILE_MAP_COPY is equivalent to mmap's MAP_PRIVATE. It maps a copy-on-write view of the file that is private to the process. + //MapViewOfFile needs lower and high order of offset (last and first 32 bits). We get high and lower orders of the offset (which might be 64bit long) by doing casts to DWORD( 32 BITS) and Binary shifts + if(!result) + log_println("%d\n", GetLastError()); + return result; #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_PRIVATE, fd, (off_t) offset)); #endif @@ -183,7 +239,20 @@ Java_com_sun_max_memory_VirtualMemory_virtualMemory_1mapFile(JNIEnv *env, jclass } Address virtualMemory_mapFileIn31BitSpace(jint size, jint fd, Size offset) { + #if os_WINDOWS //MAP_32BIT is not supported on Windows.... Also in Linux, it is no longer really needed + /*"It was added to allow thread stacks to be + allocated somewhere in the first 2 GB of memory, so as to + improve context-switch performance on some early 64-bit + processors. Modern x86-64 processors no longer have this + performance problem, so use of this flag is not required on + those systems. + + https://man7.org/linux/man-pages/man2/mmap.2.html + */ + return virtualMemory_mapFile(size, fd, offset); + #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_PRIVATE | MAP_32BIT, fd, (off_t) offset)); + #endif } JNIEXPORT jlong JNICALL @@ -192,7 +261,20 @@ Java_com_sun_max_memory_VirtualMemory_virtualMemory_1mapFileIn31BitSpace(JNIEnv } Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, Size offset) { + #if os_WINDOWS + HANDLE fmapping = CreateFileMappingA( (HANDLE)_get_osfhandle(fd) , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,0, NULL); + //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA + if(!fmapping) + log_println("%d\n", GetLastError()); + Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size,(LPVOID) address); + //the only diffrence is that we use MapViewOfFileEx instead MapViewOfFile. The first one allows us to provide an initial base address where the mapping begins (last argument) + + if(!result) + log_println("%d\n", GetLastError()); + return result; + #else return check_mmap_result(mmap((void *) address, (size_t) size, PROT, MAP_PRIVATE | MAP_FIXED, fd, (off_t) offset)); + #endif } // end of conditional exclusion of mmap stuff not available (or used) on MAXVE @@ -202,14 +284,23 @@ Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, Address virtualMemory_allocate(Size size, int type) { #if os_MAXVE return (Address) maxve_virtualMemory_allocate(size, type); +#elif os_WINDOWS + HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + Address result = (Address) MapViewOfFile (fmapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size); + if(!result) + log_println("%d\n", GetLastError()); + return result; #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)); #endif } Address virtualMemory_allocateIn31BitSpace(Size size, int type) { -#if os_LINUX +#if os_LINUX return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1, (off_t) 0)); + +#elif os_WINDOWS + return virtualMemory_allocate(size, type); //windows do not have equivalent of MAP_32BIT, also obsolete in Linux #elif os_MAXVE return (Address) maxve_virtualMemory_allocateIn31BitSpace(size, type); #else @@ -221,6 +312,17 @@ Address virtualMemory_allocateIn31BitSpace(Size size, int type) { Address virtualMemory_deallocate(Address start, Size size, int type) { #if os_MAXVE return (Address) maxve_virtualMemory_deallocate((void *)start, size, type); +#elif os_WINDOWS + if( UnmapViewOfFile((LPVOID) start) == 0){ // VirtualFree will fail for addresses mapped with MapViewOfFile so we use UnmapViewOfFile first + int result = VirtualFree((LPVOID)start, size, type); //if UnmapViewOfFile failed, we try virtualalloc (the memory might got mapped with VirtualAlloc) + //type can be MEM_RELEASE or whatever the user provides. (It was implemented for MAXVE that way) + if (!result) + return result; + else + return start; + } + else + return start; #else int result = munmap((void *) start, (size_t) size); return result == -1 ? 0 : start; @@ -230,6 +332,13 @@ Address virtualMemory_deallocate(Address start, Size size, int type) { boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int type) { #if os_SOLARIS || os_DARWIN || os_LINUX return check_mmap_result(mmap((void *) address, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, (off_t) 0)) != ALLOC_FAILED; +#elif os_WINDOWS + HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA + Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, 0, 0, size,(LPVOID) address); + if(!result) + log_println("%d\n", GetLastError()); + return result; #elif os_MAXVE return (Address) maxve_virtualMemory_allocateAtFixedAddress((unsigned long)address, size, type) != ALLOC_FAILED; #else @@ -241,11 +350,18 @@ boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int typ void virtualMemory_protectPages(Address address, int count) { /* log_println("--- protected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ c_ASSERT(virtualMemory_pageAlign(address) == address); -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_NONE) != 0) { int error = errno; log_exit(error, "protectPages: mprotect(%p) failed: %s", address, strerror(error)); } +#elif os_WINDOWS + DWORD old; //needed for VirtualProtect + int error = GetLastError(); + if(!VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_NOACCESS, &old)) //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) + log_exit(error, "protectPages: VirtualProtect(%p) failed", address); + + #elif os_MAXVE maxve_virtualMemory_protectPages(address, count); #else @@ -256,11 +372,14 @@ void virtualMemory_protectPages(Address address, int count) { void virtualMemory_unprotectPages(Address address, int count) { /* log_println("--- unprotected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ c_ASSERT(virtualMemory_pageAlign(address) == address); -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_READ| PROT_WRITE) != 0) { int error = errno; log_exit(error, "unprotectPages: mprotect(%p) failed: %s", address, strerror(error)); } +#elif os_WINDOWS + DWORD old; //needed for VirtualProtect + VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_READWRITE, &old); //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) #elif os_MAXVE maxve_virtualMemory_unProtectPages(address, count); #else @@ -276,7 +395,13 @@ unsigned int virtualMemory_getPageSize(void) { return maxve_virtualMemory_pageSize(); #else if (pageSize == 0) { + #if os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + pageSize = systemInfo.dwPageSize ; + #else pageSize = getpagesize(); + #endif } return pageSize; #endif @@ -287,9 +412,12 @@ Size virtualMemory_getPhysicalMemorySize(void) { #if os_MAXVE // TODO return 0; -#elif os_SOLARIS || os_LINUX +#elif os_SOLARIS || os_LINUX Size numPhysicalPages = (Size) sysconf(_SC_PHYS_PAGES); physicalMemory = numPhysicalPages * virtualMemory_getPageSize(); +#elif os_WINDOWS + GetPhysicallyInstalledSystemMemory(&physicalMemory); + return physicalMemory * 1024; //we want bytes #elif os_DARWIN int query[2]; query[0] = CTL_HW; diff --git a/com.oracle.max.vm.native/substrate/barrier.c b/com.oracle.max.vm.native/substrate/barrier.c index 86bb92ad9d..20fbdcd928 100644 --- a/com.oracle.max.vm.native/substrate/barrier.c +++ b/com.oracle.max.vm.native/substrate/barrier.c @@ -1,6 +1,4 @@ /* - * Copyright (c) 2020, APT Group, Department of Computer Science, - * School of Engineering, The University of Manchester. All rights reserved. * Copyright (c) 2019, APT Group, School of Computer Science, * The University of Manchester. All rights reserved. * @@ -40,7 +38,7 @@ /* * Pre-processor override for whether to compile in the membarrier system call. - * Currently only affects Aarch64 and RISCV64. See syscall_membarrier() in this compilation + * Currently only affects Aarch64. See syscall_membarrier() in this compilation * unit. */ #ifndef USE_SYS_MEMBARRIER @@ -64,7 +62,7 @@ static int membarrier_init(void) __attribute__ ((unused)); void syscall_membarrier() { -#if isa_AARCH64 || isa_RISCV64 +#if isa_AARCH64 # if USE_SYS_MEMBARRIER static volatile int barrier_kind = 0; if (!barrier_kind) { diff --git a/com.oracle.max.vm.native/substrate/image.c b/com.oracle.max.vm.native/substrate/image.c index 9825dd7ab9..198ea69f91 100644 --- a/com.oracle.max.vm.native/substrate/image.c +++ b/com.oracle.max.vm.native/substrate/image.c @@ -20,10 +20,13 @@ */ #include "os.h" + #include #include #include +#if !os_WINDOWS #include +#endif #include #include @@ -277,7 +280,7 @@ static void checkTrailer(int fd) { if (trailerStructPtr->identification != theHeader->identification || trailerStructPtr->bootImageFormatVersion != theHeader->bootImageFormatVersion || trailerStructPtr->randomID != theHeader->randomID) { log_println("inconsistent trailer"); #if !MEMORY_IMAGE - offset = lseek(fd, -sizeof(trailerStruct), SEEK_END); + offset = lseek(fd, (long int)-sizeof(trailerStruct), SEEK_END); if (offset != fileSize - (off_t) sizeof(trailerStruct)) { log_exit(1, "could not set trailer position at end of file"); } @@ -304,7 +307,7 @@ static void mapHeapAndCode(int fd) { #endif #if MEMORY_IMAGE theHeap = (Address) &maxvm_image_start + heapOffsetInImage; -#elif os_SOLARIS || os_DARWIN || os_LINUX +#elif os_SOLARIS || os_DARWIN || os_LINUX || os_WINDOWS Address reservedVirtualSpace = (Address) 0; size_t virtualSpaceSize = 1024L * theHeader->reservedVirtualSpaceSize; c_ASSERT(virtualMemory_pageAlign((Size) virtualSpaceSize) == (Size) virtualSpaceSize); @@ -332,7 +335,7 @@ static void mapHeapAndCode(int fd) { log_exit(4, "could not reserve virtual space for boot image"); } } - if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { + if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { //CAUTION on Windows, the Base Address must be a multiple of dwAllocationGranularity else mapping fails (UNTESTED since no image file is availabe) log_exit(4, "could not map boot image"); } if (reservedVirtualSpace) { @@ -419,7 +422,7 @@ void image_load(char *imageFileName) { } #endif - readHeader(fd); + readHeader(fd); checkImage(); readStringInfo(fd); checkTrailer(fd); diff --git a/com.oracle.max.vm.native/substrate/jni.c b/com.oracle.max.vm.native/substrate/jni.c index 871108e597..a18a76141b 100644 --- a/com.oracle.max.vm.native/substrate/jni.c +++ b/com.oracle.max.vm.native/substrate/jni.c @@ -26,7 +26,10 @@ * arguments in such an array. This isolates the implementation of such functions * from the platform/compiler dependent way in which varargs are implemented. */ -#include +#include "os.h" +#if os_WINDOWS +#include +#endif #include #include #include @@ -37,7 +40,9 @@ #include "threads.h" #include "vm.h" - +#if !os_WINDOWS +#include +#endif #ifndef JNI_VERSION_1_6 #error The version of jni.h being included must define the JNI_VERSION_1_6 macro #endif @@ -808,11 +813,15 @@ jint JNICALL jni_GetEnv(JavaVM *javaVM, void **penv, jint version) { return JNI_OK; } } - +#if os_WINDOWS +__declspec( dllimport ) +#endif jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) { return c_UNIMPLEMENTED(); } - +#if os_WINDOWS +__declspec( dllimport ) +#endif jint JNICALL jni_DestroyJavaVM(JavaVM *vm) { return c_UNIMPLEMENTED(); } @@ -829,7 +838,9 @@ jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { return thread_detachCurrent(); } - +#if os_WINDOWS +__declspec( dllimport ) +#endif jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { return c_UNIMPLEMENTED(); } @@ -857,7 +868,7 @@ JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs_Impl(JavaVM **vm, jsize vmBufLen, j return JNI_OK; } -JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm, jsize vmBufLen, jsize *nVMs) { +JNIEXPORT jint JNICALL __imp_JNI_GetCreatedJavaVMs(JavaVM **vm, jsize vmBufLen, jsize *nVMs) { return JNI_GetCreatedJavaVMs_Impl(vm, vmBufLen, nVMs); } diff --git a/com.oracle.max.vm.native/substrate/jvm.c b/com.oracle.max.vm.native/substrate/jvm.c index c2eab15fbc..0fd63eb587 100644 --- a/com.oracle.max.vm.native/substrate/jvm.c +++ b/com.oracle.max.vm.native/substrate/jvm.c @@ -26,40 +26,71 @@ * In cases where we bypass JDK's native libraries (@see com.sun.max.vm.jdk) * we can simply omit unneeded JVM interface functions that would otherwise occur here. */ -#include +#include "os.h" +#if os_WINDOWS +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. +#include +#include +#define lseek64 _lseeki64 +#define open _open +#define close _close //open and close work on mingw but are deprecated in MSVC so we better use _ before the name. (Internally, they call win32 funcs like CreateFile() and are added by Microsoft for POSIX compatibility +#define ftruncate _chsize +#define ioctl(a, b, c) ioctlsocket(a, b, (u_long *) c) +#include +#endif + + + + +#include "vm.h" +#include "log.h" +#include "trap.h" +#include "mutex.h" +#include "threads.h" +#include "maxine.h" +#include "memory.h" + +#if !os_WINDOWS + #include #include #include -#include -#include + + #include #include #include #include +#endif +#include + +#include +#include + #if os_DARWIN #include -#else +#elif !os_WINDOWS #include #endif +#if !os_WINDOWS +#include +#endif -#include "vm.h" -#include "log.h" -#include "trap.h" -#include "mutex.h" -#include "threads.h" -#include "maxine.h" -#include "memory.h" #if os_SOLARIS #include #endif -#if os_DARWIN +#if os_DARWIN #define lseek64 lseek #include - #endif +#include + // Platform-independent error return values from OS functions enum OSReturn { @@ -253,7 +284,7 @@ JVM_ActiveProcessorCount(void) { } // Otherwise return number of online cpus return online_cpus; -#elif os_LINUX +#elif os_LINUX cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors int cpus_size = sizeof(cpu_set_t); int processor_count = sysconf(_SC_NPROCESSORS_CONF); @@ -279,6 +310,11 @@ JVM_ActiveProcessorCount(void) { int online_cpus = sysconf(_SC_NPROCESSORS_ONLN); c_ASSERT(online_cpus > 0); return online_cpus; +#elif os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + return systemInfo.dwNumberOfProcessors; //not sure if we need logical or physical processors + //alternatively we can read NUMBER_OF_PROCESSORS environment variable #else UNIMPLEMENTED(); return 0; @@ -287,12 +323,15 @@ JVM_ActiveProcessorCount(void) { #if os_SOLARIS || os_LINUX || os_DARWIN #include + #endif void * JVM_LoadLibrary(const char *name) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN return dlopen(name, RTLD_LAZY); +#elif os_WINDOWS + return LoadLibraryA(name); #else UNIMPLEMENTED(); return 0; @@ -303,6 +342,8 @@ void JVM_UnloadLibrary(void * handle) { #if os_SOLARIS || os_LINUX || os_DARWIN dlclose(handle); +#elif os_WINDOWS + FreeLibrary(handle); #else UNIMPLEMENTED(); #endif @@ -310,8 +351,10 @@ JVM_UnloadLibrary(void * handle) { void * JVM_FindLibraryEntry(void *handle, const char *name) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN return dlsym(handle, name); +#elif os_WINDOWS + return GetProcAddress(handle, name); #else UNIMPLEMENTED(); return 0; @@ -443,7 +486,9 @@ JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name) { /* Same as JDK7u4 (and before): do nothing as not yet implemented on either Solaris / Linux */ #endif } - +#if os_WINDOWS //Microsot uses an empty Yield() Macro (obsolete, not needed) in windows.h which breaks our code so we need to undef it. +#undef Yield +#endif void JVM_Yield(JNIEnv *env, jclass threadClass) { vm.Yield(env); @@ -591,7 +636,7 @@ JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index) { jvalue JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode) { UNIMPLEMENTED_WITH_ENV(); - return (jvalue) 0; + return (jvalue) (jint)0; } void @@ -725,7 +770,9 @@ JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, /* * Reflection support functions */ - +#if os_WINDOWS //Microsot defines GetClassName as GetClassNameA in windows.h which breaks our code so we need to undef it. +#undef GetClassName +#endif jstring JVM_GetClassName(JNIEnv *env, jclass cls) { return vm.GetClassName(env, cls); @@ -1084,36 +1131,37 @@ JVM_RaiseSignal(jint sig) { if (kill(getpid(), sig) < 0) { log_println("error raising signal %d in current process: %s", sig, strerror(errno)); } +#elif os_WINDOWS + if(raise(sig)) + log_println("error raising signal %d in current process: %s", sig, strerror(errno)); + #else UNIMPLEMENTED(); #endif return JNI_TRUE; } -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX || os_WINDOWS typedef struct { const char *name; int number; } Signal; Signal signals[] = { + #if !os_WINDOWS {"HUP", SIGHUP}, - {"INT", SIGINT}, + {"QUIT", SIGQUIT}, {"ILL", SIGILL}, {"TRAP", SIGTRAP}, - {"ABRT", SIGABRT}, #if os_DARWIN {"EMT", SIGEMT}, #endif - {"FPE", SIGFPE}, {"KILL", SIGKILL}, {"BUS", SIGBUS}, - {"SEGV", SIGSEGV}, {"SYS", SIGSYS}, {"PIPE", SIGPIPE}, {"ALRM", SIGALRM}, - {"TERM", SIGTERM}, {"URG", SIGURG}, {"STOP", SIGSTOP}, {"TSTP", SIGTSTP}, @@ -1132,12 +1180,23 @@ Signal signals[] = { #endif {"USR1", SIGUSR1}, {"USR2", SIGUSR2}, + + + #endif + {"ABRT", SIGABRT}, + {"FPE", SIGFPE}, + {"ILL", SIGILL}, + {"INT", SIGINT}, + {"SEGV", SIGSEGV}, + {"TERM", SIGTERM}, + + }; #endif jint JVM_FindSignal(const char *name) { -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX || os_WINDOWS unsigned int i; for (i = 0; i < ARRAY_LENGTH(signals); i++) { if(!strcmp(name, signals[i].name)) { @@ -1804,7 +1863,7 @@ jint JVM_GetLastErrorString(char *buffer, size_t length) { if (errno == 0) { return 0; } -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX || os_WINDOWS const char *s = strerror(errno); size_t n = strlen(s); if (n >= length) { @@ -1826,7 +1885,7 @@ jint JVM_GetLastErrorString(char *buffer, size_t length) { */ char *JVM_NativePath(char *path) { jvmni_log_println("JVM_NativePath(%s)", path); -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX || os_WINDOWS return path; #else UNIMPLEMENTED(); @@ -1902,6 +1961,7 @@ JVM_Write(jint fd, char *buf, jint nbytes) { jint JVM_Available(jint fd, jlong *pbytes) { jlong cur, end; + #if !os_WINDOWS struct stat st; if (fstat(fd, &st) >= 0) { if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { @@ -1912,6 +1972,7 @@ jint JVM_Available(jint fd, jlong *pbytes) { } } } + #endif if ((cur = lseek64(fd, 0L, SEEK_CUR)) == -1) { return 0; } else if ((end = lseek64(fd, 0L, SEEK_END)) == -1) { @@ -1945,7 +2006,9 @@ JVM_Lseek(jint fd, jlong offset, jint whence) { */ jint JVM_SetLength(jint fd, jlong length) { - return ftruncate(fd, length); + return + + ftruncate(fd, length); } /* @@ -1954,7 +2017,12 @@ JVM_SetLength(jint fd, jlong length) { */ jint JVM_Sync(jint fd) { - return fsync(fd); + #if !os_WINDOWS + return fsync(fd); + #else + return !FlushFileBuffers((HANDLE)_get_osfhandle(fd)); //_get_osfhandle transforms fd to HANDLE that is needed by FlushFileBuffers +//Windows return nonzero on success + #endif } /* @@ -1963,7 +2031,7 @@ JVM_Sync(jint fd) { jint JVM_InitializeSocketLibrary(void) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return 0; #else UNIMPLEMENTED(); @@ -1971,16 +2039,15 @@ JVM_InitializeSocketLibrary(void) { #endif } -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS #include -#include #else struct sockaddr; #endif jint JVM_Socket(jint domain, jint type, jint protocol) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return socket(domain, type, protocol); #else UNIMPLEMENTED(); @@ -1990,7 +2057,7 @@ JVM_Socket(jint domain, jint type, jint protocol) { jint JVM_SocketClose(jint fd) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return close(fd); #else UNIMPLEMENTED(); @@ -2000,7 +2067,7 @@ JVM_SocketClose(jint fd) { jint JVM_SocketShutdown(jint fd, jint howto) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return shutdown(fd, howto); #else UNIMPLEMENTED(); @@ -2010,7 +2077,9 @@ JVM_SocketShutdown(jint fd, jint howto) { jint JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS + + return recv(fd, buf, nBytes, flags); #else UNIMPLEMENTED(); @@ -2020,7 +2089,8 @@ JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) { jint JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS + return send(fd, buf, nBytes, flags); #else UNIMPLEMENTED(); @@ -2028,6 +2098,10 @@ JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { #endif } +#if os_WINDOWS +extern int gettimeofday(struct timeval * tp); + +#endif jint JVM_Timeout(int fd, long timeout) { #if os_DARWIN || os_LINUX @@ -2085,6 +2159,36 @@ JVM_Timeout(int fd, long timeout) { } } else return res; } +#elif os_WINDOWS +Unsigned8 prevtime,newtime; + struct timeval t; + + gettimeofday(&t); + prevtime = ((Unsigned8)t.tv_sec * 1000) + t.tv_usec / 1000; + + for(;;) { + WSAPOLLFD pfd; + + pfd.fd = fd; + pfd.events = POLLIN | POLLERR; + + int res = WSAPoll(&pfd, 1, timeout); + + if (res == SOCKET_ERROR && errno == EINTR) { + + // On Windows any value < 0 means "forever" too + + if(timeout >= 0) { + gettimeofday(&t); + newtime = ((Unsigned8)t.tv_sec * 1000) + t.tv_usec / 1000; + timeout -= newtime - prevtime; + if(timeout <= 0) + return OS_OK; + prevtime = newtime; + } + } else + return res; + } #else UNIMPLEMENTED(); return 0; @@ -2093,7 +2197,7 @@ JVM_Timeout(int fd, long timeout) { jint JVM_Listen(jint fd, jint count) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return listen(fd, count); #else UNIMPLEMENTED(); @@ -2103,7 +2207,7 @@ JVM_Listen(jint fd, jint count) { jint JVM_Connect(jint fd, struct sockaddr *him, jint len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return connect(fd, him, len); #else UNIMPLEMENTED(); @@ -2113,7 +2217,7 @@ JVM_Connect(jint fd, struct sockaddr *him, jint len) { jint JVM_Bind(jint fd, struct sockaddr *him, jint len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return bind(fd, him, len); #else UNIMPLEMENTED(); @@ -2123,7 +2227,7 @@ JVM_Bind(jint fd, struct sockaddr *him, jint len) { jint JVM_Accept(jint fd, struct sockaddr *him, jint *len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS if (fd < 0) { return -1; } @@ -2173,7 +2277,8 @@ JVM_SocketAvailable(jint fd, jint *pbytes) { // note ioctl can return 0 when successful, JVM_SocketAvailable // is expected to return 0 on failure and 1 on success to the jdk. return (ret == OS_ERR) ? 0 : 1; -#elif os_LINUX +#elif os_LINUX || os_WINDOWS + // Linux doc says EINTR not returned, unlike Solaris int ret = ioctl(fd, FIONREAD, pbytes); @@ -2189,7 +2294,7 @@ JVM_SocketAvailable(jint fd, jint *pbytes) { jint JVM_GetSockName(jint fd, struct sockaddr *him, int *len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return getsockname(fd, him, (socklen_t*) len); #else UNIMPLEMENTED(); @@ -2199,7 +2304,7 @@ JVM_GetSockName(jint fd, struct sockaddr *him, int *len) { jint JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return getsockopt(fd, level, optname, optval, (socklen_t*) optlen); #else UNIMPLEMENTED(); @@ -2209,7 +2314,7 @@ JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) { jint JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return setsockopt(fd, level, optname, optval, optlen); #else UNIMPLEMENTED(); @@ -2245,7 +2350,7 @@ JVM_GetHostByName(char* name) { int JVM_GetHostName(char* name, int namelen) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return gethostname(name, namelen); #else UNIMPLEMENTED(); diff --git a/com.oracle.max.vm.native/substrate/jvmti.c b/com.oracle.max.vm.native/substrate/jvmti.c index c8b9dc0129..5e6c923371 100644 --- a/com.oracle.max.vm.native/substrate/jvmti.c +++ b/com.oracle.max.vm.native/substrate/jvmti.c @@ -18,7 +18,15 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if os_WINDOWS +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 // needed for tools like MINGW in order to use condition variables which became available from Windows Vista and on. Visual Studio might define it on its own +#include +#endif #include #include #include @@ -28,7 +36,7 @@ // (cwi): Java 7 added a new JVMTI function, so it is necessary to distinguish between Java 6 and Java 7. // This is the only #define that I found in the header files that allows this distinction. -#if os_LINUX || os_SOLARIS +#if os_LINUX || os_SOLARIS || os_WINDOWS #include #endif diff --git a/com.oracle.max.vm.native/substrate/maxine.c b/com.oracle.max.vm.native/substrate/maxine.c index a8a3dbf3bf..c6759acb1a 100644 --- a/com.oracle.max.vm.native/substrate/maxine.c +++ b/com.oracle.max.vm.native/substrate/maxine.c @@ -26,35 +26,61 @@ * hands control over to the VM's compiled code, which has been written in Java, * by calling a VM entry point as a C function. */ -#include + #include "os.h" + + #if !os_WINDOWS + #include + #include + #include + #include + #include + #include + #include +#else + #ifdef _WIN32_WINNT + #undef _WIN32_WINNT + #endif + #define _WIN32_WINNT 0x0600 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. + #include + #include + #include + #include + #include + #define sleep(a) Sleep(a * 1000) + #define strdup _strdup + char last_dl_error [100]; //emulating dlerror() function not available on Windows +#endif + + #include #include -#include -#include + #include -#include #include -#include -#include -#include + #include #include "log.h" #include "isa.h" #include "image.h" #include "threads.h" -#include "os.h" #include "vm.h" #include "virtualMemory.h" #include "maxine.h" #include + + + + #if os_MAXVE #include "maxve.h" #endif -#ifdef arm +#ifdef arm +#if !os_WINDOWS #include #endif +#endif static void max_fd_limit() { @@ -76,7 +102,10 @@ static void max_fd_limit() { log_println("setrlimit failed"); } } +#elif os_WINDOWS + _setmaxstdio(16777216); //windows support setting the max number of fds but they do not have a global max defined. That numer is the theoeretical max fo 64 bit machines #endif + } #define IMAGE_FILE_NAME "maxine.vm" @@ -96,15 +125,18 @@ static void getExecutablePath(char *result) { #elif os_MAXVE result[0] = 0; return; -#elif os_LINUX +#elif os_LINUX char *linkName = "/proc/self/exe"; #elif os_SOLARIS char *linkName = "/proc/self/path/a.out"; +#elif os_WINDOWS + + int numberOfChars = GetModuleFileNameA(NULL,result, MAX_PATH_LENGTH); #else # error getExecutablePath() not supported on other platforms yet #endif -#if os_LINUX || os_SOLARIS +#if os_LINUX || os_SOLARIS // read the symbolic link to figure out what the executable is. int numberOfChars = readlink(linkName, result, MAX_PATH_LENGTH); if (numberOfChars < 0) { @@ -116,7 +148,11 @@ static void getExecutablePath(char *result) { char *p; // chop off the name of the executable for (p = result + (numberOfChars - 1); p >= result; p--) { + #if os_WINDOWS + if (*p == '\\') { + #else if (*p == '/') { + #endif p[1] = 0; break; } @@ -146,7 +182,14 @@ static void *openLibrary(char *path) { log_println("openLibrary(\"%s\")", path); } #endif +#if !os_WINDOWS void *result = dlopen(path, RTLD_LAZY); +#else + void *result = LoadLibraryA(path); + if (result==NULL) { + sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); + } +#endif #if log_LINKER char* errorMessage = dlerror(); if (path == NULL) { @@ -162,8 +205,16 @@ static void *openLibrary(char *path) { } static void* loadSymbol(void* handle, const char* symbol) { + #if os_WINDOWS + void* result = GetProcAddress(handle, symbol); + if (!result) { + sprintf(last_dl_error, "dl function : GetProcAddress error code : %lu", GetLastError ()); + + } + #else void* result = dlsym(handle, symbol); -#if log_LINKER + #endif +#if log_LINKER //NOT IMPLEMENTED FOR WINDOWS, you can get info using the dlerror() function we defined #if os_MAXVE log_println("loadSymbol(%p, \"%s\") = %p", handle, symbol, result); #else @@ -183,7 +234,7 @@ static void* loadSymbol(void* handle, const char* symbol) { return result; } -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX #include #include @@ -194,7 +245,7 @@ static void* loadSymbol(void* handle, const char* symbol) { #if os_DARWIN #include -#elif os_LINUX +#elif os_LINUX #include #elif os_SOLARIS #define _STRUCTURED_PROC 1 /* Use new definitions in procfs.h instead of those in procfs_old.h */ @@ -215,7 +266,7 @@ void debugger_initialize() { char *port = getenv("MAX_AGENT_PORT"); if (port != NULL) { -#if os_LINUX && defined(PR_SET_PTRACER) +#if (os_LINUX ) && defined(PR_SET_PTRACER) /* See info about PR_SET_PTRACER at https://wiki.ubuntu.com/Security/Features#ptrace */ char *val = getenv("MAX_AGENT_PID"); if (val == NULL) { @@ -269,7 +320,7 @@ void debugger_initialize() { #if log_TELE log_println("Stopping VM for debugger"); #endif -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX || os_WINDOWS kill(getpid(), SIGTRAP); #elif os_SOLARIS int ctlfd = open("/proc/self/ctl", O_WRONLY); @@ -284,7 +335,7 @@ void debugger_initialize() { } } #else -#define debugger_initialize() +#define debugger_initialize() //not implemented for WINDOWS #endif /** @@ -293,6 +344,9 @@ void debugger_initialize() { typedef jint (*VMRunMethod)(Address tlBlock, int tlBlockSize, Address bootHeapRegionStart, void *openLibrary(char *), void *dlsym(void *, const char *), char *dlerror(void), void* vmInterface, JNIEnv jniEnv, void *jmmInterface, void *jvmtiInterface, int argc, char *argv[]); +#if os_WINDOWS +__declspec(dllexport) +#endif int maxine(int argc, char *argv[], char *executablePath) { VMRunMethod method; int exitCode = 0; @@ -341,6 +395,13 @@ int maxine(int argc, char *argv[], char *executablePath) { Address tlBlock = threadLocalsBlock_create(PRIMORDIAL_THREAD_ID, 0, 0); NativeThreadLocals ntl = NATIVE_THREAD_LOCALS_FROM_TLBLOCK(tlBlock); +#if os_WINDOWS +char *dlerror(){ + + + return last_dl_error; +} +#endif #if log_LOADER log_println("entering Java by calling MaxineVM.run(tlBlock=%p, bootHeapRegionStart=%p, openLibrary=%p, dlsym=%p, dlerror=%p, vmInterface=%p, jniEnv=%p, jmmInterface=%p, jvmtiInterface=%p, argc=%d, argv=%p)", @@ -405,8 +466,12 @@ void core_dump() { log_print("dumping core....\n heap @ "); log_print_symbol(image_heap()); log_print_newline(); + #if os_WINDOWS + raise(SIGABRT); + #else // Use kill instead of abort so the vm process keeps running after the core is created. kill(getpid(), SIGABRT); + #endif sleep(3); #endif } @@ -444,6 +509,23 @@ void *native_properties(void) { } #if os_MAXVE maxve_native_props(&nativeProperties); +#elif os_WINDOWS + + nativeProperties.user_name = malloc(MAX_PATH_LENGTH); + nativeProperties.user_dir = malloc(MAX_PATH_LENGTH); + nativeProperties.user_home = malloc(MAX_PATH_LENGTH); + + DWORD size = MAX_PATH_LENGTH; + GetUserNameA(nativeProperties.user_name, &size); + size = MAX_PATH_LENGTH; + char * tmp; + SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, (WCHAR **) &tmp); //Unfortunately, windows return home dir only in Unicode (Wide) format, not ANSI + nativeProperties.user_home = (char*) _wcsdup((const wchar_t * ) tmp); + CoTaskMemFree(tmp); //SHGetKnownFolderPath allocated that space and it is our responsibility to free it + GetCurrentDirectory(MAX_PATH_LENGTH, nativeProperties.user_dir); +//CAUTION nativeProperties.user_home contains the path in Unicode format so it cannot be printed with %s but rather with %ls using printf + + #else /* user properties */ { diff --git a/com.oracle.max.vm.native/substrate/maxine.h b/com.oracle.max.vm.native/substrate/maxine.h index 64df50d182..76ef87f53d 100644 --- a/com.oracle.max.vm.native/substrate/maxine.h +++ b/com.oracle.max.vm.native/substrate/maxine.h @@ -27,7 +27,7 @@ extern jlong native_nanoTime(void); extern jlong native_currentTimeMillis(void); extern void *native_executablePath(void); -extern void native_exit(int code); +extern void native_exit(jint code); extern void *native_environment(void); extern int maxine(int argc, char *argv[], char *executablePath); diff --git a/com.oracle.max.vm.native/substrate/memory.c b/com.oracle.max.vm.native/substrate/memory.c index 542f654493..1849aaa863 100644 --- a/com.oracle.max.vm.native/substrate/memory.c +++ b/com.oracle.max.vm.native/substrate/memory.c @@ -19,9 +19,13 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "os.h" - +#if !os_WINDOWS #include #include +#else +#include +#endif + #include #include diff --git a/com.oracle.max.vm.native/substrate/signal.c b/com.oracle.max.vm.native/substrate/signal.c index 9813304e5c..f07eb5cea2 100644 --- a/com.oracle.max.vm.native/substrate/signal.c +++ b/com.oracle.max.vm.native/substrate/signal.c @@ -24,6 +24,10 @@ /** * Native functions for SignalDispatcher.java. */ +#include "os.h" +#if os_WINDOWS +#include +#endif #include #include #include @@ -32,7 +36,9 @@ #include "threads.h" #include "log.h" -#if os_DARWIN +#if os_WINDOWS +static HANDLE signal_sem; +#elif os_DARWIN #include static semaphore_t signal_sem; #elif os_SOLARIS @@ -43,11 +49,11 @@ static semaphore_t signal_sem; #define sem_destroy sema_destroy #define sem_t sema_t static sem_t signal_sem; -#elif os_LINUX +#elif os_MAXVE +#else #include static sem_t signal_sem; -#elif os_MAXVE -// no signals, so nothing necessary + #endif boolean traceSignals = false; @@ -69,10 +75,15 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalNotify(JNIEnv *env, jcl if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_signal failed: %s", mach_error_string(kr)); } -#elif os_LINUX || os_SOLARIS +#elif os_LINUX || os_SOLARIS if (sem_post(&signal_sem) != 0) { log_exit(11, "sem_post failed: %s", strerror(errno)); } +#elif os_WINDOWS + if(!ReleaseSemaphore(signal_sem, 1, NULL)) + log_exit(GetLastError(), "ReleaseSemaphore failed"); + + #elif os_MAXVE #else c_UNIMPLEMENTED(); @@ -113,13 +124,18 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalWait(JNIEnv *env, jclas if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_wait failed: %s", mach_error_string(kr)); } -#elif os_LINUX || os_SOLARIS +#elif os_LINUX || os_SOLARIS int ret; - while ((ret = sem_wait(&signal_sem) == EINTR)) { + while ((ret = sem_wait(&signal_sem) == EINTR)) { //not sure if EINTR can occur on Windows (No sending signals is supported } if (ret != 0) { log_exit(11, "sem_wait failed: %s", strerror(errno)); } +#elif os_WINDOWS + if ( WaitForSingleObject(signal_sem,INFINITE) == WAIT_FAILED) + log_exit(GetLastError(), "WaitForSingleObject failed:"); + + #elif os_MAXVE #else c_UNIMPLEMENTED(); @@ -139,10 +155,13 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalInit(JNIEnv *env, jclas if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_create failed: %s", mach_error_string(kr)); } -#elif os_LINUX +#elif os_LINUX if (sem_init(&signal_sem, 0, 0) != 0) { log_exit(11, "sem_init failed: %s", strerror(errno)); } +#elif os_WINDOWS + signal_sem = CreateSemaphoreA(NULL, 1, 50000,NULL); //Windows Semaphore needs to have initial val 1 not 0 like Linux. If it was 0 no thread could enter +//Unfortunately, Windows Semaphores need a maximum value representing how many can enter it so we use a random big value (50000) #elif os_SOLARIS if (sem_init(&signal_sem, 0, USYNC_THREAD, NULL) != 0) { log_exit(11, "sema_init failed: %s", strerror(errno)); @@ -176,6 +195,8 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalFinalize(JNIEnv *env, j if (sem_destroy(&signal_sem) != 0) { log_exit(11, "sema_destroy failed: %s", strerror(errno)); } +#elif os_WINDOWS + CloseHandle(signal_sem); #endif } diff --git a/com.oracle.max.vm.native/substrate/sync.c b/com.oracle.max.vm.native/substrate/sync.c index bb6f59e38c..d0f4af3ead 100644 --- a/com.oracle.max.vm.native/substrate/sync.c +++ b/com.oracle.max.vm.native/substrate/sync.c @@ -18,6 +18,10 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if os_WINDOWS +#include +#endif #include #include @@ -26,7 +30,6 @@ #include "log.h" #include "jni.h" #include "mutex.h" -#include "os.h" #include "word.h" #include "threads.h" diff --git a/com.oracle.max.vm.native/substrate/threads.c b/com.oracle.max.vm.native/substrate/threads.c index 6d82a2491b..3717429596 100644 --- a/com.oracle.max.vm.native/substrate/threads.c +++ b/com.oracle.max.vm.native/substrate/threads.c @@ -19,11 +19,16 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include "os.h" -#include +#if (!os_WINDOWS) + #include +#else + #include +#endif #include -#include "os.h" #include "isa.h" #include "virtualMemory.h" @@ -41,8 +46,9 @@ #include "trap.h" #include "threads.h" #include "threadLocals.h" +#if !os_WINDOWS #include - +#endif #if (os_DARWIN || os_LINUX) # include # include @@ -56,6 +62,16 @@ # include "maxve.h" typedef maxve_Thread Thread; #define thread_current() (maxve_get_current()) + +#elif os_WINDOWS + + #include + #include + #include + #include + typedef HANDLE Thread; +#define thread_current() ((Thread) GetCurrentThread()) + #endif #if log_NUMA_THREADS @@ -114,6 +130,20 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { } pthread_attr_destroy(&attr); +#elif os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + + NT_TIB *tib = (NT_TIB*)NtCurrentTeb(); + *stackBase = (DWORD_PTR)tib->StackBase - systemInfo.dwPageSize ; //In windows, guard size is always one memory page so we remove it from stacksize. + + + MEMORY_BASIC_INFORMATION mbi = {0}; + if (VirtualQuery((LPCVOID)(stackBase ), &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0) //we use virtualquery to get windows reserved stack size (not committed). + { + DWORD_PTR allocationStart = (DWORD_PTR)mbi.AllocationBase; + *stackSize = (size_t) stackBase - allocationStart; + } #elif os_DARWIN pthread_t self = pthread_self(); void *stackTop = pthread_get_stackaddr_np(self); @@ -146,7 +176,7 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { */ static Thread thread_create(jint id, Size stackSize, int priority) { Thread thread; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS int error; #endif @@ -158,8 +188,10 @@ static Thread thread_create(jint id, Size stackSize, int priority) { #if log_THREADS log_println("thread_create: id = %d, stack size = %ld", id, stackSize); #endif - -#if (os_LINUX || os_DARWIN) +#if os_WINDOWS +#define PTHREAD_STACK_MIN 0 +#endif +#if (os_LINUX || os_DARWIN ) if (stackSize < PTHREAD_STACK_MIN) { stackSize = PTHREAD_STACK_MIN; } @@ -184,7 +216,7 @@ static Thread thread_create(jint id, Size stackSize, int priority) { if (thread == NULL) { return (Thread) 0; } -#elif (os_LINUX || os_DARWIN) +#elif (os_LINUX || os_DARWIN ) pthread_attr_t attributes; pthread_attr_init(&attributes); @@ -200,6 +232,15 @@ static Thread thread_create(jint id, Size stackSize, int priority) { log_println("pthread_create failed with error: %d", error); return (Thread) 0; } +#elif (os_WINDOWS) + thread = CreateThread(NULL, stackSize, thread_run, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL); //we demand explicitly stack size to be reservedd + //Also guard is set automatically + if(!thread){ + log_println("thread_create failed with error: %d", GetLastError()); + return (Thread) 0; + } + //the only way to make thread detached is to invalidate its handle using CloseHandle(). However, this would result in returning an invalid Thread at the end of the function + #elif os_SOLARIS if (stackSize < thr_min_stack()) { stackSize = thr_min_stack(); @@ -226,7 +267,13 @@ void *thread_self() { * * @param arg the pre-allocated, but uninitialized, thread locals block. */ -void *thread_run(void *arg) { + #if os_WINDOWS +DWORD WINAPI thread_run(void *arg) //we prefer this signature in order to avoid compiler waring on Windows. + + #else +void * thread_run(void *arg) +#endif + { Address tlBlock = (Address) arg; TLA etla = ETLA_FROM_TLBLOCK(tlBlock); @@ -307,7 +354,11 @@ void *thread_run(void *arg) { setCurrentThreadSignalMaskOnThreadExit(result == 1); /* Successful thread exit */ - return NULL; + #if os_WINDOWS + return 0; + #else + return NULL; + #endif } /** @@ -478,10 +529,12 @@ Java_com_sun_max_vm_thread_VmThread_nativeYield(JNIEnv *env, jclass c) { thr_yield(); #elif os_DARWIN sched_yield(); -#elif os_LINUX +#elif os_LINUX pthread_yield(); #elif os_MAXVE maxve_yield(); +#elif os_WINDOWS + SwitchToThread(); #else c_UNIMPLEMENTED(); #endif @@ -504,7 +557,7 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre log_exit(11, "Error sending signal SIGUSR1 to native thread %p", nativeThread); } } -#elif os_LINUX || os_DARWIN +#elif os_LINUX || os_DARWIN // Signals the thread int result = pthread_kill((pthread_t) nativeThread, SIGUSR1); if (result != 0) { @@ -517,7 +570,12 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre } } #elif os_MAXVE + maxve_interrupt((void*) nativeThread); +#elif os_WINDOWS + c_UNIMPLEMENTED(); + + #else c_UNIMPLEMENTED(); #endif @@ -526,6 +584,20 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre jboolean thread_sleep(jlong numberOfMilliSeconds) { #if os_MAXVE return maxve_sleep(numberOfMilliSeconds * 1000000); +#elif os_WINDOWS +HANDLE timer; +LARGE_INTEGER li; +if(!(timer = CreateWaitableTimer(NULL, TRUE, NULL))) + return FALSE; + +li.QuadPart = -(numberOfMilliSeconds * 1000000); +if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)){ + CloseHandle(timer); + return FALSE; + } + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); + return TRUE; #else struct timespec time, remainder; diff --git a/com.oracle.max.vm.native/substrate/time.c b/com.oracle.max.vm.native/substrate/time.c index 60e90b0d39..06eb634748 100644 --- a/com.oracle.max.vm.native/substrate/time.c +++ b/com.oracle.max.vm.native/substrate/time.c @@ -21,15 +21,47 @@ #include "os.h" #include "jni.h" #include "maxine.h" - #include -#include +#if !os_WINDOWS +#include //MINGW may contain this file but it is not officially part of WINAPI so other SDKs (eg. Visual Studio do not include it) +#endif #if os_DARWIN #include #include #elif os_LINUX #include +#elif os_WINDOWS +#include +#include +int gettimeofday(struct timeval * tp) +{ + // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's + // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) + // until 00:00:00 January 1, 1970 + static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); + + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; + + GetSystemTime( &system_time ); + SystemTimeToFileTime( &system_time, &file_time ); + time = ((uint64_t)file_time.dwLowDateTime ) ; + time += ((uint64_t)file_time.dwHighDateTime) << 32; + + tp->tv_sec = (long) ((time - EPOCH) / 10000000L); + tp->tv_usec = (long) (system_time.wMilliseconds * 1000); + return 0; +} + +int clock_gettime(int x, struct timespec *spec) +{ __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); + wintime -=(int64_t)116444736000000000; //1jan1601 to 1jan1970 + spec->tv_sec =wintime / (int64_t)10000000; //seconds + spec->tv_nsec =wintime % (int64_t)10000000 *100; //nano-seconds + return 0; +} #endif @@ -69,7 +101,7 @@ jlong native_nanoTime(void) { struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)tv.tv_sec * (uint64_t)(1000 * 1000 * 1000) + (uint64_t)(tv.tv_usec * 1000); -#elif os_LINUX +#elif os_LINUX #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC (1) @@ -119,15 +151,24 @@ jlong native_nanoTime(void) { c_ASSERT(status != -1); jlong usecs = ((jlong) time.tv_sec) * (1000 * 1000) + (jlong) time.tv_usec; return 1000 * usecs; +#elif os_WINDOWS + struct timespec time; + clock_gettime(1, &time); + return ((jlong)time.tv_sec) * (1000 * 1000 * 1000) + (jlong) time.tv_nsec; +//NOT 100% TESTED #else return 1; #endif } jlong native_currentTimeMillis(void) { -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX || os_WINDOWS struct timeval tv; + #if os_WINDOWS + gettimeofday(&tv); + #else gettimeofday(&tv, NULL); + #endif // we need to cast to jlong to avoid overflows in ARMv7 return ((jlong) tv.tv_sec * 1000) + ((jlong) tv.tv_usec / 1000); #else diff --git a/com.oracle.max.vm.native/substrate/trap.c b/com.oracle.max.vm.native/substrate/trap.c index 3030b388ae..7501e780fe 100644 --- a/com.oracle.max.vm.native/substrate/trap.c +++ b/com.oracle.max.vm.native/substrate/trap.c @@ -19,13 +19,15 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - +#include "os.h" +#if os_WINDOWS +#include +#endif #include "c.h" #include "threads.h" #include "virtualMemory.h" #include "log.h" #include "jni.h" -#include "os.h" #include "isa.h" #include "image.h" #include "trap.h" @@ -49,7 +51,7 @@ static Address theJavaTrapStub; static boolean traceTraps = false; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS //Windows do not support POSIX signals unfortunately. You can only raise some signals from within your own process/thread but not send it to another process/thread /** * All signals. @@ -77,13 +79,13 @@ static sigset_t blockedOnThreadExitSignals; int getTrapNumber(int signal) { switch (signal) { case SIGSEGV: -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS case SIGBUS: #endif return MEMORY_FAULT; case SIGFPE: return ARITHMETIC_EXCEPTION; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS case SIGUSR1: return ASYNC_INTERRUPT; default: @@ -96,12 +98,12 @@ int getTrapNumber(int signal) { #if os_SOLARIS #include #define thread_setSignalMask thr_sigsetmask -#elif os_DARWIN || os_LINUX +#elif os_DARWIN || os_LINUX #define thread_setSignalMask pthread_sigmask #endif void setCurrentThreadSignalMaskOnThreadExit(boolean isVmOperationThread) { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS if (!isVmOperationThread) { /* disable signals sent by Thread.interrupt() as thread is transitioning to not alive state. */ thread_setSignalMask(SIG_BLOCK, &blockedOnThreadExitSignals, NULL); @@ -110,7 +112,7 @@ void setCurrentThreadSignalMaskOnThreadExit(boolean isVmOperationThread) { } void setCurrentThreadSignalMask(boolean isVmOperationThread) { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS if (isVmOperationThread) { thread_setSignalMask(SIG_SETMASK, &vmAndDefaultSignals, NULL); } else { @@ -120,9 +122,12 @@ void setCurrentThreadSignalMask(boolean isVmOperationThread) { #endif } -void* setSignalHandler(int signal, SignalHandlerFunction handler) { +void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'signal' argument to 'sig' because it overlapped with windows signal() function #if os_MAXVE - maxve_register_fault_handler(signal, handler); + maxve_register_fault_handler(sig, handler); + return NULL; +#elif os_WINDOWS + signal(sig, handler); return NULL; #else struct sigaction newSigaction; @@ -132,14 +137,14 @@ void* setSignalHandler(int signal, SignalHandlerFunction handler) { sigemptyset(&newSigaction.sa_mask); newSigaction.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK; -#if os_SOLARIS || os_LINUX || os_DARWIN - if (signal == SIGUSR1) { +#if os_SOLARIS || os_LINUX || os_DARWIN + if (sig == SIGUSR1) { newSigaction.sa_flags = SA_SIGINFO | SA_ONSTACK; } #endif newSigaction.sa_sigaction = handler; - if (sigaction(signal, &newSigaction, &oldSigaction) != 0) { + if (sigaction(sig, &newSigaction, &oldSigaction) != 0) { log_exit(1, "sigaction failed"); } @@ -147,7 +152,7 @@ void* setSignalHandler(int signal, SignalHandlerFunction handler) { log_lock(); log_print("Registered handler %p [", handler); log_print_symbol((Address) handler); - log_print("] for signal %d", signal); + log_print("] for signal %d", sig); if (oldSigaction.sa_handler != NULL) { log_print(" replacing handler "); log_print_symbol((Address) oldSigaction.sa_handler); @@ -163,7 +168,7 @@ void* setSignalHandler(int signal, SignalHandlerFunction handler) { static Address getInstructionPointer(UContext *ucontext) { #if os_SOLARIS return ucontext->uc_mcontext.gregs[REG_PC]; -#elif os_LINUX +#elif os_LINUX # if isa_AMD64 return ucontext->uc_mcontext.gregs[REG_RIP]; # elif isa_IA32 @@ -179,6 +184,10 @@ static Address getInstructionPointer(UContext *ucontext) { return ucontext->uc_mcontext->__ss.__rip; #elif os_MAXVE return ucontext->rip; +#elif os_WINDOWS +#if isa_AMD64 + return ucontext->Rip; + #endif #else c_UNIMPLEMENTED(); #endif @@ -192,7 +201,7 @@ static void setInstructionPointer(UContext *ucontext, Address stub) { ucontext->uc_mcontext.gregs[REG_PC] = (greg_t) stub; #elif os_DARWIN ucontext->uc_mcontext->__ss.__rip = stub; -#elif os_LINUX +#elif os_LINUX # if isa_AMD64 ucontext->uc_mcontext.gregs[REG_RIP] = (greg_t) stub; # elif isa_IA32 @@ -206,15 +215,19 @@ static void setInstructionPointer(UContext *ucontext, Address stub) { # endif #elif os_MAXVE ucontext->rip = (unsigned long) stub; +#elseif os_WINDOWS +# if isa_AMD64 + ucontext->uc_mcontext.rip = (greg_t) stub; + #endif #else c_UNIMPLEMENTED(); #endif } -static Address getFaultAddress(SigInfo * sigInfo, UContext *ucontext) { +static Address getFaultAddress(SigInfo * sigInfo, UContext *ucontext) { //there is no siginfo_t struct in Windows #if (os_DARWIN || os_SOLARIS || os_LINUX ) return (Address) sigInfo->si_addr; -#elif (os_MAXVE) +#elif (os_MAXVE) || os_WINDOWS return (Address) sigInfo; #endif } @@ -228,7 +241,7 @@ char *vmSignalName(int signal) { case SIGSEGV: return "SIGSEGV"; case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS case SIGUSR1: return "SIGUSR1"; case SIGBUS: return "SIGBUS"; #endif @@ -269,12 +282,15 @@ static boolean handleDivideOverflow(UContext *ucontext) { if (rip[0] == 0xf7) { #if os_SOLARIS Address dividend = ucontext->uc_mcontext.gregs[REG_RAX]; -#elif os_LINUX +#elif os_LINUX Address dividend = ucontext->uc_mcontext.gregs[REG_RAX]; #elif os_DARWIN Address dividend = ucontext->uc_mcontext->__ss.__rax; #elif os_MAXVE Address dividend = ucontext->rax; +#elif os_WINDOWS + Address dividend = ucontext->Rax; + #else c_UNIMPLEMENTED(); #endif @@ -294,12 +310,15 @@ static boolean handleDivideOverflow(UContext *ucontext) { /* Set the remainder to 0. */ #if os_SOLARIS ucontext->uc_mcontext.gregs[REG_RDX] = 0; -#elif os_LINUX +#elif os_LINUX ucontext->uc_mcontext.gregs[REG_RDX] = 0; #elif os_DARWIN ucontext->uc_mcontext->__ss.__rdx = 0; #elif os_MAXVE ucontext->rdx = 0; +#elif os_WINDOWS + ucontext->Rdx = 0; + #else c_UNIMPLEMENTED(); #endif @@ -446,6 +465,9 @@ static void vmSignalHandler(int signal, SigInfo *signalInfo, UContext *ucontext) #elif isa_AMD64 && (os_SOLARIS || os_LINUX) tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->uc_mcontext.gregs[REG_R14]); ucontext->uc_mcontext.gregs[REG_R14] = (Address) dtla; +#elif isa_AMD64 && os_WINDOWS + tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->R14); + ucontext->R14 = (Address) dtla; #elif isa_AMD64 && os_DARWIN tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->uc_mcontext->__ss.__r14); ucontext->uc_mcontext->__ss.__r14 = (Address) dtla; @@ -471,11 +493,17 @@ static void vmSignalHandler(int signal, SigInfo *signalInfo, UContext *ucontext) /** * The handler for signals handled by SignalDispatcher.java. */ + #if os_WINDOWS + static void userSignalHandlerDef(int signal) { + void postSignal(int signal); + postSignal(signal); +} +#else static void userSignalHandlerDef(int signal, SigInfo *signalInfo, UContext *ucontext) { void postSignal(int signal); postSignal(signal); } - +#endif /* Defined global declared in trap.h */ SignalHandlerFunction userSignalHandler = (SignalHandlerFunction) userSignalHandlerDef; @@ -491,7 +519,7 @@ void nativeTrapInitialize(Address javaTrapStub) { setSignalHandler(SIGILL, (SignalHandlerFunction) vmSignalHandler); setSignalHandler(SIGFPE, (SignalHandlerFunction) vmSignalHandler); -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS //no support for windows signals setSignalHandler(SIGBUS, (SignalHandlerFunction) vmSignalHandler); setSignalHandler(SIGUSR1, (SignalHandlerFunction) vmSignalHandler); diff --git a/com.oracle.max.vm.native/substrate/trap.h b/com.oracle.max.vm.native/substrate/trap.h index 620a4b9afe..990f1a582a 100644 --- a/com.oracle.max.vm.native/substrate/trap.h +++ b/com.oracle.max.vm.native/substrate/trap.h @@ -29,14 +29,22 @@ # include # include # include -# include +#if (!os_WINDOWS) + # include # include -#endif +#endif +#endif #include "os.h" -#if os_MAXVE +#if os_MAXVE #define SignalHandlerFunction fault_handler_t +#elif os_WINDOWS +typedef void SigInfo; + +typedef void (*SignalHandlerFunction)(int signal); //Windows want a signal handler with one argument (Remember, Windows do not support POSIX signals. They can only be used as exceptions raised from within the same process. You cannot send them to other threads/ procs) + +typedef CONTEXT UContext; #else typedef ucontext_t UContext; typedef siginfo_t SigInfo; diff --git a/com.oracle.max.vm.native/substrate/vm.h b/com.oracle.max.vm.native/substrate/vm.h index 880df618d4..8a4da41eed 100644 --- a/com.oracle.max.vm.native/substrate/vm.h +++ b/com.oracle.max.vm.native/substrate/vm.h @@ -36,6 +36,10 @@ * A set of VM functions implemented in Java that can (only) be called from C code. * These are defined in VMFunctionsSource.java. */ + #include "os.h" + #if os_WINDOWS + #undef GetClassName + #endif //Microsoft defines GetClassName as GetClassNameA in some header files which breaks our code typedef struct vmInterface_ { // START GENERATED CODE void (JNICALL *Unimplemented) (JNIEnv *env); From 2b9f08d807fbc0b889020632c2af4df0c58b5f7e Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Wed, 8 Jul 2020 21:10:24 +0300 Subject: [PATCH 04/17] Revert "Added Windows support for com.oracle.max.vm.native" This reverts commit 1f966b0ba87113b321e329f33cc4beaa9ea20372. --- com.oracle.max.vm.native/hosted/platform.c | 18 +- com.oracle.max.vm.native/javatest/javatest.mk | 2 +- com.oracle.max.vm.native/javatest/tests.c | 36 +--- com.oracle.max.vm.native/launch/maxvm.c | 40 +--- com.oracle.max.vm.native/makefile | 2 +- com.oracle.max.vm.native/platform/aarch64.c | 2 +- com.oracle.max.vm.native/platform/aarch64.h | 2 +- com.oracle.max.vm.native/platform/amd64.c | 6 +- com.oracle.max.vm.native/platform/amd64.h | 16 -- com.oracle.max.vm.native/platform/arm.c | 6 +- com.oracle.max.vm.native/platform/platform.mk | 44 +--- .../platform/usercygwinamd64.h | 45 ---- com.oracle.max.vm.native/share/c.h | 4 +- com.oracle.max.vm.native/share/condition.c | 33 +-- com.oracle.max.vm.native/share/condition.h | 4 - com.oracle.max.vm.native/share/log.c | 35 ++- com.oracle.max.vm.native/share/mutex.c | 21 +- com.oracle.max.vm.native/share/mutex.h | 3 +- com.oracle.max.vm.native/share/threadLocals.c | 26 +-- com.oracle.max.vm.native/share/threads.h | 7 +- .../share/virtualMemory.c | 154 ++------------ com.oracle.max.vm.native/substrate/barrier.c | 6 +- com.oracle.max.vm.native/substrate/image.c | 11 +- com.oracle.max.vm.native/substrate/jni.c | 23 +- com.oracle.max.vm.native/substrate/jvm.c | 199 +++++------------- com.oracle.max.vm.native/substrate/jvmti.c | 10 +- com.oracle.max.vm.native/substrate/maxine.c | 116 ++-------- com.oracle.max.vm.native/substrate/maxine.h | 2 +- com.oracle.max.vm.native/substrate/memory.c | 6 +- com.oracle.max.vm.native/substrate/signal.c | 37 +--- com.oracle.max.vm.native/substrate/sync.c | 5 +- com.oracle.max.vm.native/substrate/threads.c | 94 +-------- com.oracle.max.vm.native/substrate/time.c | 49 +---- com.oracle.max.vm.native/substrate/trap.c | 74 ++----- com.oracle.max.vm.native/substrate/trap.h | 14 +- com.oracle.max.vm.native/substrate/vm.h | 4 - 36 files changed, 201 insertions(+), 955 deletions(-) delete mode 100644 com.oracle.max.vm.native/platform/usercygwinamd64.h diff --git a/com.oracle.max.vm.native/hosted/platform.c b/com.oracle.max.vm.native/hosted/platform.c index b0c02489a3..de3410bb39 100644 --- a/com.oracle.max.vm.native/hosted/platform.c +++ b/com.oracle.max.vm.native/hosted/platform.c @@ -18,21 +18,12 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "os.h" -#if !os_WINDOWS #include -#else - #include - #include -#endif #include "word.h" #include "isa.h" #include "jni.h" #include #include -#include - - JNIEXPORT void JNICALL JVM_OnLoad(JavaVM *vm, char *options, void *arg) @@ -63,14 +54,7 @@ Java_com_sun_max_platform_Platform_nativeGetOS(JNIEnv *env, jclass c) JNIEXPORT jint JNICALL Java_com_sun_max_platform_Platform_nativeGetPageSize(JNIEnv *env, jclass c) { - #if os_WINDOWS - SYSTEM_INFO systemInfo = {0}; - GetSystemInfo(&systemInfo); - return systemInfo.dwPageSize ; - - #else - return (jint) sysconf(_SC_PAGESIZE); - #endif + return (jint) sysconf(_SC_PAGESIZE); } diff --git a/com.oracle.max.vm.native/javatest/javatest.mk b/com.oracle.max.vm.native/javatest/javatest.mk index 7a92b47a1a..6a76e4ed70 100644 --- a/com.oracle.max.vm.native/javatest/javatest.mk +++ b/com.oracle.max.vm.native/javatest/javatest.mk @@ -27,7 +27,7 @@ LIB = javatest include $(PROJECT)/platform/platform.mk -SOURCES = jvmni.c tests.c threads.c jnitests.c jvm.c jni.c threadLocals.c image.c log.c virtualMemory.c mutex.c c.c trap.c time.c jmm.c jvmti.c relocation.c signal.c dataio.c +SOURCES = jvmni.c tests.c threads.c jnitests.c SOURCE_DIRS = javatest jni platform hosted share substrate diff --git a/com.oracle.max.vm.native/javatest/tests.c b/com.oracle.max.vm.native/javatest/tests.c index f700cd6dac..94c9cb4f4b 100644 --- a/com.oracle.max.vm.native/javatest/tests.c +++ b/com.oracle.max.vm.native/javatest/tests.c @@ -24,11 +24,8 @@ * JNI code for any of the JavaTester tests that use native methods. */ #include "os.h" -#if !os_WINDOWS + #include -#else - #include -#endif #include "jni.h" JNIEXPORT void JNICALL @@ -99,42 +96,23 @@ void upcall(jclass cls) { (*env)->DeleteGlobalRef(env, cls); (*vm)->DetachCurrentThread(vm); } -#if os_WINDOWS -DWORD WINAPI thread_function(void *arguments) {//we prefer this signature in order to avoid compiler waring on Windows. -#else + void *thread_function(void *arguments) { -#endif upcall((jclass) arguments); - #if os_WINDOWS - return 0; - #else - return NULL; - #endif + return NULL; } JNIEXPORT void JNICALL Java_test_output_AttachThread_callHelloWorldOnAttachedThread(JNIEnv *env, jclass clazz) { - #if !os_WINDOWS - pthread_t thread_id; - pthread_attr_t attributes; - - #endif + pthread_t thread_id; + pthread_attr_t attributes; + /* Convert argument to be a global handle as it is going to the new thread */ clazz = (*env)->NewGlobalRef(env, clazz); - #if os_WINDOWS - LPVOID - #else - void * - #endif - arguments = clazz; - #if !os_WINDOWS + void *arguments = clazz; pthread_attr_init(&attributes); pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE); pthread_create(&thread_id, &attributes, thread_function, arguments); pthread_attr_destroy(&attributes); - #else - CreateThread(NULL, 0, thread_function, arguments, 0, NULL); - - #endif } diff --git a/com.oracle.max.vm.native/launch/maxvm.c b/com.oracle.max.vm.native/launch/maxvm.c index 214a12a67e..1c45914fff 100644 --- a/com.oracle.max.vm.native/launch/maxvm.c +++ b/com.oracle.max.vm.native/launch/maxvm.c @@ -18,19 +18,13 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "os.h" -#if os_WINDOWS -#include -char last_dl_error [100]; //emulating dlerror() function not available on Windows - -#else #include -#endif #include #include #include #include +#include "os.h" #include "maxine.h" typedef int (*MaxineFunction)(int argc, char *argv[], char *executablePath); @@ -64,15 +58,6 @@ typedef int (*MaxineFunction)(int argc, char *argv[], char *executablePath); #include const CFNullRef initializeCoreFoundationOnMainThread; -#elif os_WINDOWS -#define LIBRARY_NAME "jvm.dll" -#define MAIN_EXTRA_ARGS -#define PROG_PATH argv[0] -char *dlerror(){ - - - return last_dl_error; -} #else #define LIBRARY_NAME "libjvm.so" #define MAIN_EXTRA_ARGS @@ -123,42 +108,23 @@ int main(int argc, char *argv[] MAIN_EXTRA_ARGS) { strncpy(libraryPath, programPath, prefixLength); strcpy(libraryPath + prefixLength, LIBRARY_NAME); #endif - #if os_WINDOWS - void *result = LoadLibraryA(libraryPath); - if (result==NULL) { - sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); - fprintf(stderr, "could not load %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); - exit(1); - - } - MaxineFunction maxine = (MaxineFunction) GetProcAddress(result, "maxine"); - if (maxine == 0) { - sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); - fprintf(stderr, "could not find symbol 'maxine' in %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); - exit(1); - } - - return (*maxine)(argc, argv, NULL); - #else void *handle = dlopen(libraryPath, RTLD_LAZY | RTLD_GLOBAL); if (handle == 0) { - fprintf(stderr, "could not load %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); + fprintf(stderr, "could not load %s: %s\n", LIBRARY_NAME, dlerror()); exit(1); } MaxineFunction maxine = (MaxineFunction) dlsym(handle, "maxine"); if (maxine == 0) { - fprintf(stderr, "could not find symbol 'maxine' in %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); + fprintf(stderr, "could not find symbol 'maxine' in %s: %s\n", LIBRARY_NAME, dlerror()); exit(1); } - #endif #if os_DARWIN return (*maxine)(argc, argv, programPath); #else free(libraryPath); - return (*maxine)(argc, argv, NULL); #endif } diff --git a/com.oracle.max.vm.native/makefile b/com.oracle.max.vm.native/makefile index e5c253f008..cab187f58c 100644 --- a/com.oracle.max.vm.native/makefile +++ b/com.oracle.max.vm.native/makefile @@ -28,7 +28,7 @@ include platform/platform.mk -all : hosted substrate launch javatest tele +all : hosted substrate launch tele javatest hosted : build/$(OS)/hosted/makefile $(AT) (cd build/$(OS)/hosted; $(MAKE) all) diff --git a/com.oracle.max.vm.native/platform/aarch64.c b/com.oracle.max.vm.native/platform/aarch64.c index b8ca765cf4..3b946e3ff8 100644 --- a/com.oracle.max.vm.native/platform/aarch64.c +++ b/com.oracle.max.vm.native/platform/aarch64.c @@ -23,7 +23,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_CanonicalIntegerRegisters c) { -#if os_LINUX || os_WINDOWS +#if os_LINUX #define CANONICALIZE(reg) c->r##reg = (Word) os->regs[reg] #else #define CANONICALIZE(reg, ucReg) c_UNIMPLEMENTED() diff --git a/com.oracle.max.vm.native/platform/aarch64.h b/com.oracle.max.vm.native/platform/aarch64.h index 5efd40fd8d..75303f0b13 100644 --- a/com.oracle.max.vm.native/platform/aarch64.h +++ b/com.oracle.max.vm.native/platform/aarch64.h @@ -23,7 +23,7 @@ #include "word.h" -#if (os_LINUX || os_WINDOWS) +#if os_LINUX # include # include typedef struct user_regs_struct *aarch64_OsTeleIntegerRegisters; diff --git a/com.oracle.max.vm.native/platform/amd64.c b/com.oracle.max.vm.native/platform/amd64.c index df6edd7508..5db518c005 100644 --- a/com.oracle.max.vm.native/platform/amd64.c +++ b/com.oracle.max.vm.native/platform/amd64.c @@ -27,7 +27,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can #if os_DARWIN #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->__##reg -#elif os_LINUX || os_MAXVE || os_WINDOWS +#elif os_LINUX || os_MAXVE #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->reg #elif os_SOLARIS #define CANONICALIZE(reg, ucReg) c->reg = (Word) os[REG_##ucReg] @@ -58,7 +58,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can void isa_canonicalizeTeleFloatingPointRegisters(isa_OsTeleFloatingPointRegisters os, isa_CanonicalFloatingPointRegisters c) { #if os_DARWIN #define CANONICALIZE(reg) c->xmm##reg = (*((Word *) (&os->__fpu_xmm##reg))) -#elif os_LINUX || os_WINDOWS +#elif os_LINUX #define CANONICALIZE(reg) c->xmm##reg = (Word) ((XMMRegister *) &os->xmm_space)[reg].low #elif os_SOLARIS #define CANONICALIZE(reg) c->xmm##reg = (Word) *((Word *) &os->fp_reg_set.fpchip_state.xmm[reg]) @@ -92,7 +92,7 @@ void isa_canonicalizeTeleStateRegisters(isa_OsTeleStateRegisters os, isa_Canonic #if os_DARWIN c->rip = (Word) os->__rip; c->flags = (Word) os->__rflags; -#elif os_LINUX || os_WINDOWS +#elif os_LINUX c->rip = (Word) os->rip; c->flags = (Word) os->eflags; #elif os_SOLARIS diff --git a/com.oracle.max.vm.native/platform/amd64.h b/com.oracle.max.vm.native/platform/amd64.h index 731be34164..25f1015604 100644 --- a/com.oracle.max.vm.native/platform/amd64.h +++ b/com.oracle.max.vm.native/platform/amd64.h @@ -40,16 +40,6 @@ Word low; Word high; } XMMRegister; -#elif os_WINDOWS -//# include -# include "usercygwinamd64.h" - typedef struct user_regs_struct *amd64_OsTeleIntegerRegisters; - typedef struct user_fpregs_struct *amd64_OsTeleFloatingPointRegisters; - typedef struct user_regs_struct *amd64_OsTeleStateRegisters; - typedef struct { - Word low; - Word high; - } XMMRegister; #elif os_SOLARIS # include typedef prgreg_t *amd64_OsTeleIntegerRegisters; @@ -57,12 +47,6 @@ typedef prgreg_t *amd64_OsTeleStateRegisters; #elif os_MAXVE # include -# include - typedef struct db_regs* amd64_OsTeleIntegerRegisters; - typedef struct db_regs* amd64_OsTeleStateRegisters; - typedef struct db_regs* amd64_OsTeleFloatingPointRegisters; -#elif os_WINDOWS -# include # include typedef struct db_regs* amd64_OsTeleIntegerRegisters; typedef struct db_regs* amd64_OsTeleStateRegisters; diff --git a/com.oracle.max.vm.native/platform/arm.c b/com.oracle.max.vm.native/platform/arm.c index 8ca37e79bc..6b73ec0f9d 100644 --- a/com.oracle.max.vm.native/platform/arm.c +++ b/com.oracle.max.vm.native/platform/arm.c @@ -25,7 +25,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can #if os_DARWIN #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->__##reg -#elif os_LINUX || os_MAXVE || os_WINDOWS +#elif os_LINUX || os_MAXVE #ifdef __arm__ #define CANONICALIZE(reg, intpos) c->reg = (Word) os->uregs[intpos] #else @@ -79,7 +79,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can void isa_canonicalizeTeleFloatingPointRegisters(isa_OsTeleFloatingPointRegisters os, isa_CanonicalFloatingPointRegisters c) { #if os_DARWIN #define CANONICALIZE(reg) c->xmm##reg = (*((Word *) (&os->__fpu_xmm##reg))) -#elif os_LINUX || os_WINDOWS +#elif os_LINUX #define CANONICALIZE(reg) c->xmm##reg = (Word) ((XMMRegister *) &os->xmm_space)[reg].low #elif os_SOLARIS #define CANONICALIZE(reg) c->xmm##reg = (Word) *((Word *) &os->fp_reg_set.fpchip_state.xmm[reg]) @@ -116,7 +116,7 @@ void isa_canonicalizeTeleStateRegisters(isa_OsTeleStateRegisters os, isa_Canonic #if os_DARWIN c->rip = (Word) os->__rip; c->flags = (Word) os->__rflags; -#elif os_LINUX || os_WINDOWS +#elif os_LINUX #ifdef __arm__ log_println("ARM: isa_canonicalizeTeleStateRegisters is not implemented!"); #else diff --git a/com.oracle.max.vm.native/platform/platform.mk b/com.oracle.max.vm.native/platform/platform.mk index fe15588ab0..69221735ef 100644 --- a/com.oracle.max.vm.native/platform/platform.mk +++ b/com.oracle.max.vm.native/platform/platform.mk @@ -22,7 +22,6 @@ # # Print verbose output only when MX_VERBOSE is set to y (i.e. mx -V command is used) - ifneq ($(MX_VERBOSE), y) AT := @ MAKE := $(MAKE) -s @@ -55,8 +54,6 @@ ifneq ($(MAIN),) TARGET := LAUNCH endif -OS := windows -ISA := amd64 # HOSTOS is the platform we are compiling on HOSTOS = $(shell uname -s) # TARGETOS is the platform we are compiling for (usually the same as HOSTOS) @@ -154,9 +151,9 @@ ifeq ($(TARGETOS),SunOS) endif endif -ifeq ($(TARGETOS),WindowsNT) +ifeq ($(findstring CYGWIN,$(TARGETOS)),CYGWIN) OS := windows - ISA := amd64 + ISA := ia32 endif # There are three variants for Maxine VE, owing to the 32/64 dom0 variants @@ -313,33 +310,20 @@ ifeq ($(OS),solaris) endif ifeq ($(OS),windows) + # determine predefined macros: touch foo.c; gcc -E -dD foo.c ifneq "$(findstring def, $(origin CC))" "" # origin of CC is either undefined or default, so set it here CC = gcc endif ifneq "$(findstring def, $(origin CFLAGS))" "" # origin of CFLAGS is either undefined or default, so set it here - CFLAGS = -g -Wall -Wno-long-long -Wextra -Wno-main -Wno-unused-parameter -fPIC -D_GNU_SOURCE -D$(ISA) -DWINDOWS -D__int64=int64_t -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) $(OTHER_CFLAGS) + CFLAGS = -g -ansi -Wall -pedantic -Wno-long-long -mno-cygwin -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) endif - C_DEPENDENCIES_FLAGS = -M -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) - # The '-rpath' linker option is used so that LD_LIBRARY_PATH does not have to be configured at runtime to - # find Maxine's version of the libjvm.so library. - # The '-z execstack' is a workaround that stops the runtime dynamic linker from - # changing the protection of the main thread's stack (via mprotect) *after* the - # yellow guard page (for detecting stack overflow) has been mprotected. Without - # this flag, the main thread's complete stack (including the guard page) is - # mprotected with PROT_READ, PROT_WRITE, PROT_EXEC when dlopen() is called to - # open libjava.so. - LINK_MAIN = $(CC) -g -Xlinker -rpath -Xlinker $(shell cd $(PROJECT)/generated/$(OS) && /bin/pwd) -o $(MAIN) - - LINK_LIB = $(CC) -g -shared -mwindows - LINK_LIB_POSTFIX += -lole32 -lws2_32 - - - + C_DEPENDENCIES_FLAGS = -MM -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) + LINK_MAIN = $(CC) -g -mno-cygwin -Wall -W1,----add-stdcall-alias -ldl + LINK_LIB = $(CC) -g -shared -mno-cygwin -Wall -W1,----add-stdcall-alias LIB_PREFIX = - LIB_SUFFIX = .dll - + LIB_SUFFIX = .dll endif ifeq ($(OS),maxve) @@ -429,15 +413,9 @@ else endif JNI_INCLUDES = -I $(dir $(JNI_H_PATH)) endif - else - ifeq ($(OS),windows) - JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/win32/ - JNI_H_PATH = $(JAVA_HOME)/include/win32/jni.h - else - JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) - JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) - endif - + else + JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) + JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) endif endif diff --git a/com.oracle.max.vm.native/platform/usercygwinamd64.h b/com.oracle.max.vm.native/platform/usercygwinamd64.h deleted file mode 100644 index e1a4c0d496..0000000000 --- a/com.oracle.max.vm.native/platform/usercygwinamd64.h +++ /dev/null @@ -1,45 +0,0 @@ -struct user_fpregs_struct -{ - unsigned short int cwd; - unsigned short int swd; - unsigned short int ftw; - unsigned short int fop; - __extension__ unsigned long long int rip; - __extension__ unsigned long long int rdp; - unsigned int mxcsr; - unsigned int mxcr_mask; - unsigned int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ - unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ - unsigned int padding[24]; -}; - -struct user_regs_struct -{ - __extension__ unsigned long long int r15; - __extension__ unsigned long long int r14; - __extension__ unsigned long long int r13; - __extension__ unsigned long long int r12; - __extension__ unsigned long long int rbp; - __extension__ unsigned long long int rbx; - __extension__ unsigned long long int r11; - __extension__ unsigned long long int r10; - __extension__ unsigned long long int r9; - __extension__ unsigned long long int r8; - __extension__ unsigned long long int rax; - __extension__ unsigned long long int rcx; - __extension__ unsigned long long int rdx; - __extension__ unsigned long long int rsi; - __extension__ unsigned long long int rdi; - __extension__ unsigned long long int orig_rax; - __extension__ unsigned long long int rip; - __extension__ unsigned long long int cs; - __extension__ unsigned long long int eflags; - __extension__ unsigned long long int rsp; - __extension__ unsigned long long int ss; - __extension__ unsigned long long int fs_base; - __extension__ unsigned long long int gs_base; - __extension__ unsigned long long int ds; - __extension__ unsigned long long int es; - __extension__ unsigned long long int fs; - __extension__ unsigned long long int gs; -}; diff --git a/com.oracle.max.vm.native/share/c.h b/com.oracle.max.vm.native/share/c.h index ed33c77f61..c4add88ca4 100644 --- a/com.oracle.max.vm.native/share/c.h +++ b/com.oracle.max.vm.native/share/c.h @@ -53,12 +53,10 @@ typedef long long Signed8; typedef float Float4; typedef double Float8; -#define true 1 -#define false 0 #if !defined(false) && !defined(true) typedef enum {false, true} boolean; #else - typedef unsigned char boolean; + typedef int boolean; #endif #define MAX_PATH_LENGTH 2048 diff --git a/com.oracle.max.vm.native/share/condition.c b/com.oracle.max.vm.native/share/condition.c index b8b8feac0c..90e052fcfe 100644 --- a/com.oracle.max.vm.native/share/condition.c +++ b/com.oracle.max.vm.native/share/condition.c @@ -18,15 +18,6 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "os.h" -#if os_WINDOWS -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT 0x0600 // needed for tools like MINGW in order to use condition variables which became available from Windows Vista and on. Visual Studio might define it on its own -#include - -#endif #include #include #include @@ -54,10 +45,6 @@ void condition_initialize(Condition condition) { } #elif os_MAXVE *condition = maxve_condition_create(); -#elif os_WINDOWS - InitializeConditionVariable(condition); - //initialize condtionVariable does not return anything! - #else # error #endif @@ -75,8 +62,6 @@ void condition_destroy(Condition condition) { if (pthread_cond_destroy(condition) != 0) { c_FATAL(); } -#elif os_WINDOWS -//condition variables cannot get destroyed https://stackoverflow.com/questions/28975958/why-does-windows-have-no-deleteconditionvariable-function-to-go-together-with #endif } @@ -95,7 +80,7 @@ void condition_destroy(Condition condition) { * @return false if an error occurred, true otherwise (i.e. the thread was notified or interrupted). * In either case, the current thread has reacquired the lock on 'mutex'. */ -boolean condition_wait(Condition condition, Mutex mutex) { //mutex is not needed in windows +boolean condition_wait(Condition condition, Mutex mutex) { #if log_MONITORS log_println("condition_wait (" THREAD_CONDVAR_MUTEX_FORMAT ")", thread_self(), condition, mutex); #endif @@ -116,8 +101,6 @@ boolean condition_wait(Condition condition, Mutex mutex) { //mutex is not needed /* (Doug) I assume 1 means EINTR */ return true; } -#elif os_WINDOWS - error = !SleepConditionVariableCS (condition, mutex, INFINITE); // non zero return value means success on Windows! #endif if (error != 0) { log_println("condition_wait (" THREAD_CONDVAR_MUTEX_FORMAT ") unexpected error code %d [%s]", thread_self(), condition, mutex, error, strerror(error)); @@ -129,7 +112,7 @@ boolean condition_wait(Condition condition, Mutex mutex) { //mutex is not needed return true; } -#if (os_DARWIN || os_LINUX ) +#if (os_DARWIN || os_LINUX) /* * This function is taken from HotSpot (os_linux.cpp). */ @@ -176,7 +159,7 @@ boolean condition_timedWait(Condition condition, Mutex mutex, Unsigned8 timeoutM log_println("condition_timedWait (" THREAD_CONDVAR_MUTEX_FORMAT ", %d)", thread_self(), condition, mutex, timeoutMilliSeconds); #endif int error; -#if (os_DARWIN || os_LINUX ) +#if (os_DARWIN || os_LINUX) struct timeval now; int status = gettimeofday(&now, NULL); c_ASSERT(status != -1); @@ -215,8 +198,6 @@ boolean condition_timedWait(Condition condition, Mutex mutex, Unsigned8 timeoutM /* (Doug) I assume 1 means EINTR */ return true; } -#elif os_WINDOWS - error = !SleepConditionVariableCS (condition, mutex, timeoutMilliSeconds); // non zero return value means success on Windows! #else # error #endif @@ -241,9 +222,6 @@ boolean condition_notify(Condition condition) { return cond_signal(condition) == 0; #elif os_MAXVE return maxve_condition_notify(*condition, 0) == 0; -#elif os_WINDOWS - WakeConditionVariable (condition); //WakeConditionVariable returns nothing - return true; #else # error #endif @@ -253,15 +231,12 @@ boolean condition_notifyAll(Condition condition) { #if log_MONITORS log_println("condition_notifyAll (" THREAD_CONDVAR_FORMAT ")", thread_self(), condition); #endif -#if (os_DARWIN || os_LINUX ) +#if (os_DARWIN || os_LINUX) return pthread_cond_broadcast(condition) == 0; #elif os_SOLARIS return cond_broadcast(condition) == 0; #elif os_MAXVE return maxve_condition_notify(*condition, 1) == 0; -#elif os_WINDOWS - WakeAllConditionVariable (condition); //WakeAllConditionVariable returns nothing - return true; #else # error #endif diff --git a/com.oracle.max.vm.native/share/condition.h b/com.oracle.max.vm.native/share/condition.h index 953fa41c4b..93c379f5ca 100644 --- a/com.oracle.max.vm.native/share/condition.h +++ b/com.oracle.max.vm.native/share/condition.h @@ -36,10 +36,6 @@ #elif os_MAXVE # include "maxve.h" typedef maxve_condition_t condition_Struct; -#elif os_WINDOWS - typedef CONDITION_VARIABLE condition_Struct; - - #endif typedef condition_Struct *Condition; diff --git a/com.oracle.max.vm.native/share/log.c b/com.oracle.max.vm.native/share/log.c index 5e5a04a828..a5bedc320a 100644 --- a/com.oracle.max.vm.native/share/log.c +++ b/com.oracle.max.vm.native/share/log.c @@ -18,28 +18,17 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - - #include #include #include #include - -#include "log.h" -#if os_WINDOWS -#include -#define pthread_self GetCurrentThread -#else #include -#endif - +#include "log.h" #include "jni.h" #include "mutex.h" #include "threads.h" - - #if !os_MAXVE static FILE *fileStream = NULL; #endif @@ -57,14 +46,14 @@ static mutex_Struct allocationProfiler_mutexStruct; void log_initialize(const char *path) { mutex_initialize(&log_mutexStruct); mutex_initialize(&allocationProfiler_mutexStruct); -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE if (path == NULL) { path = "stdout"; } if (strncmp(path, "stdout\0", 7) == 0) { fileStream = stdout; /* Set the file stream to flush whenever a newline character is encountered */ - // setlinebuf(fileStream); + setlinebuf(fileStream); } else if (strncmp(path, "stderr\0", 7) == 0) { fileStream = stderr; } else { @@ -74,7 +63,7 @@ void log_initialize(const char *path) { exit(1); } /* Set the file stream to flush whenever a newline character is encountered */ - // setlinebuf(fileStream); + setlinebuf(fileStream); } #endif } @@ -82,7 +71,7 @@ void log_initialize(const char *path) { void log_lock(void) { int result; if ((result = mutex_enter_nolog(&log_mutexStruct)) != 0) { - log_exit(-1, "Thread %d could not lock mutex %p: %s", pthread_self(), &log_mutexStruct, strerror(result)); + log_exit(-1, "Thread %p could not lock mutex %p: %s", thread_self(), &log_mutexStruct, strerror(result)); } } @@ -90,14 +79,14 @@ void numaProfiler_lock(void) { int result; result = mutex_enter_nolog(&allocationProfiler_mutexStruct); if (result != 0) { - log_exit(-1, "Thread %d could not lock mutex %p: %s", pthread_self(), &allocationProfiler_mutexStruct, strerror(result)); + log_exit(-1, "Thread %p could not lock mutex %p: %s", thread_self(), &allocationProfiler_mutexStruct, strerror(result)); } } void log_unlock(void) { int result; if ((result = mutex_exit_nolog(&log_mutexStruct)) != 0) { - log_exit(-1, "Thread %d could not unlock mutex %p: %s", pthread_self(), &log_mutexStruct, strerror(result)); + log_exit(-1, "Thread %p could not unlock mutex %p: %s", thread_self(), &log_mutexStruct, strerror(result)); } } @@ -105,7 +94,7 @@ void numaProfiler_unlock(void) { int result; result = mutex_exit_nolog(&allocationProfiler_mutexStruct); if (result != 0) { - log_exit(-1, "Thread %d could not unlock mutex %p: %s", pthread_self(), &allocationProfiler_mutexStruct, strerror(result)); + log_exit(-1, "Thread %p could not unlock mutex %p: %s", thread_self(), &allocationProfiler_mutexStruct, strerror(result)); } } @@ -122,14 +111,14 @@ void log_print_format(const char *format, ...) { } void log_flush() { -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE FILE* out = fileStream == NULL ? stdout : fileStream; fflush(out); #endif } void log_print_vformat(const char *format, va_list ap) { -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE FILE* out = fileStream == NULL ? stdout : fileStream; vfprintf(out, format, ap); #else @@ -208,8 +197,8 @@ void log_print_newline() { } void log_print_symbol(Address address) { -#if !os_MAXVE && !os_WINDOWS - Dl_info info; +#if !os_MAXVE + Dl_info info; if (dladdr((void *) address, &info) != 0) { if (info.dli_sname == NULL) { log_print("%s (%p+%d)", info.dli_fname, info.dli_fbase, address - (Address) info.dli_fbase); diff --git a/com.oracle.max.vm.native/share/mutex.c b/com.oracle.max.vm.native/share/mutex.c index 3ed0431939..4902d146fc 100644 --- a/com.oracle.max.vm.native/share/mutex.c +++ b/com.oracle.max.vm.native/share/mutex.c @@ -20,11 +20,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -#include "os.h" -#if os_WINDOWS -#include -#endif - #include "mutex.h" #include "log.h" #include "threads.h" @@ -55,8 +50,6 @@ void mutex_initialize(Mutex mutex) { } #elif os_MAXVE *mutex = maxve_monitor_create(); -#elif os_WINDOWS - InitializeCriticalSection(mutex); //windows CS's are recursive be default ,mutex is pointer to Critical section # else c_UNIMPLEMENTED(); # endif @@ -72,9 +65,6 @@ int mutex_enter_nolog(Mutex mutex) { c_ASSERT(false); } return 0; -#elif os_WINDOWS - EnterCriticalSection(mutex); //mutex is pointer to Critical section. EnterCriticalSection returns nothing - return 0; //0 means success for funcs like pthread_mutex_lock #else c_UNIMPLEMENTED(); #endif @@ -83,11 +73,8 @@ int mutex_enter_nolog(Mutex mutex) { int mutex_try_enter(Mutex mutex) { #if os_SOLARIS return mutex_trylock(mutex); -#elif os_LINUX || os_DARWIN +#elif os_LINUX || os_DARWIN return pthread_mutex_trylock(mutex); -#elif os_WINDOWS - return !TryEnterCriticalSection(mutex); //mutex is pointer to Critical section. On windows non zero return value means success that's why we use ! at the result - #else c_UNIMPLEMENTED(); #endif @@ -111,9 +98,6 @@ int mutex_exit_nolog(Mutex mutex) { c_ASSERT(false); } return 0; -#elif os_WINDOWS - LeaveCriticalSection(mutex); //mutex is pointer to Critical section - return 0; #else c_UNIMPLEMENTED(); #endif @@ -140,8 +124,5 @@ void mutex_dispose(Mutex mutex) { } #elif os_MAXVE c_UNIMPLEMENTED(); -#elif os_WINDOWS - DeleteCriticalSection(mutex); //mutex is pointer to Critical section - #endif } diff --git a/com.oracle.max.vm.native/share/mutex.h b/com.oracle.max.vm.native/share/mutex.h index 68ebec04de..962941271a 100644 --- a/com.oracle.max.vm.native/share/mutex.h +++ b/com.oracle.max.vm.native/share/mutex.h @@ -35,9 +35,8 @@ #elif os_MAXVE # include typedef maxve_monitor_t mutex_Struct; -#elif os_WINDOWS -typedef CRITICAL_SECTION mutex_Struct; #endif + typedef mutex_Struct *Mutex; extern void mutex_initialize(Mutex mutex); diff --git a/com.oracle.max.vm.native/share/threadLocals.c b/com.oracle.max.vm.native/share/threadLocals.c index 11b7a7ea24..5868340538 100644 --- a/com.oracle.max.vm.native/share/threadLocals.c +++ b/com.oracle.max.vm.native/share/threadLocals.c @@ -18,14 +18,7 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "os.h" -#if !os_WINDOWS - #include -#else - #include - #include - #define aligned_alloc(a, b) _aligned_malloc(a, b) -#endif +#include #include #include @@ -55,9 +48,6 @@ typedef maxve_Thread Thread; typedef maxve_SpecificsKey ThreadLocalsKey; typedef void (*ThreadLocalsBlockDestructor)(void *); -#elif os_WINDOWS - typedef DWORD ThreadLocalsKey; - #endif int theTLASize = -1; @@ -96,7 +86,7 @@ static void deallocateThreadLocalBlock(Address tlBlock, Size tlBlockSize) { * lazily commit memory reserved for the initial thread's stack. */ static void commitStackMemoryForInitialThread(Address base, int pageSize) { -#if os_LINUX || os_WINDOWS +#if os_LINUX /* Writing to the bottom page of the reserved stack (appears) not to be * sufficient on Linux. Using alloca() to allocate a chunk approximately * the size of the remaining stack seems to fix it. */ @@ -357,7 +347,7 @@ void threadLocalsBlock_destroy(Address tlBlock) { void tla_initialize(int tlaSize) { theTLASize = tlaSize; #if !TELE -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX int error = pthread_key_create(&theThreadLocalsKey, (ThreadLocalsBlockDestructor)(void *) threadLocalsBlock_destroy); #if log_THREADS log_println("tla_initialize: pthread_key_create returned code = %d", error); @@ -365,8 +355,6 @@ void tla_initialize(int tlaSize) { if (error != 0) { log_exit(-1, "tla_initialize: pthread_key_create returned non zero code = %d", error); } -#elif os_WINDOWS - theThreadLocalsKey = TlsAlloc(); #elif os_SOLARIS thr_keycreate(&theThreadLocalsKey, (ThreadLocalsBlockDestructor) threadLocalsBlock_destroy); #elif os_MAXVE @@ -380,7 +368,7 @@ void tla_initialize(int tlaSize) { Address threadLocalsBlock_current() { Address tlBlock; -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX tlBlock = (Address) pthread_getspecific(theThreadLocalsKey); #elif os_SOLARIS Address value; @@ -391,8 +379,6 @@ Address threadLocalsBlock_current() { tlBlock = value; #elif os_MAXVE tlBlock = (Address) maxve_thread_getSpecific(theThreadLocalsKey); -#elif os_WINDOWS - tlBlock = (Address) TlsGetValue(theThreadLocalsKey); #else c_UNIMPLEMENTED(); #endif @@ -400,14 +386,12 @@ Address threadLocalsBlock_current() { } void threadLocalsBlock_setCurrent(Address tlBlock) { -#if (os_DARWIN || os_LINUX ) +#if (os_DARWIN || os_LINUX) pthread_setspecific(theThreadLocalsKey, (void *) tlBlock); #elif os_SOLARIS thr_setspecific(theThreadLocalsKey, (void *) tlBlock); #elif os_MAXVE maxve_thread_setSpecific(theThreadLocalsKey, (void *) tlBlock); -#elif os_WINDOWS - TlsSetValue(theThreadLocalsKey, (LPVOID) tlBlock); #endif } diff --git a/com.oracle.max.vm.native/share/threads.h b/com.oracle.max.vm.native/share/threads.h index 63b48db454..f360882742 100644 --- a/com.oracle.max.vm.native/share/threads.h +++ b/com.oracle.max.vm.native/share/threads.h @@ -80,13 +80,8 @@ typedef void (*VmThreadDetachMethod)(Address tla); * @return true if the sleep was interrupted */ extern jboolean thread_sleep(jlong numberOfMilliSeconds); -#if os_WINDOWS -DWORD WINAPI thread_run(LPVOID param); -#else - -void * thread_run(void *arg); -#endif +void *thread_run(void *arg); int thread_attachCurrent(void **penv, JavaVMAttachArgs* args, boolean daemon); int thread_detachCurrent(); diff --git a/com.oracle.max.vm.native/share/virtualMemory.c b/com.oracle.max.vm.native/share/virtualMemory.c index 5ef4152e04..1846d69f03 100644 --- a/com.oracle.max.vm.native/share/virtualMemory.c +++ b/com.oracle.max.vm.native/share/virtualMemory.c @@ -18,28 +18,18 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - - #include "virtualMemory.h" #include "log.h" - #if defined(MAXVE) - #include +#include /* No mmap function on MaxVE (yet)*/ #else - #include - #include - #include - #if !os_WINDOWS - #include - #else - #ifdef _WIN32_WINNT - #undef _WIN32_WINNT - #endif - #define _WIN32_WINNT 0x0601 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. - #include - #endif +#include +#include +#include +#include + #include "jni.h" #include "unistd.h" @@ -49,7 +39,7 @@ #endif /* There is a problem binding these identifiers in RedHat's include files, so we fake them: */ -#if os_LINUX || os_WINDOWS +#if os_LINUX # ifndef MAP_ANONYMOUS # define MAP_ANONYMOUS 0x20 # endif @@ -68,16 +58,11 @@ # define MAP_32BIT 0 # endif #endif -#if !os_WINDOWS -#define PROT (PROT_EXEC | PROT_READ | PROT_WRITE) -#endif -#if !os_WINDOWS //we do not use mmap on Windows so this function is not needed. +#define PROT (PROT_EXEC | PROT_READ | PROT_WRITE) /* mmap returns MAP_FAILED on error, we convert to ALLOC_FAILED */ static Address check_mmap_result(void *result) { - - #if log_MMAP if(result == MAP_FAILED) { switch(errno) { @@ -114,11 +99,8 @@ static Address check_mmap_result(void *result) { } } #endif - return ((Address) (result == (void *) MAP_FAILED ? ALLOC_FAILED : result)); } -#endif - #ifdef arm static int attempt = 0; @@ -143,36 +125,8 @@ Address virtualMemory_allocatePrivateAnon(Address address, Size size, jboolean r address = allocAddress; } #endif -#if os_WINDOWS - //Windows got no Swap space, so jboolean reserveSwap is redundant - Address result; - if(protNone == JNI_TRUE){ - - result = (Address) VirtualAlloc( (void *) address, size, MEM_COMMIT | MEM_RESERVE| PAGE_WRITECOPY, PAGE_NOACCESS); - - //virtualalloc is the only win32 function that supports the PROT_NONE equivalent PAGE_NOACCESS - //PAGE_WRITECOPY is equivalent to MAP_PRIVATE - if(!result) - log_println("%d\n", GetLastError()); - } - else { - //if protnone is not used, we can use CreateFileMappingA + MapViewOfFile combination to emulate mmap() on Windows - //INVALID_HANDLE_VALUE means that we dont use an actual file but the system pagefile, similar to fd= -1 & MPI_ANON in mmap() - HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); - //FILE_MAP_COPY is equivalent to MAP_PRIVATE -if(!fmapping) - log_println("%d\n", GetLastError()); - result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, 0, 0, size, (LPVOID)address); - if(!result) - log_println("%d\n", GetLastError()); - - - } - return result; - -#else int flags = MAP_PRIVATE | MAP_ANON; -#if os_LINUX +#if os_LINUX /* For some reason, subsequent calls to mmap to allocate out of the space * reserved here only work if the reserved space is in 32-bit space. */ #endif @@ -199,7 +153,6 @@ if(!fmapping) #else return check_mmap_result(result); #endif -#endif } @@ -219,15 +172,6 @@ Address virtualMemory_mapFile(Size size, jint fd, Size offset) { address = check_mmap_result(result); allocAddress = address + size; return address; -#elif os_WINDOWS - HANDLE fmapping = CreateFileMappingA( (HANDLE)_get_osfhandle(fd) , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); - //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA - Address result = (Address) MapViewOfFile (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size); - //FILE_MAP_COPY is equivalent to mmap's MAP_PRIVATE. It maps a copy-on-write view of the file that is private to the process. - //MapViewOfFile needs lower and high order of offset (last and first 32 bits). We get high and lower orders of the offset (which might be 64bit long) by doing casts to DWORD( 32 BITS) and Binary shifts - if(!result) - log_println("%d\n", GetLastError()); - return result; #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_PRIVATE, fd, (off_t) offset)); #endif @@ -239,20 +183,7 @@ Java_com_sun_max_memory_VirtualMemory_virtualMemory_1mapFile(JNIEnv *env, jclass } Address virtualMemory_mapFileIn31BitSpace(jint size, jint fd, Size offset) { - #if os_WINDOWS //MAP_32BIT is not supported on Windows.... Also in Linux, it is no longer really needed - /*"It was added to allow thread stacks to be - allocated somewhere in the first 2 GB of memory, so as to - improve context-switch performance on some early 64-bit - processors. Modern x86-64 processors no longer have this - performance problem, so use of this flag is not required on - those systems. - - https://man7.org/linux/man-pages/man2/mmap.2.html - */ - return virtualMemory_mapFile(size, fd, offset); - #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_PRIVATE | MAP_32BIT, fd, (off_t) offset)); - #endif } JNIEXPORT jlong JNICALL @@ -261,20 +192,7 @@ Java_com_sun_max_memory_VirtualMemory_virtualMemory_1mapFileIn31BitSpace(JNIEnv } Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, Size offset) { - #if os_WINDOWS - HANDLE fmapping = CreateFileMappingA( (HANDLE)_get_osfhandle(fd) , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,0, NULL); - //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA - if(!fmapping) - log_println("%d\n", GetLastError()); - Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size,(LPVOID) address); - //the only diffrence is that we use MapViewOfFileEx instead MapViewOfFile. The first one allows us to provide an initial base address where the mapping begins (last argument) - - if(!result) - log_println("%d\n", GetLastError()); - return result; - #else return check_mmap_result(mmap((void *) address, (size_t) size, PROT, MAP_PRIVATE | MAP_FIXED, fd, (off_t) offset)); - #endif } // end of conditional exclusion of mmap stuff not available (or used) on MAXVE @@ -284,23 +202,14 @@ Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, Address virtualMemory_allocate(Size size, int type) { #if os_MAXVE return (Address) maxve_virtualMemory_allocate(size, type); -#elif os_WINDOWS - HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); - Address result = (Address) MapViewOfFile (fmapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size); - if(!result) - log_println("%d\n", GetLastError()); - return result; #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)); #endif } Address virtualMemory_allocateIn31BitSpace(Size size, int type) { -#if os_LINUX +#if os_LINUX return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1, (off_t) 0)); - -#elif os_WINDOWS - return virtualMemory_allocate(size, type); //windows do not have equivalent of MAP_32BIT, also obsolete in Linux #elif os_MAXVE return (Address) maxve_virtualMemory_allocateIn31BitSpace(size, type); #else @@ -312,17 +221,6 @@ Address virtualMemory_allocateIn31BitSpace(Size size, int type) { Address virtualMemory_deallocate(Address start, Size size, int type) { #if os_MAXVE return (Address) maxve_virtualMemory_deallocate((void *)start, size, type); -#elif os_WINDOWS - if( UnmapViewOfFile((LPVOID) start) == 0){ // VirtualFree will fail for addresses mapped with MapViewOfFile so we use UnmapViewOfFile first - int result = VirtualFree((LPVOID)start, size, type); //if UnmapViewOfFile failed, we try virtualalloc (the memory might got mapped with VirtualAlloc) - //type can be MEM_RELEASE or whatever the user provides. (It was implemented for MAXVE that way) - if (!result) - return result; - else - return start; - } - else - return start; #else int result = munmap((void *) start, (size_t) size); return result == -1 ? 0 : start; @@ -332,13 +230,6 @@ Address virtualMemory_deallocate(Address start, Size size, int type) { boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int type) { #if os_SOLARIS || os_DARWIN || os_LINUX return check_mmap_result(mmap((void *) address, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, (off_t) 0)) != ALLOC_FAILED; -#elif os_WINDOWS - HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); - //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA - Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, 0, 0, size,(LPVOID) address); - if(!result) - log_println("%d\n", GetLastError()); - return result; #elif os_MAXVE return (Address) maxve_virtualMemory_allocateAtFixedAddress((unsigned long)address, size, type) != ALLOC_FAILED; #else @@ -350,18 +241,11 @@ boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int typ void virtualMemory_protectPages(Address address, int count) { /* log_println("--- protected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ c_ASSERT(virtualMemory_pageAlign(address) == address); -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_NONE) != 0) { int error = errno; log_exit(error, "protectPages: mprotect(%p) failed: %s", address, strerror(error)); } -#elif os_WINDOWS - DWORD old; //needed for VirtualProtect - int error = GetLastError(); - if(!VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_NOACCESS, &old)) //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) - log_exit(error, "protectPages: VirtualProtect(%p) failed", address); - - #elif os_MAXVE maxve_virtualMemory_protectPages(address, count); #else @@ -372,14 +256,11 @@ void virtualMemory_protectPages(Address address, int count) { void virtualMemory_unprotectPages(Address address, int count) { /* log_println("--- unprotected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ c_ASSERT(virtualMemory_pageAlign(address) == address); -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_READ| PROT_WRITE) != 0) { int error = errno; log_exit(error, "unprotectPages: mprotect(%p) failed: %s", address, strerror(error)); } -#elif os_WINDOWS - DWORD old; //needed for VirtualProtect - VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_READWRITE, &old); //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) #elif os_MAXVE maxve_virtualMemory_unProtectPages(address, count); #else @@ -395,13 +276,7 @@ unsigned int virtualMemory_getPageSize(void) { return maxve_virtualMemory_pageSize(); #else if (pageSize == 0) { - #if os_WINDOWS - SYSTEM_INFO systemInfo = {0}; - GetSystemInfo(&systemInfo); - pageSize = systemInfo.dwPageSize ; - #else pageSize = getpagesize(); - #endif } return pageSize; #endif @@ -412,12 +287,9 @@ Size virtualMemory_getPhysicalMemorySize(void) { #if os_MAXVE // TODO return 0; -#elif os_SOLARIS || os_LINUX +#elif os_SOLARIS || os_LINUX Size numPhysicalPages = (Size) sysconf(_SC_PHYS_PAGES); physicalMemory = numPhysicalPages * virtualMemory_getPageSize(); -#elif os_WINDOWS - GetPhysicallyInstalledSystemMemory(&physicalMemory); - return physicalMemory * 1024; //we want bytes #elif os_DARWIN int query[2]; query[0] = CTL_HW; diff --git a/com.oracle.max.vm.native/substrate/barrier.c b/com.oracle.max.vm.native/substrate/barrier.c index 20fbdcd928..86bb92ad9d 100644 --- a/com.oracle.max.vm.native/substrate/barrier.c +++ b/com.oracle.max.vm.native/substrate/barrier.c @@ -1,4 +1,6 @@ /* + * Copyright (c) 2020, APT Group, Department of Computer Science, + * School of Engineering, The University of Manchester. All rights reserved. * Copyright (c) 2019, APT Group, School of Computer Science, * The University of Manchester. All rights reserved. * @@ -38,7 +40,7 @@ /* * Pre-processor override for whether to compile in the membarrier system call. - * Currently only affects Aarch64. See syscall_membarrier() in this compilation + * Currently only affects Aarch64 and RISCV64. See syscall_membarrier() in this compilation * unit. */ #ifndef USE_SYS_MEMBARRIER @@ -62,7 +64,7 @@ static int membarrier_init(void) __attribute__ ((unused)); void syscall_membarrier() { -#if isa_AARCH64 +#if isa_AARCH64 || isa_RISCV64 # if USE_SYS_MEMBARRIER static volatile int barrier_kind = 0; if (!barrier_kind) { diff --git a/com.oracle.max.vm.native/substrate/image.c b/com.oracle.max.vm.native/substrate/image.c index 198ea69f91..9825dd7ab9 100644 --- a/com.oracle.max.vm.native/substrate/image.c +++ b/com.oracle.max.vm.native/substrate/image.c @@ -20,13 +20,10 @@ */ #include "os.h" - #include #include #include -#if !os_WINDOWS #include -#endif #include #include @@ -280,7 +277,7 @@ static void checkTrailer(int fd) { if (trailerStructPtr->identification != theHeader->identification || trailerStructPtr->bootImageFormatVersion != theHeader->bootImageFormatVersion || trailerStructPtr->randomID != theHeader->randomID) { log_println("inconsistent trailer"); #if !MEMORY_IMAGE - offset = lseek(fd, (long int)-sizeof(trailerStruct), SEEK_END); + offset = lseek(fd, -sizeof(trailerStruct), SEEK_END); if (offset != fileSize - (off_t) sizeof(trailerStruct)) { log_exit(1, "could not set trailer position at end of file"); } @@ -307,7 +304,7 @@ static void mapHeapAndCode(int fd) { #endif #if MEMORY_IMAGE theHeap = (Address) &maxvm_image_start + heapOffsetInImage; -#elif os_SOLARIS || os_DARWIN || os_LINUX || os_WINDOWS +#elif os_SOLARIS || os_DARWIN || os_LINUX Address reservedVirtualSpace = (Address) 0; size_t virtualSpaceSize = 1024L * theHeader->reservedVirtualSpaceSize; c_ASSERT(virtualMemory_pageAlign((Size) virtualSpaceSize) == (Size) virtualSpaceSize); @@ -335,7 +332,7 @@ static void mapHeapAndCode(int fd) { log_exit(4, "could not reserve virtual space for boot image"); } } - if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { //CAUTION on Windows, the Base Address must be a multiple of dwAllocationGranularity else mapping fails (UNTESTED since no image file is availabe) + if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { log_exit(4, "could not map boot image"); } if (reservedVirtualSpace) { @@ -422,7 +419,7 @@ void image_load(char *imageFileName) { } #endif - readHeader(fd); + readHeader(fd); checkImage(); readStringInfo(fd); checkTrailer(fd); diff --git a/com.oracle.max.vm.native/substrate/jni.c b/com.oracle.max.vm.native/substrate/jni.c index a18a76141b..871108e597 100644 --- a/com.oracle.max.vm.native/substrate/jni.c +++ b/com.oracle.max.vm.native/substrate/jni.c @@ -26,10 +26,7 @@ * arguments in such an array. This isolates the implementation of such functions * from the platform/compiler dependent way in which varargs are implemented. */ -#include "os.h" -#if os_WINDOWS -#include -#endif +#include #include #include #include @@ -40,9 +37,7 @@ #include "threads.h" #include "vm.h" -#if !os_WINDOWS -#include -#endif + #ifndef JNI_VERSION_1_6 #error The version of jni.h being included must define the JNI_VERSION_1_6 macro #endif @@ -813,15 +808,11 @@ jint JNICALL jni_GetEnv(JavaVM *javaVM, void **penv, jint version) { return JNI_OK; } } -#if os_WINDOWS -__declspec( dllimport ) -#endif + jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) { return c_UNIMPLEMENTED(); } -#if os_WINDOWS -__declspec( dllimport ) -#endif + jint JNICALL jni_DestroyJavaVM(JavaVM *vm) { return c_UNIMPLEMENTED(); } @@ -838,9 +829,7 @@ jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { return thread_detachCurrent(); } -#if os_WINDOWS -__declspec( dllimport ) -#endif + jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { return c_UNIMPLEMENTED(); } @@ -868,7 +857,7 @@ JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs_Impl(JavaVM **vm, jsize vmBufLen, j return JNI_OK; } -JNIEXPORT jint JNICALL __imp_JNI_GetCreatedJavaVMs(JavaVM **vm, jsize vmBufLen, jsize *nVMs) { +JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm, jsize vmBufLen, jsize *nVMs) { return JNI_GetCreatedJavaVMs_Impl(vm, vmBufLen, nVMs); } diff --git a/com.oracle.max.vm.native/substrate/jvm.c b/com.oracle.max.vm.native/substrate/jvm.c index 0fd63eb587..c2eab15fbc 100644 --- a/com.oracle.max.vm.native/substrate/jvm.c +++ b/com.oracle.max.vm.native/substrate/jvm.c @@ -26,70 +26,39 @@ * In cases where we bypass JDK's native libraries (@see com.sun.max.vm.jdk) * we can simply omit unneeded JVM interface functions that would otherwise occur here. */ -#include "os.h" -#if os_WINDOWS -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT 0x0600 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. -#include -#include -#define lseek64 _lseeki64 -#define open _open -#define close _close //open and close work on mingw but are deprecated in MSVC so we better use _ before the name. (Internally, they call win32 funcs like CreateFile() and are added by Microsoft for POSIX compatibility -#define ftruncate _chsize -#define ioctl(a, b, c) ioctlsocket(a, b, (u_long *) c) -#include -#endif - - - - -#include "vm.h" -#include "log.h" -#include "trap.h" -#include "mutex.h" -#include "threads.h" -#include "maxine.h" -#include "memory.h" - -#if !os_WINDOWS - +#include #include #include #include - - +#include +#include #include #include #include #include -#endif -#include - -#include -#include - #if os_DARWIN #include -#elif !os_WINDOWS +#else #include #endif -#if !os_WINDOWS -#include -#endif +#include "vm.h" +#include "log.h" +#include "trap.h" +#include "mutex.h" +#include "threads.h" +#include "maxine.h" +#include "memory.h" #if os_SOLARIS #include #endif -#if os_DARWIN +#if os_DARWIN #define lseek64 lseek #include -#endif -#include +#endif // Platform-independent error return values from OS functions @@ -284,7 +253,7 @@ JVM_ActiveProcessorCount(void) { } // Otherwise return number of online cpus return online_cpus; -#elif os_LINUX +#elif os_LINUX cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors int cpus_size = sizeof(cpu_set_t); int processor_count = sysconf(_SC_NPROCESSORS_CONF); @@ -310,11 +279,6 @@ JVM_ActiveProcessorCount(void) { int online_cpus = sysconf(_SC_NPROCESSORS_ONLN); c_ASSERT(online_cpus > 0); return online_cpus; -#elif os_WINDOWS - SYSTEM_INFO systemInfo = {0}; - GetSystemInfo(&systemInfo); - return systemInfo.dwNumberOfProcessors; //not sure if we need logical or physical processors - //alternatively we can read NUMBER_OF_PROCESSORS environment variable #else UNIMPLEMENTED(); return 0; @@ -323,15 +287,12 @@ JVM_ActiveProcessorCount(void) { #if os_SOLARIS || os_LINUX || os_DARWIN #include - #endif void * JVM_LoadLibrary(const char *name) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN return dlopen(name, RTLD_LAZY); -#elif os_WINDOWS - return LoadLibraryA(name); #else UNIMPLEMENTED(); return 0; @@ -342,8 +303,6 @@ void JVM_UnloadLibrary(void * handle) { #if os_SOLARIS || os_LINUX || os_DARWIN dlclose(handle); -#elif os_WINDOWS - FreeLibrary(handle); #else UNIMPLEMENTED(); #endif @@ -351,10 +310,8 @@ JVM_UnloadLibrary(void * handle) { void * JVM_FindLibraryEntry(void *handle, const char *name) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN return dlsym(handle, name); -#elif os_WINDOWS - return GetProcAddress(handle, name); #else UNIMPLEMENTED(); return 0; @@ -486,9 +443,7 @@ JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name) { /* Same as JDK7u4 (and before): do nothing as not yet implemented on either Solaris / Linux */ #endif } -#if os_WINDOWS //Microsot uses an empty Yield() Macro (obsolete, not needed) in windows.h which breaks our code so we need to undef it. -#undef Yield -#endif + void JVM_Yield(JNIEnv *env, jclass threadClass) { vm.Yield(env); @@ -636,7 +591,7 @@ JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index) { jvalue JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode) { UNIMPLEMENTED_WITH_ENV(); - return (jvalue) (jint)0; + return (jvalue) 0; } void @@ -770,9 +725,7 @@ JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, /* * Reflection support functions */ -#if os_WINDOWS //Microsot defines GetClassName as GetClassNameA in windows.h which breaks our code so we need to undef it. -#undef GetClassName -#endif + jstring JVM_GetClassName(JNIEnv *env, jclass cls) { return vm.GetClassName(env, cls); @@ -1131,37 +1084,36 @@ JVM_RaiseSignal(jint sig) { if (kill(getpid(), sig) < 0) { log_println("error raising signal %d in current process: %s", sig, strerror(errno)); } -#elif os_WINDOWS - if(raise(sig)) - log_println("error raising signal %d in current process: %s", sig, strerror(errno)); - #else UNIMPLEMENTED(); #endif return JNI_TRUE; } -#if os_DARWIN || os_LINUX || os_WINDOWS +#if os_DARWIN || os_LINUX typedef struct { const char *name; int number; } Signal; Signal signals[] = { - #if !os_WINDOWS {"HUP", SIGHUP}, - + {"INT", SIGINT}, {"QUIT", SIGQUIT}, {"ILL", SIGILL}, {"TRAP", SIGTRAP}, + {"ABRT", SIGABRT}, #if os_DARWIN {"EMT", SIGEMT}, #endif + {"FPE", SIGFPE}, {"KILL", SIGKILL}, {"BUS", SIGBUS}, + {"SEGV", SIGSEGV}, {"SYS", SIGSYS}, {"PIPE", SIGPIPE}, {"ALRM", SIGALRM}, + {"TERM", SIGTERM}, {"URG", SIGURG}, {"STOP", SIGSTOP}, {"TSTP", SIGTSTP}, @@ -1180,23 +1132,12 @@ Signal signals[] = { #endif {"USR1", SIGUSR1}, {"USR2", SIGUSR2}, - - - #endif - {"ABRT", SIGABRT}, - {"FPE", SIGFPE}, - {"ILL", SIGILL}, - {"INT", SIGINT}, - {"SEGV", SIGSEGV}, - {"TERM", SIGTERM}, - - }; #endif jint JVM_FindSignal(const char *name) { -#if os_DARWIN || os_LINUX || os_WINDOWS +#if os_DARWIN || os_LINUX unsigned int i; for (i = 0; i < ARRAY_LENGTH(signals); i++) { if(!strcmp(name, signals[i].name)) { @@ -1863,7 +1804,7 @@ jint JVM_GetLastErrorString(char *buffer, size_t length) { if (errno == 0) { return 0; } -#if os_DARWIN || os_SOLARIS || os_LINUX || os_WINDOWS +#if os_DARWIN || os_SOLARIS || os_LINUX const char *s = strerror(errno); size_t n = strlen(s); if (n >= length) { @@ -1885,7 +1826,7 @@ jint JVM_GetLastErrorString(char *buffer, size_t length) { */ char *JVM_NativePath(char *path) { jvmni_log_println("JVM_NativePath(%s)", path); -#if os_DARWIN || os_SOLARIS || os_LINUX || os_WINDOWS +#if os_DARWIN || os_SOLARIS || os_LINUX return path; #else UNIMPLEMENTED(); @@ -1961,7 +1902,6 @@ JVM_Write(jint fd, char *buf, jint nbytes) { jint JVM_Available(jint fd, jlong *pbytes) { jlong cur, end; - #if !os_WINDOWS struct stat st; if (fstat(fd, &st) >= 0) { if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { @@ -1972,7 +1912,6 @@ jint JVM_Available(jint fd, jlong *pbytes) { } } } - #endif if ((cur = lseek64(fd, 0L, SEEK_CUR)) == -1) { return 0; } else if ((end = lseek64(fd, 0L, SEEK_END)) == -1) { @@ -2006,9 +1945,7 @@ JVM_Lseek(jint fd, jlong offset, jint whence) { */ jint JVM_SetLength(jint fd, jlong length) { - return - - ftruncate(fd, length); + return ftruncate(fd, length); } /* @@ -2017,12 +1954,7 @@ JVM_SetLength(jint fd, jlong length) { */ jint JVM_Sync(jint fd) { - #if !os_WINDOWS - return fsync(fd); - #else - return !FlushFileBuffers((HANDLE)_get_osfhandle(fd)); //_get_osfhandle transforms fd to HANDLE that is needed by FlushFileBuffers -//Windows return nonzero on success - #endif + return fsync(fd); } /* @@ -2031,7 +1963,7 @@ JVM_Sync(jint fd) { jint JVM_InitializeSocketLibrary(void) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return 0; #else UNIMPLEMENTED(); @@ -2039,15 +1971,16 @@ JVM_InitializeSocketLibrary(void) { #endif } -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN #include +#include #else struct sockaddr; #endif jint JVM_Socket(jint domain, jint type, jint protocol) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return socket(domain, type, protocol); #else UNIMPLEMENTED(); @@ -2057,7 +1990,7 @@ JVM_Socket(jint domain, jint type, jint protocol) { jint JVM_SocketClose(jint fd) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return close(fd); #else UNIMPLEMENTED(); @@ -2067,7 +2000,7 @@ JVM_SocketClose(jint fd) { jint JVM_SocketShutdown(jint fd, jint howto) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return shutdown(fd, howto); #else UNIMPLEMENTED(); @@ -2077,9 +2010,7 @@ JVM_SocketShutdown(jint fd, jint howto) { jint JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS - - +#if os_SOLARIS || os_LINUX || os_DARWIN return recv(fd, buf, nBytes, flags); #else UNIMPLEMENTED(); @@ -2089,8 +2020,7 @@ JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) { jint JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS - +#if os_SOLARIS || os_LINUX || os_DARWIN return send(fd, buf, nBytes, flags); #else UNIMPLEMENTED(); @@ -2098,10 +2028,6 @@ JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { #endif } -#if os_WINDOWS -extern int gettimeofday(struct timeval * tp); - -#endif jint JVM_Timeout(int fd, long timeout) { #if os_DARWIN || os_LINUX @@ -2159,36 +2085,6 @@ JVM_Timeout(int fd, long timeout) { } } else return res; } -#elif os_WINDOWS -Unsigned8 prevtime,newtime; - struct timeval t; - - gettimeofday(&t); - prevtime = ((Unsigned8)t.tv_sec * 1000) + t.tv_usec / 1000; - - for(;;) { - WSAPOLLFD pfd; - - pfd.fd = fd; - pfd.events = POLLIN | POLLERR; - - int res = WSAPoll(&pfd, 1, timeout); - - if (res == SOCKET_ERROR && errno == EINTR) { - - // On Windows any value < 0 means "forever" too - - if(timeout >= 0) { - gettimeofday(&t); - newtime = ((Unsigned8)t.tv_sec * 1000) + t.tv_usec / 1000; - timeout -= newtime - prevtime; - if(timeout <= 0) - return OS_OK; - prevtime = newtime; - } - } else - return res; - } #else UNIMPLEMENTED(); return 0; @@ -2197,7 +2093,7 @@ Unsigned8 prevtime,newtime; jint JVM_Listen(jint fd, jint count) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return listen(fd, count); #else UNIMPLEMENTED(); @@ -2207,7 +2103,7 @@ JVM_Listen(jint fd, jint count) { jint JVM_Connect(jint fd, struct sockaddr *him, jint len) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return connect(fd, him, len); #else UNIMPLEMENTED(); @@ -2217,7 +2113,7 @@ JVM_Connect(jint fd, struct sockaddr *him, jint len) { jint JVM_Bind(jint fd, struct sockaddr *him, jint len) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return bind(fd, him, len); #else UNIMPLEMENTED(); @@ -2227,7 +2123,7 @@ JVM_Bind(jint fd, struct sockaddr *him, jint len) { jint JVM_Accept(jint fd, struct sockaddr *him, jint *len) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN if (fd < 0) { return -1; } @@ -2277,8 +2173,7 @@ JVM_SocketAvailable(jint fd, jint *pbytes) { // note ioctl can return 0 when successful, JVM_SocketAvailable // is expected to return 0 on failure and 1 on success to the jdk. return (ret == OS_ERR) ? 0 : 1; -#elif os_LINUX || os_WINDOWS - +#elif os_LINUX // Linux doc says EINTR not returned, unlike Solaris int ret = ioctl(fd, FIONREAD, pbytes); @@ -2294,7 +2189,7 @@ JVM_SocketAvailable(jint fd, jint *pbytes) { jint JVM_GetSockName(jint fd, struct sockaddr *him, int *len) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return getsockname(fd, him, (socklen_t*) len); #else UNIMPLEMENTED(); @@ -2304,7 +2199,7 @@ JVM_GetSockName(jint fd, struct sockaddr *him, int *len) { jint JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return getsockopt(fd, level, optname, optval, (socklen_t*) optlen); #else UNIMPLEMENTED(); @@ -2314,7 +2209,7 @@ JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) { jint JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return setsockopt(fd, level, optname, optval, optlen); #else UNIMPLEMENTED(); @@ -2350,7 +2245,7 @@ JVM_GetHostByName(char* name) { int JVM_GetHostName(char* name, int namelen) { -#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS +#if os_SOLARIS || os_LINUX || os_DARWIN return gethostname(name, namelen); #else UNIMPLEMENTED(); diff --git a/com.oracle.max.vm.native/substrate/jvmti.c b/com.oracle.max.vm.native/substrate/jvmti.c index 5e6c923371..c8b9dc0129 100644 --- a/com.oracle.max.vm.native/substrate/jvmti.c +++ b/com.oracle.max.vm.native/substrate/jvmti.c @@ -18,15 +18,7 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "os.h" -#if os_WINDOWS -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT 0x0600 // needed for tools like MINGW in order to use condition variables which became available from Windows Vista and on. Visual Studio might define it on its own -#include -#endif #include #include #include @@ -36,7 +28,7 @@ // (cwi): Java 7 added a new JVMTI function, so it is necessary to distinguish between Java 6 and Java 7. // This is the only #define that I found in the header files that allows this distinction. -#if os_LINUX || os_SOLARIS || os_WINDOWS +#if os_LINUX || os_SOLARIS #include #endif diff --git a/com.oracle.max.vm.native/substrate/maxine.c b/com.oracle.max.vm.native/substrate/maxine.c index c6759acb1a..a8a3dbf3bf 100644 --- a/com.oracle.max.vm.native/substrate/maxine.c +++ b/com.oracle.max.vm.native/substrate/maxine.c @@ -26,61 +26,35 @@ * hands control over to the VM's compiled code, which has been written in Java, * by calling a VM entry point as a C function. */ - #include "os.h" - - #if !os_WINDOWS - #include - #include - #include - #include - #include - #include - #include -#else - #ifdef _WIN32_WINNT - #undef _WIN32_WINNT - #endif - #define _WIN32_WINNT 0x0600 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. - #include - #include - #include - #include - #include - #define sleep(a) Sleep(a * 1000) - #define strdup _strdup - char last_dl_error [100]; //emulating dlerror() function not available on Windows -#endif - - +#include #include #include - +#include +#include #include +#include #include - +#include +#include +#include #include #include "log.h" #include "isa.h" #include "image.h" #include "threads.h" +#include "os.h" #include "vm.h" #include "virtualMemory.h" #include "maxine.h" #include - - - - #if os_MAXVE #include "maxve.h" #endif -#ifdef arm -#if !os_WINDOWS +#ifdef arm #include #endif -#endif static void max_fd_limit() { @@ -102,10 +76,7 @@ static void max_fd_limit() { log_println("setrlimit failed"); } } -#elif os_WINDOWS - _setmaxstdio(16777216); //windows support setting the max number of fds but they do not have a global max defined. That numer is the theoeretical max fo 64 bit machines #endif - } #define IMAGE_FILE_NAME "maxine.vm" @@ -125,18 +96,15 @@ static void getExecutablePath(char *result) { #elif os_MAXVE result[0] = 0; return; -#elif os_LINUX +#elif os_LINUX char *linkName = "/proc/self/exe"; #elif os_SOLARIS char *linkName = "/proc/self/path/a.out"; -#elif os_WINDOWS - - int numberOfChars = GetModuleFileNameA(NULL,result, MAX_PATH_LENGTH); #else # error getExecutablePath() not supported on other platforms yet #endif -#if os_LINUX || os_SOLARIS +#if os_LINUX || os_SOLARIS // read the symbolic link to figure out what the executable is. int numberOfChars = readlink(linkName, result, MAX_PATH_LENGTH); if (numberOfChars < 0) { @@ -148,11 +116,7 @@ static void getExecutablePath(char *result) { char *p; // chop off the name of the executable for (p = result + (numberOfChars - 1); p >= result; p--) { - #if os_WINDOWS - if (*p == '\\') { - #else if (*p == '/') { - #endif p[1] = 0; break; } @@ -182,14 +146,7 @@ static void *openLibrary(char *path) { log_println("openLibrary(\"%s\")", path); } #endif -#if !os_WINDOWS void *result = dlopen(path, RTLD_LAZY); -#else - void *result = LoadLibraryA(path); - if (result==NULL) { - sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); - } -#endif #if log_LINKER char* errorMessage = dlerror(); if (path == NULL) { @@ -205,16 +162,8 @@ static void *openLibrary(char *path) { } static void* loadSymbol(void* handle, const char* symbol) { - #if os_WINDOWS - void* result = GetProcAddress(handle, symbol); - if (!result) { - sprintf(last_dl_error, "dl function : GetProcAddress error code : %lu", GetLastError ()); - - } - #else void* result = dlsym(handle, symbol); - #endif -#if log_LINKER //NOT IMPLEMENTED FOR WINDOWS, you can get info using the dlerror() function we defined +#if log_LINKER #if os_MAXVE log_println("loadSymbol(%p, \"%s\") = %p", handle, symbol, result); #else @@ -234,7 +183,7 @@ static void* loadSymbol(void* handle, const char* symbol) { return result; } -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX #include #include @@ -245,7 +194,7 @@ static void* loadSymbol(void* handle, const char* symbol) { #if os_DARWIN #include -#elif os_LINUX +#elif os_LINUX #include #elif os_SOLARIS #define _STRUCTURED_PROC 1 /* Use new definitions in procfs.h instead of those in procfs_old.h */ @@ -266,7 +215,7 @@ void debugger_initialize() { char *port = getenv("MAX_AGENT_PORT"); if (port != NULL) { -#if (os_LINUX ) && defined(PR_SET_PTRACER) +#if os_LINUX && defined(PR_SET_PTRACER) /* See info about PR_SET_PTRACER at https://wiki.ubuntu.com/Security/Features#ptrace */ char *val = getenv("MAX_AGENT_PID"); if (val == NULL) { @@ -320,7 +269,7 @@ void debugger_initialize() { #if log_TELE log_println("Stopping VM for debugger"); #endif -#if os_DARWIN || os_LINUX || os_WINDOWS +#if os_DARWIN || os_LINUX kill(getpid(), SIGTRAP); #elif os_SOLARIS int ctlfd = open("/proc/self/ctl", O_WRONLY); @@ -335,7 +284,7 @@ void debugger_initialize() { } } #else -#define debugger_initialize() //not implemented for WINDOWS +#define debugger_initialize() #endif /** @@ -344,9 +293,6 @@ void debugger_initialize() { typedef jint (*VMRunMethod)(Address tlBlock, int tlBlockSize, Address bootHeapRegionStart, void *openLibrary(char *), void *dlsym(void *, const char *), char *dlerror(void), void* vmInterface, JNIEnv jniEnv, void *jmmInterface, void *jvmtiInterface, int argc, char *argv[]); -#if os_WINDOWS -__declspec(dllexport) -#endif int maxine(int argc, char *argv[], char *executablePath) { VMRunMethod method; int exitCode = 0; @@ -395,13 +341,6 @@ int maxine(int argc, char *argv[], char *executablePath) { Address tlBlock = threadLocalsBlock_create(PRIMORDIAL_THREAD_ID, 0, 0); NativeThreadLocals ntl = NATIVE_THREAD_LOCALS_FROM_TLBLOCK(tlBlock); -#if os_WINDOWS -char *dlerror(){ - - - return last_dl_error; -} -#endif #if log_LOADER log_println("entering Java by calling MaxineVM.run(tlBlock=%p, bootHeapRegionStart=%p, openLibrary=%p, dlsym=%p, dlerror=%p, vmInterface=%p, jniEnv=%p, jmmInterface=%p, jvmtiInterface=%p, argc=%d, argv=%p)", @@ -466,12 +405,8 @@ void core_dump() { log_print("dumping core....\n heap @ "); log_print_symbol(image_heap()); log_print_newline(); - #if os_WINDOWS - raise(SIGABRT); - #else // Use kill instead of abort so the vm process keeps running after the core is created. kill(getpid(), SIGABRT); - #endif sleep(3); #endif } @@ -509,23 +444,6 @@ void *native_properties(void) { } #if os_MAXVE maxve_native_props(&nativeProperties); -#elif os_WINDOWS - - nativeProperties.user_name = malloc(MAX_PATH_LENGTH); - nativeProperties.user_dir = malloc(MAX_PATH_LENGTH); - nativeProperties.user_home = malloc(MAX_PATH_LENGTH); - - DWORD size = MAX_PATH_LENGTH; - GetUserNameA(nativeProperties.user_name, &size); - size = MAX_PATH_LENGTH; - char * tmp; - SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, (WCHAR **) &tmp); //Unfortunately, windows return home dir only in Unicode (Wide) format, not ANSI - nativeProperties.user_home = (char*) _wcsdup((const wchar_t * ) tmp); - CoTaskMemFree(tmp); //SHGetKnownFolderPath allocated that space and it is our responsibility to free it - GetCurrentDirectory(MAX_PATH_LENGTH, nativeProperties.user_dir); -//CAUTION nativeProperties.user_home contains the path in Unicode format so it cannot be printed with %s but rather with %ls using printf - - #else /* user properties */ { diff --git a/com.oracle.max.vm.native/substrate/maxine.h b/com.oracle.max.vm.native/substrate/maxine.h index 76ef87f53d..64df50d182 100644 --- a/com.oracle.max.vm.native/substrate/maxine.h +++ b/com.oracle.max.vm.native/substrate/maxine.h @@ -27,7 +27,7 @@ extern jlong native_nanoTime(void); extern jlong native_currentTimeMillis(void); extern void *native_executablePath(void); -extern void native_exit(jint code); +extern void native_exit(int code); extern void *native_environment(void); extern int maxine(int argc, char *argv[], char *executablePath); diff --git a/com.oracle.max.vm.native/substrate/memory.c b/com.oracle.max.vm.native/substrate/memory.c index 1849aaa863..542f654493 100644 --- a/com.oracle.max.vm.native/substrate/memory.c +++ b/com.oracle.max.vm.native/substrate/memory.c @@ -19,13 +19,9 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "os.h" -#if !os_WINDOWS + #include #include -#else -#include -#endif - #include #include diff --git a/com.oracle.max.vm.native/substrate/signal.c b/com.oracle.max.vm.native/substrate/signal.c index f07eb5cea2..9813304e5c 100644 --- a/com.oracle.max.vm.native/substrate/signal.c +++ b/com.oracle.max.vm.native/substrate/signal.c @@ -24,10 +24,6 @@ /** * Native functions for SignalDispatcher.java. */ -#include "os.h" -#if os_WINDOWS -#include -#endif #include #include #include @@ -36,9 +32,7 @@ #include "threads.h" #include "log.h" -#if os_WINDOWS -static HANDLE signal_sem; -#elif os_DARWIN +#if os_DARWIN #include static semaphore_t signal_sem; #elif os_SOLARIS @@ -49,11 +43,11 @@ static semaphore_t signal_sem; #define sem_destroy sema_destroy #define sem_t sema_t static sem_t signal_sem; -#elif os_MAXVE -#else +#elif os_LINUX #include static sem_t signal_sem; - +#elif os_MAXVE +// no signals, so nothing necessary #endif boolean traceSignals = false; @@ -75,15 +69,10 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalNotify(JNIEnv *env, jcl if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_signal failed: %s", mach_error_string(kr)); } -#elif os_LINUX || os_SOLARIS +#elif os_LINUX || os_SOLARIS if (sem_post(&signal_sem) != 0) { log_exit(11, "sem_post failed: %s", strerror(errno)); } -#elif os_WINDOWS - if(!ReleaseSemaphore(signal_sem, 1, NULL)) - log_exit(GetLastError(), "ReleaseSemaphore failed"); - - #elif os_MAXVE #else c_UNIMPLEMENTED(); @@ -124,18 +113,13 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalWait(JNIEnv *env, jclas if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_wait failed: %s", mach_error_string(kr)); } -#elif os_LINUX || os_SOLARIS +#elif os_LINUX || os_SOLARIS int ret; - while ((ret = sem_wait(&signal_sem) == EINTR)) { //not sure if EINTR can occur on Windows (No sending signals is supported + while ((ret = sem_wait(&signal_sem) == EINTR)) { } if (ret != 0) { log_exit(11, "sem_wait failed: %s", strerror(errno)); } -#elif os_WINDOWS - if ( WaitForSingleObject(signal_sem,INFINITE) == WAIT_FAILED) - log_exit(GetLastError(), "WaitForSingleObject failed:"); - - #elif os_MAXVE #else c_UNIMPLEMENTED(); @@ -155,13 +139,10 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalInit(JNIEnv *env, jclas if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_create failed: %s", mach_error_string(kr)); } -#elif os_LINUX +#elif os_LINUX if (sem_init(&signal_sem, 0, 0) != 0) { log_exit(11, "sem_init failed: %s", strerror(errno)); } -#elif os_WINDOWS - signal_sem = CreateSemaphoreA(NULL, 1, 50000,NULL); //Windows Semaphore needs to have initial val 1 not 0 like Linux. If it was 0 no thread could enter -//Unfortunately, Windows Semaphores need a maximum value representing how many can enter it so we use a random big value (50000) #elif os_SOLARIS if (sem_init(&signal_sem, 0, USYNC_THREAD, NULL) != 0) { log_exit(11, "sema_init failed: %s", strerror(errno)); @@ -195,8 +176,6 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalFinalize(JNIEnv *env, j if (sem_destroy(&signal_sem) != 0) { log_exit(11, "sema_destroy failed: %s", strerror(errno)); } -#elif os_WINDOWS - CloseHandle(signal_sem); #endif } diff --git a/com.oracle.max.vm.native/substrate/sync.c b/com.oracle.max.vm.native/substrate/sync.c index d0f4af3ead..bb6f59e38c 100644 --- a/com.oracle.max.vm.native/substrate/sync.c +++ b/com.oracle.max.vm.native/substrate/sync.c @@ -18,10 +18,6 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "os.h" -#if os_WINDOWS -#include -#endif #include #include @@ -30,6 +26,7 @@ #include "log.h" #include "jni.h" #include "mutex.h" +#include "os.h" #include "word.h" #include "threads.h" diff --git a/com.oracle.max.vm.native/substrate/threads.c b/com.oracle.max.vm.native/substrate/threads.c index 3717429596..6d82a2491b 100644 --- a/com.oracle.max.vm.native/substrate/threads.c +++ b/com.oracle.max.vm.native/substrate/threads.c @@ -19,16 +19,11 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "os.h" -#if (!os_WINDOWS) - #include -#else - #include -#endif +#include #include +#include "os.h" #include "isa.h" #include "virtualMemory.h" @@ -46,9 +41,8 @@ #include "trap.h" #include "threads.h" #include "threadLocals.h" -#if !os_WINDOWS #include -#endif + #if (os_DARWIN || os_LINUX) # include # include @@ -62,16 +56,6 @@ # include "maxve.h" typedef maxve_Thread Thread; #define thread_current() (maxve_get_current()) - -#elif os_WINDOWS - - #include - #include - #include - #include - typedef HANDLE Thread; -#define thread_current() ((Thread) GetCurrentThread()) - #endif #if log_NUMA_THREADS @@ -130,20 +114,6 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { } pthread_attr_destroy(&attr); -#elif os_WINDOWS - SYSTEM_INFO systemInfo = {0}; - GetSystemInfo(&systemInfo); - - NT_TIB *tib = (NT_TIB*)NtCurrentTeb(); - *stackBase = (DWORD_PTR)tib->StackBase - systemInfo.dwPageSize ; //In windows, guard size is always one memory page so we remove it from stacksize. - - - MEMORY_BASIC_INFORMATION mbi = {0}; - if (VirtualQuery((LPCVOID)(stackBase ), &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0) //we use virtualquery to get windows reserved stack size (not committed). - { - DWORD_PTR allocationStart = (DWORD_PTR)mbi.AllocationBase; - *stackSize = (size_t) stackBase - allocationStart; - } #elif os_DARWIN pthread_t self = pthread_self(); void *stackTop = pthread_get_stackaddr_np(self); @@ -176,7 +146,7 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { */ static Thread thread_create(jint id, Size stackSize, int priority) { Thread thread; -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE int error; #endif @@ -188,10 +158,8 @@ static Thread thread_create(jint id, Size stackSize, int priority) { #if log_THREADS log_println("thread_create: id = %d, stack size = %ld", id, stackSize); #endif -#if os_WINDOWS -#define PTHREAD_STACK_MIN 0 -#endif -#if (os_LINUX || os_DARWIN ) + +#if (os_LINUX || os_DARWIN) if (stackSize < PTHREAD_STACK_MIN) { stackSize = PTHREAD_STACK_MIN; } @@ -216,7 +184,7 @@ static Thread thread_create(jint id, Size stackSize, int priority) { if (thread == NULL) { return (Thread) 0; } -#elif (os_LINUX || os_DARWIN ) +#elif (os_LINUX || os_DARWIN) pthread_attr_t attributes; pthread_attr_init(&attributes); @@ -232,15 +200,6 @@ static Thread thread_create(jint id, Size stackSize, int priority) { log_println("pthread_create failed with error: %d", error); return (Thread) 0; } -#elif (os_WINDOWS) - thread = CreateThread(NULL, stackSize, thread_run, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL); //we demand explicitly stack size to be reservedd - //Also guard is set automatically - if(!thread){ - log_println("thread_create failed with error: %d", GetLastError()); - return (Thread) 0; - } - //the only way to make thread detached is to invalidate its handle using CloseHandle(). However, this would result in returning an invalid Thread at the end of the function - #elif os_SOLARIS if (stackSize < thr_min_stack()) { stackSize = thr_min_stack(); @@ -267,13 +226,7 @@ void *thread_self() { * * @param arg the pre-allocated, but uninitialized, thread locals block. */ - #if os_WINDOWS -DWORD WINAPI thread_run(void *arg) //we prefer this signature in order to avoid compiler waring on Windows. - - #else -void * thread_run(void *arg) -#endif - { +void *thread_run(void *arg) { Address tlBlock = (Address) arg; TLA etla = ETLA_FROM_TLBLOCK(tlBlock); @@ -354,11 +307,7 @@ void * thread_run(void *arg) setCurrentThreadSignalMaskOnThreadExit(result == 1); /* Successful thread exit */ - #if os_WINDOWS - return 0; - #else - return NULL; - #endif + return NULL; } /** @@ -529,12 +478,10 @@ Java_com_sun_max_vm_thread_VmThread_nativeYield(JNIEnv *env, jclass c) { thr_yield(); #elif os_DARWIN sched_yield(); -#elif os_LINUX +#elif os_LINUX pthread_yield(); #elif os_MAXVE maxve_yield(); -#elif os_WINDOWS - SwitchToThread(); #else c_UNIMPLEMENTED(); #endif @@ -557,7 +504,7 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre log_exit(11, "Error sending signal SIGUSR1 to native thread %p", nativeThread); } } -#elif os_LINUX || os_DARWIN +#elif os_LINUX || os_DARWIN // Signals the thread int result = pthread_kill((pthread_t) nativeThread, SIGUSR1); if (result != 0) { @@ -570,12 +517,7 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre } } #elif os_MAXVE - maxve_interrupt((void*) nativeThread); -#elif os_WINDOWS - c_UNIMPLEMENTED(); - - #else c_UNIMPLEMENTED(); #endif @@ -584,20 +526,6 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre jboolean thread_sleep(jlong numberOfMilliSeconds) { #if os_MAXVE return maxve_sleep(numberOfMilliSeconds * 1000000); -#elif os_WINDOWS -HANDLE timer; -LARGE_INTEGER li; -if(!(timer = CreateWaitableTimer(NULL, TRUE, NULL))) - return FALSE; - -li.QuadPart = -(numberOfMilliSeconds * 1000000); -if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)){ - CloseHandle(timer); - return FALSE; - } - WaitForSingleObject(timer, INFINITE); - CloseHandle(timer); - return TRUE; #else struct timespec time, remainder; diff --git a/com.oracle.max.vm.native/substrate/time.c b/com.oracle.max.vm.native/substrate/time.c index 06eb634748..60e90b0d39 100644 --- a/com.oracle.max.vm.native/substrate/time.c +++ b/com.oracle.max.vm.native/substrate/time.c @@ -21,47 +21,15 @@ #include "os.h" #include "jni.h" #include "maxine.h" + #include +#include -#if !os_WINDOWS -#include //MINGW may contain this file but it is not officially part of WINAPI so other SDKs (eg. Visual Studio do not include it) -#endif #if os_DARWIN #include #include #elif os_LINUX #include -#elif os_WINDOWS -#include -#include -int gettimeofday(struct timeval * tp) -{ - // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's - // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) - // until 00:00:00 January 1, 1970 - static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); - - SYSTEMTIME system_time; - FILETIME file_time; - uint64_t time; - - GetSystemTime( &system_time ); - SystemTimeToFileTime( &system_time, &file_time ); - time = ((uint64_t)file_time.dwLowDateTime ) ; - time += ((uint64_t)file_time.dwHighDateTime) << 32; - - tp->tv_sec = (long) ((time - EPOCH) / 10000000L); - tp->tv_usec = (long) (system_time.wMilliseconds * 1000); - return 0; -} - -int clock_gettime(int x, struct timespec *spec) -{ __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); - wintime -=(int64_t)116444736000000000; //1jan1601 to 1jan1970 - spec->tv_sec =wintime / (int64_t)10000000; //seconds - spec->tv_nsec =wintime % (int64_t)10000000 *100; //nano-seconds - return 0; -} #endif @@ -101,7 +69,7 @@ jlong native_nanoTime(void) { struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)tv.tv_sec * (uint64_t)(1000 * 1000 * 1000) + (uint64_t)(tv.tv_usec * 1000); -#elif os_LINUX +#elif os_LINUX #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC (1) @@ -151,24 +119,15 @@ jlong native_nanoTime(void) { c_ASSERT(status != -1); jlong usecs = ((jlong) time.tv_sec) * (1000 * 1000) + (jlong) time.tv_usec; return 1000 * usecs; -#elif os_WINDOWS - struct timespec time; - clock_gettime(1, &time); - return ((jlong)time.tv_sec) * (1000 * 1000 * 1000) + (jlong) time.tv_nsec; -//NOT 100% TESTED #else return 1; #endif } jlong native_currentTimeMillis(void) { -#if os_SOLARIS || os_DARWIN || os_LINUX || os_WINDOWS +#if os_SOLARIS || os_DARWIN || os_LINUX struct timeval tv; - #if os_WINDOWS - gettimeofday(&tv); - #else gettimeofday(&tv, NULL); - #endif // we need to cast to jlong to avoid overflows in ARMv7 return ((jlong) tv.tv_sec * 1000) + ((jlong) tv.tv_usec / 1000); #else diff --git a/com.oracle.max.vm.native/substrate/trap.c b/com.oracle.max.vm.native/substrate/trap.c index 7501e780fe..3030b388ae 100644 --- a/com.oracle.max.vm.native/substrate/trap.c +++ b/com.oracle.max.vm.native/substrate/trap.c @@ -19,15 +19,13 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "os.h" -#if os_WINDOWS -#include -#endif + #include "c.h" #include "threads.h" #include "virtualMemory.h" #include "log.h" #include "jni.h" +#include "os.h" #include "isa.h" #include "image.h" #include "trap.h" @@ -51,7 +49,7 @@ static Address theJavaTrapStub; static boolean traceTraps = false; -#if !os_MAXVE && !os_WINDOWS //Windows do not support POSIX signals unfortunately. You can only raise some signals from within your own process/thread but not send it to another process/thread +#if !os_MAXVE /** * All signals. @@ -79,13 +77,13 @@ static sigset_t blockedOnThreadExitSignals; int getTrapNumber(int signal) { switch (signal) { case SIGSEGV: -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE case SIGBUS: #endif return MEMORY_FAULT; case SIGFPE: return ARITHMETIC_EXCEPTION; -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE case SIGUSR1: return ASYNC_INTERRUPT; default: @@ -98,12 +96,12 @@ int getTrapNumber(int signal) { #if os_SOLARIS #include #define thread_setSignalMask thr_sigsetmask -#elif os_DARWIN || os_LINUX +#elif os_DARWIN || os_LINUX #define thread_setSignalMask pthread_sigmask #endif void setCurrentThreadSignalMaskOnThreadExit(boolean isVmOperationThread) { -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE if (!isVmOperationThread) { /* disable signals sent by Thread.interrupt() as thread is transitioning to not alive state. */ thread_setSignalMask(SIG_BLOCK, &blockedOnThreadExitSignals, NULL); @@ -112,7 +110,7 @@ void setCurrentThreadSignalMaskOnThreadExit(boolean isVmOperationThread) { } void setCurrentThreadSignalMask(boolean isVmOperationThread) { -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE if (isVmOperationThread) { thread_setSignalMask(SIG_SETMASK, &vmAndDefaultSignals, NULL); } else { @@ -122,12 +120,9 @@ void setCurrentThreadSignalMask(boolean isVmOperationThread) { #endif } -void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'signal' argument to 'sig' because it overlapped with windows signal() function +void* setSignalHandler(int signal, SignalHandlerFunction handler) { #if os_MAXVE - maxve_register_fault_handler(sig, handler); - return NULL; -#elif os_WINDOWS - signal(sig, handler); + maxve_register_fault_handler(signal, handler); return NULL; #else struct sigaction newSigaction; @@ -137,14 +132,14 @@ void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'sign sigemptyset(&newSigaction.sa_mask); newSigaction.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK; -#if os_SOLARIS || os_LINUX || os_DARWIN - if (sig == SIGUSR1) { +#if os_SOLARIS || os_LINUX || os_DARWIN + if (signal == SIGUSR1) { newSigaction.sa_flags = SA_SIGINFO | SA_ONSTACK; } #endif newSigaction.sa_sigaction = handler; - if (sigaction(sig, &newSigaction, &oldSigaction) != 0) { + if (sigaction(signal, &newSigaction, &oldSigaction) != 0) { log_exit(1, "sigaction failed"); } @@ -152,7 +147,7 @@ void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'sign log_lock(); log_print("Registered handler %p [", handler); log_print_symbol((Address) handler); - log_print("] for signal %d", sig); + log_print("] for signal %d", signal); if (oldSigaction.sa_handler != NULL) { log_print(" replacing handler "); log_print_symbol((Address) oldSigaction.sa_handler); @@ -168,7 +163,7 @@ void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'sign static Address getInstructionPointer(UContext *ucontext) { #if os_SOLARIS return ucontext->uc_mcontext.gregs[REG_PC]; -#elif os_LINUX +#elif os_LINUX # if isa_AMD64 return ucontext->uc_mcontext.gregs[REG_RIP]; # elif isa_IA32 @@ -184,10 +179,6 @@ static Address getInstructionPointer(UContext *ucontext) { return ucontext->uc_mcontext->__ss.__rip; #elif os_MAXVE return ucontext->rip; -#elif os_WINDOWS -#if isa_AMD64 - return ucontext->Rip; - #endif #else c_UNIMPLEMENTED(); #endif @@ -201,7 +192,7 @@ static void setInstructionPointer(UContext *ucontext, Address stub) { ucontext->uc_mcontext.gregs[REG_PC] = (greg_t) stub; #elif os_DARWIN ucontext->uc_mcontext->__ss.__rip = stub; -#elif os_LINUX +#elif os_LINUX # if isa_AMD64 ucontext->uc_mcontext.gregs[REG_RIP] = (greg_t) stub; # elif isa_IA32 @@ -215,19 +206,15 @@ static void setInstructionPointer(UContext *ucontext, Address stub) { # endif #elif os_MAXVE ucontext->rip = (unsigned long) stub; -#elseif os_WINDOWS -# if isa_AMD64 - ucontext->uc_mcontext.rip = (greg_t) stub; - #endif #else c_UNIMPLEMENTED(); #endif } -static Address getFaultAddress(SigInfo * sigInfo, UContext *ucontext) { //there is no siginfo_t struct in Windows +static Address getFaultAddress(SigInfo * sigInfo, UContext *ucontext) { #if (os_DARWIN || os_SOLARIS || os_LINUX ) return (Address) sigInfo->si_addr; -#elif (os_MAXVE) || os_WINDOWS +#elif (os_MAXVE) return (Address) sigInfo; #endif } @@ -241,7 +228,7 @@ char *vmSignalName(int signal) { case SIGSEGV: return "SIGSEGV"; case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; -#if !os_MAXVE && !os_WINDOWS +#if !os_MAXVE case SIGUSR1: return "SIGUSR1"; case SIGBUS: return "SIGBUS"; #endif @@ -282,15 +269,12 @@ static boolean handleDivideOverflow(UContext *ucontext) { if (rip[0] == 0xf7) { #if os_SOLARIS Address dividend = ucontext->uc_mcontext.gregs[REG_RAX]; -#elif os_LINUX +#elif os_LINUX Address dividend = ucontext->uc_mcontext.gregs[REG_RAX]; #elif os_DARWIN Address dividend = ucontext->uc_mcontext->__ss.__rax; #elif os_MAXVE Address dividend = ucontext->rax; -#elif os_WINDOWS - Address dividend = ucontext->Rax; - #else c_UNIMPLEMENTED(); #endif @@ -310,15 +294,12 @@ static boolean handleDivideOverflow(UContext *ucontext) { /* Set the remainder to 0. */ #if os_SOLARIS ucontext->uc_mcontext.gregs[REG_RDX] = 0; -#elif os_LINUX +#elif os_LINUX ucontext->uc_mcontext.gregs[REG_RDX] = 0; #elif os_DARWIN ucontext->uc_mcontext->__ss.__rdx = 0; #elif os_MAXVE ucontext->rdx = 0; -#elif os_WINDOWS - ucontext->Rdx = 0; - #else c_UNIMPLEMENTED(); #endif @@ -465,9 +446,6 @@ static void vmSignalHandler(int signal, SigInfo *signalInfo, UContext *ucontext) #elif isa_AMD64 && (os_SOLARIS || os_LINUX) tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->uc_mcontext.gregs[REG_R14]); ucontext->uc_mcontext.gregs[REG_R14] = (Address) dtla; -#elif isa_AMD64 && os_WINDOWS - tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->R14); - ucontext->R14 = (Address) dtla; #elif isa_AMD64 && os_DARWIN tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->uc_mcontext->__ss.__r14); ucontext->uc_mcontext->__ss.__r14 = (Address) dtla; @@ -493,17 +471,11 @@ static void vmSignalHandler(int signal, SigInfo *signalInfo, UContext *ucontext) /** * The handler for signals handled by SignalDispatcher.java. */ - #if os_WINDOWS - static void userSignalHandlerDef(int signal) { - void postSignal(int signal); - postSignal(signal); -} -#else static void userSignalHandlerDef(int signal, SigInfo *signalInfo, UContext *ucontext) { void postSignal(int signal); postSignal(signal); } -#endif + /* Defined global declared in trap.h */ SignalHandlerFunction userSignalHandler = (SignalHandlerFunction) userSignalHandlerDef; @@ -519,7 +491,7 @@ void nativeTrapInitialize(Address javaTrapStub) { setSignalHandler(SIGILL, (SignalHandlerFunction) vmSignalHandler); setSignalHandler(SIGFPE, (SignalHandlerFunction) vmSignalHandler); -#if !os_MAXVE && !os_WINDOWS //no support for windows signals +#if !os_MAXVE setSignalHandler(SIGBUS, (SignalHandlerFunction) vmSignalHandler); setSignalHandler(SIGUSR1, (SignalHandlerFunction) vmSignalHandler); diff --git a/com.oracle.max.vm.native/substrate/trap.h b/com.oracle.max.vm.native/substrate/trap.h index 990f1a582a..620a4b9afe 100644 --- a/com.oracle.max.vm.native/substrate/trap.h +++ b/com.oracle.max.vm.native/substrate/trap.h @@ -29,22 +29,14 @@ # include # include # include -#if (!os_WINDOWS) - # include +# include # include - -#endif #endif + #include "os.h" -#if os_MAXVE +#if os_MAXVE #define SignalHandlerFunction fault_handler_t -#elif os_WINDOWS -typedef void SigInfo; - -typedef void (*SignalHandlerFunction)(int signal); //Windows want a signal handler with one argument (Remember, Windows do not support POSIX signals. They can only be used as exceptions raised from within the same process. You cannot send them to other threads/ procs) - -typedef CONTEXT UContext; #else typedef ucontext_t UContext; typedef siginfo_t SigInfo; diff --git a/com.oracle.max.vm.native/substrate/vm.h b/com.oracle.max.vm.native/substrate/vm.h index 8a4da41eed..880df618d4 100644 --- a/com.oracle.max.vm.native/substrate/vm.h +++ b/com.oracle.max.vm.native/substrate/vm.h @@ -36,10 +36,6 @@ * A set of VM functions implemented in Java that can (only) be called from C code. * These are defined in VMFunctionsSource.java. */ - #include "os.h" - #if os_WINDOWS - #undef GetClassName - #endif //Microsoft defines GetClassName as GetClassNameA in some header files which breaks our code typedef struct vmInterface_ { // START GENERATED CODE void (JNICALL *Unimplemented) (JNIEnv *env); From a109ab754fe3081d2f8010494cc7283c7d38cf24 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Wed, 8 Jul 2020 21:20:59 +0300 Subject: [PATCH 05/17] Added Windows support to com.oracle.max.vm.native Added code for the creation of the following executables and shared libraries on Windows: jvm.dll (substrate), javatest.dll, maxvm.exe (launch), hosted.dll -Only tele.dll excluded The code depends entirely on native Windows Libraries available in any Windows OS after (including) Windows Vista. No additional dependency (like .Cygwin, pthread libraries etc) is required to compile and run it. Only thing left unimplemented (besides Tele) is the ability to send signals to different threads/ procs (ie. kill () ) as Windows do not support such functionality. Windows signals can only be raised from within the same process that receives them (like Exceptions). One could probably emulate the functionality of UNIX signals using something like Windows message posting but that requires each thread to explicitly receive a message using function like GetMessage(). For now, it is left unimplemented. --- com.oracle.max.vm.native/hosted/platform.c | 18 +- com.oracle.max.vm.native/javatest/javatest.mk | 2 +- com.oracle.max.vm.native/javatest/tests.c | 36 +++- com.oracle.max.vm.native/launch/maxvm.c | 40 +++- com.oracle.max.vm.native/makefile | 2 +- com.oracle.max.vm.native/platform/aarch64.c | 2 +- com.oracle.max.vm.native/platform/aarch64.h | 2 +- com.oracle.max.vm.native/platform/amd64.c | 6 +- com.oracle.max.vm.native/platform/amd64.h | 16 ++ com.oracle.max.vm.native/platform/arm.c | 6 +- com.oracle.max.vm.native/platform/platform.mk | 44 +++- .../platform/usercygwinamd64.h | 45 ++++ com.oracle.max.vm.native/share/c.h | 4 +- com.oracle.max.vm.native/share/condition.c | 33 ++- com.oracle.max.vm.native/share/condition.h | 4 + com.oracle.max.vm.native/share/log.c | 35 +-- com.oracle.max.vm.native/share/mutex.c | 21 +- com.oracle.max.vm.native/share/mutex.h | 3 +- com.oracle.max.vm.native/share/threadLocals.c | 26 ++- com.oracle.max.vm.native/share/threads.h | 7 +- .../share/virtualMemory.c | 154 ++++++++++++-- com.oracle.max.vm.native/substrate/barrier.c | 6 +- com.oracle.max.vm.native/substrate/image.c | 11 +- com.oracle.max.vm.native/substrate/jni.c | 23 +- com.oracle.max.vm.native/substrate/jvm.c | 199 +++++++++++++----- com.oracle.max.vm.native/substrate/jvmti.c | 10 +- com.oracle.max.vm.native/substrate/maxine.c | 116 ++++++++-- com.oracle.max.vm.native/substrate/maxine.h | 2 +- com.oracle.max.vm.native/substrate/memory.c | 6 +- com.oracle.max.vm.native/substrate/signal.c | 37 +++- com.oracle.max.vm.native/substrate/sync.c | 5 +- com.oracle.max.vm.native/substrate/threads.c | 94 ++++++++- com.oracle.max.vm.native/substrate/time.c | 49 ++++- com.oracle.max.vm.native/substrate/trap.c | 74 +++++-- com.oracle.max.vm.native/substrate/trap.h | 14 +- com.oracle.max.vm.native/substrate/vm.h | 4 + 36 files changed, 955 insertions(+), 201 deletions(-) create mode 100644 com.oracle.max.vm.native/platform/usercygwinamd64.h diff --git a/com.oracle.max.vm.native/hosted/platform.c b/com.oracle.max.vm.native/hosted/platform.c index de3410bb39..b0c02489a3 100644 --- a/com.oracle.max.vm.native/hosted/platform.c +++ b/com.oracle.max.vm.native/hosted/platform.c @@ -18,12 +18,21 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if !os_WINDOWS #include +#else + #include + #include +#endif #include "word.h" #include "isa.h" #include "jni.h" #include #include +#include + + JNIEXPORT void JNICALL JVM_OnLoad(JavaVM *vm, char *options, void *arg) @@ -54,7 +63,14 @@ Java_com_sun_max_platform_Platform_nativeGetOS(JNIEnv *env, jclass c) JNIEXPORT jint JNICALL Java_com_sun_max_platform_Platform_nativeGetPageSize(JNIEnv *env, jclass c) { - return (jint) sysconf(_SC_PAGESIZE); + #if os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + return systemInfo.dwPageSize ; + + #else + return (jint) sysconf(_SC_PAGESIZE); + #endif } diff --git a/com.oracle.max.vm.native/javatest/javatest.mk b/com.oracle.max.vm.native/javatest/javatest.mk index 6a76e4ed70..7a92b47a1a 100644 --- a/com.oracle.max.vm.native/javatest/javatest.mk +++ b/com.oracle.max.vm.native/javatest/javatest.mk @@ -27,7 +27,7 @@ LIB = javatest include $(PROJECT)/platform/platform.mk -SOURCES = jvmni.c tests.c threads.c jnitests.c +SOURCES = jvmni.c tests.c threads.c jnitests.c jvm.c jni.c threadLocals.c image.c log.c virtualMemory.c mutex.c c.c trap.c time.c jmm.c jvmti.c relocation.c signal.c dataio.c SOURCE_DIRS = javatest jni platform hosted share substrate diff --git a/com.oracle.max.vm.native/javatest/tests.c b/com.oracle.max.vm.native/javatest/tests.c index 94c9cb4f4b..f700cd6dac 100644 --- a/com.oracle.max.vm.native/javatest/tests.c +++ b/com.oracle.max.vm.native/javatest/tests.c @@ -24,8 +24,11 @@ * JNI code for any of the JavaTester tests that use native methods. */ #include "os.h" - +#if !os_WINDOWS #include +#else + #include +#endif #include "jni.h" JNIEXPORT void JNICALL @@ -96,23 +99,42 @@ void upcall(jclass cls) { (*env)->DeleteGlobalRef(env, cls); (*vm)->DetachCurrentThread(vm); } - +#if os_WINDOWS +DWORD WINAPI thread_function(void *arguments) {//we prefer this signature in order to avoid compiler waring on Windows. +#else void *thread_function(void *arguments) { +#endif upcall((jclass) arguments); - return NULL; + #if os_WINDOWS + return 0; + #else + return NULL; + #endif } JNIEXPORT void JNICALL Java_test_output_AttachThread_callHelloWorldOnAttachedThread(JNIEnv *env, jclass clazz) { - pthread_t thread_id; - pthread_attr_t attributes; - + #if !os_WINDOWS + pthread_t thread_id; + pthread_attr_t attributes; + + #endif /* Convert argument to be a global handle as it is going to the new thread */ clazz = (*env)->NewGlobalRef(env, clazz); - void *arguments = clazz; + #if os_WINDOWS + LPVOID + #else + void * + #endif + arguments = clazz; + #if !os_WINDOWS pthread_attr_init(&attributes); pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE); pthread_create(&thread_id, &attributes, thread_function, arguments); pthread_attr_destroy(&attributes); + #else + CreateThread(NULL, 0, thread_function, arguments, 0, NULL); + + #endif } diff --git a/com.oracle.max.vm.native/launch/maxvm.c b/com.oracle.max.vm.native/launch/maxvm.c index 1c45914fff..214a12a67e 100644 --- a/com.oracle.max.vm.native/launch/maxvm.c +++ b/com.oracle.max.vm.native/launch/maxvm.c @@ -18,13 +18,19 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + #include "os.h" +#if os_WINDOWS +#include +char last_dl_error [100]; //emulating dlerror() function not available on Windows + +#else #include +#endif #include #include #include #include -#include "os.h" #include "maxine.h" typedef int (*MaxineFunction)(int argc, char *argv[], char *executablePath); @@ -58,6 +64,15 @@ typedef int (*MaxineFunction)(int argc, char *argv[], char *executablePath); #include const CFNullRef initializeCoreFoundationOnMainThread; +#elif os_WINDOWS +#define LIBRARY_NAME "jvm.dll" +#define MAIN_EXTRA_ARGS +#define PROG_PATH argv[0] +char *dlerror(){ + + + return last_dl_error; +} #else #define LIBRARY_NAME "libjvm.so" #define MAIN_EXTRA_ARGS @@ -108,23 +123,42 @@ int main(int argc, char *argv[] MAIN_EXTRA_ARGS) { strncpy(libraryPath, programPath, prefixLength); strcpy(libraryPath + prefixLength, LIBRARY_NAME); #endif + #if os_WINDOWS + void *result = LoadLibraryA(libraryPath); + if (result==NULL) { + sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); + fprintf(stderr, "could not load %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); + exit(1); + + } + MaxineFunction maxine = (MaxineFunction) GetProcAddress(result, "maxine"); + if (maxine == 0) { + sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); + fprintf(stderr, "could not find symbol 'maxine' in %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); + exit(1); + } + + return (*maxine)(argc, argv, NULL); + #else void *handle = dlopen(libraryPath, RTLD_LAZY | RTLD_GLOBAL); if (handle == 0) { - fprintf(stderr, "could not load %s: %s\n", LIBRARY_NAME, dlerror()); + fprintf(stderr, "could not load %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); exit(1); } MaxineFunction maxine = (MaxineFunction) dlsym(handle, "maxine"); if (maxine == 0) { - fprintf(stderr, "could not find symbol 'maxine' in %s: %s\n", LIBRARY_NAME, dlerror()); + fprintf(stderr, "could not find symbol 'maxine' in %s: %s %s\n", LIBRARY_NAME, dlerror(), libraryPath); exit(1); } + #endif #if os_DARWIN return (*maxine)(argc, argv, programPath); #else free(libraryPath); + return (*maxine)(argc, argv, NULL); #endif } diff --git a/com.oracle.max.vm.native/makefile b/com.oracle.max.vm.native/makefile index cab187f58c..e5c253f008 100644 --- a/com.oracle.max.vm.native/makefile +++ b/com.oracle.max.vm.native/makefile @@ -28,7 +28,7 @@ include platform/platform.mk -all : hosted substrate launch tele javatest +all : hosted substrate launch javatest tele hosted : build/$(OS)/hosted/makefile $(AT) (cd build/$(OS)/hosted; $(MAKE) all) diff --git a/com.oracle.max.vm.native/platform/aarch64.c b/com.oracle.max.vm.native/platform/aarch64.c index 3b946e3ff8..b8ca765cf4 100644 --- a/com.oracle.max.vm.native/platform/aarch64.c +++ b/com.oracle.max.vm.native/platform/aarch64.c @@ -23,7 +23,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_CanonicalIntegerRegisters c) { -#if os_LINUX +#if os_LINUX || os_WINDOWS #define CANONICALIZE(reg) c->r##reg = (Word) os->regs[reg] #else #define CANONICALIZE(reg, ucReg) c_UNIMPLEMENTED() diff --git a/com.oracle.max.vm.native/platform/aarch64.h b/com.oracle.max.vm.native/platform/aarch64.h index 75303f0b13..5efd40fd8d 100644 --- a/com.oracle.max.vm.native/platform/aarch64.h +++ b/com.oracle.max.vm.native/platform/aarch64.h @@ -23,7 +23,7 @@ #include "word.h" -#if os_LINUX +#if (os_LINUX || os_WINDOWS) # include # include typedef struct user_regs_struct *aarch64_OsTeleIntegerRegisters; diff --git a/com.oracle.max.vm.native/platform/amd64.c b/com.oracle.max.vm.native/platform/amd64.c index 5db518c005..df6edd7508 100644 --- a/com.oracle.max.vm.native/platform/amd64.c +++ b/com.oracle.max.vm.native/platform/amd64.c @@ -27,7 +27,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can #if os_DARWIN #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->__##reg -#elif os_LINUX || os_MAXVE +#elif os_LINUX || os_MAXVE || os_WINDOWS #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->reg #elif os_SOLARIS #define CANONICALIZE(reg, ucReg) c->reg = (Word) os[REG_##ucReg] @@ -58,7 +58,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can void isa_canonicalizeTeleFloatingPointRegisters(isa_OsTeleFloatingPointRegisters os, isa_CanonicalFloatingPointRegisters c) { #if os_DARWIN #define CANONICALIZE(reg) c->xmm##reg = (*((Word *) (&os->__fpu_xmm##reg))) -#elif os_LINUX +#elif os_LINUX || os_WINDOWS #define CANONICALIZE(reg) c->xmm##reg = (Word) ((XMMRegister *) &os->xmm_space)[reg].low #elif os_SOLARIS #define CANONICALIZE(reg) c->xmm##reg = (Word) *((Word *) &os->fp_reg_set.fpchip_state.xmm[reg]) @@ -92,7 +92,7 @@ void isa_canonicalizeTeleStateRegisters(isa_OsTeleStateRegisters os, isa_Canonic #if os_DARWIN c->rip = (Word) os->__rip; c->flags = (Word) os->__rflags; -#elif os_LINUX +#elif os_LINUX || os_WINDOWS c->rip = (Word) os->rip; c->flags = (Word) os->eflags; #elif os_SOLARIS diff --git a/com.oracle.max.vm.native/platform/amd64.h b/com.oracle.max.vm.native/platform/amd64.h index 25f1015604..731be34164 100644 --- a/com.oracle.max.vm.native/platform/amd64.h +++ b/com.oracle.max.vm.native/platform/amd64.h @@ -40,6 +40,16 @@ Word low; Word high; } XMMRegister; +#elif os_WINDOWS +//# include +# include "usercygwinamd64.h" + typedef struct user_regs_struct *amd64_OsTeleIntegerRegisters; + typedef struct user_fpregs_struct *amd64_OsTeleFloatingPointRegisters; + typedef struct user_regs_struct *amd64_OsTeleStateRegisters; + typedef struct { + Word low; + Word high; + } XMMRegister; #elif os_SOLARIS # include typedef prgreg_t *amd64_OsTeleIntegerRegisters; @@ -47,6 +57,12 @@ typedef prgreg_t *amd64_OsTeleStateRegisters; #elif os_MAXVE # include +# include + typedef struct db_regs* amd64_OsTeleIntegerRegisters; + typedef struct db_regs* amd64_OsTeleStateRegisters; + typedef struct db_regs* amd64_OsTeleFloatingPointRegisters; +#elif os_WINDOWS +# include # include typedef struct db_regs* amd64_OsTeleIntegerRegisters; typedef struct db_regs* amd64_OsTeleStateRegisters; diff --git a/com.oracle.max.vm.native/platform/arm.c b/com.oracle.max.vm.native/platform/arm.c index 6b73ec0f9d..8ca37e79bc 100644 --- a/com.oracle.max.vm.native/platform/arm.c +++ b/com.oracle.max.vm.native/platform/arm.c @@ -25,7 +25,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can #if os_DARWIN #define CANONICALIZE(reg, ucReg) c->reg = (Word) os->__##reg -#elif os_LINUX || os_MAXVE +#elif os_LINUX || os_MAXVE || os_WINDOWS #ifdef __arm__ #define CANONICALIZE(reg, intpos) c->reg = (Word) os->uregs[intpos] #else @@ -79,7 +79,7 @@ void isa_canonicalizeTeleIntegerRegisters(isa_OsTeleIntegerRegisters os, isa_Can void isa_canonicalizeTeleFloatingPointRegisters(isa_OsTeleFloatingPointRegisters os, isa_CanonicalFloatingPointRegisters c) { #if os_DARWIN #define CANONICALIZE(reg) c->xmm##reg = (*((Word *) (&os->__fpu_xmm##reg))) -#elif os_LINUX +#elif os_LINUX || os_WINDOWS #define CANONICALIZE(reg) c->xmm##reg = (Word) ((XMMRegister *) &os->xmm_space)[reg].low #elif os_SOLARIS #define CANONICALIZE(reg) c->xmm##reg = (Word) *((Word *) &os->fp_reg_set.fpchip_state.xmm[reg]) @@ -116,7 +116,7 @@ void isa_canonicalizeTeleStateRegisters(isa_OsTeleStateRegisters os, isa_Canonic #if os_DARWIN c->rip = (Word) os->__rip; c->flags = (Word) os->__rflags; -#elif os_LINUX +#elif os_LINUX || os_WINDOWS #ifdef __arm__ log_println("ARM: isa_canonicalizeTeleStateRegisters is not implemented!"); #else diff --git a/com.oracle.max.vm.native/platform/platform.mk b/com.oracle.max.vm.native/platform/platform.mk index 69221735ef..fe15588ab0 100644 --- a/com.oracle.max.vm.native/platform/platform.mk +++ b/com.oracle.max.vm.native/platform/platform.mk @@ -22,6 +22,7 @@ # # Print verbose output only when MX_VERBOSE is set to y (i.e. mx -V command is used) + ifneq ($(MX_VERBOSE), y) AT := @ MAKE := $(MAKE) -s @@ -54,6 +55,8 @@ ifneq ($(MAIN),) TARGET := LAUNCH endif +OS := windows +ISA := amd64 # HOSTOS is the platform we are compiling on HOSTOS = $(shell uname -s) # TARGETOS is the platform we are compiling for (usually the same as HOSTOS) @@ -151,9 +154,9 @@ ifeq ($(TARGETOS),SunOS) endif endif -ifeq ($(findstring CYGWIN,$(TARGETOS)),CYGWIN) +ifeq ($(TARGETOS),WindowsNT) OS := windows - ISA := ia32 + ISA := amd64 endif # There are three variants for Maxine VE, owing to the 32/64 dom0 variants @@ -310,20 +313,33 @@ ifeq ($(OS),solaris) endif ifeq ($(OS),windows) - # determine predefined macros: touch foo.c; gcc -E -dD foo.c ifneq "$(findstring def, $(origin CC))" "" # origin of CC is either undefined or default, so set it here CC = gcc endif ifneq "$(findstring def, $(origin CFLAGS))" "" # origin of CFLAGS is either undefined or default, so set it here - CFLAGS = -g -ansi -Wall -pedantic -Wno-long-long -mno-cygwin -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) + CFLAGS = -g -Wall -Wno-long-long -Wextra -Wno-main -Wno-unused-parameter -fPIC -D_GNU_SOURCE -D$(ISA) -DWINDOWS -D__int64=int64_t -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) $(OTHER_CFLAGS) endif - C_DEPENDENCIES_FLAGS = -MM -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) - LINK_MAIN = $(CC) -g -mno-cygwin -Wall -W1,----add-stdcall-alias -ldl - LINK_LIB = $(CC) -g -shared -mno-cygwin -Wall -W1,----add-stdcall-alias + C_DEPENDENCIES_FLAGS = -M -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) + # The '-rpath' linker option is used so that LD_LIBRARY_PATH does not have to be configured at runtime to + # find Maxine's version of the libjvm.so library. + # The '-z execstack' is a workaround that stops the runtime dynamic linker from + # changing the protection of the main thread's stack (via mprotect) *after* the + # yellow guard page (for detecting stack overflow) has been mprotected. Without + # this flag, the main thread's complete stack (including the guard page) is + # mprotected with PROT_READ, PROT_WRITE, PROT_EXEC when dlopen() is called to + # open libjava.so. + LINK_MAIN = $(CC) -g -Xlinker -rpath -Xlinker $(shell cd $(PROJECT)/generated/$(OS) && /bin/pwd) -o $(MAIN) + + LINK_LIB = $(CC) -g -shared -mwindows + LINK_LIB_POSTFIX += -lole32 -lws2_32 + + + LIB_PREFIX = - LIB_SUFFIX = .dll + LIB_SUFFIX = .dll + endif ifeq ($(OS),maxve) @@ -413,9 +429,15 @@ else endif JNI_INCLUDES = -I $(dir $(JNI_H_PATH)) endif - else - JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) - JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) + else + ifeq ($(OS),windows) + JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/win32/ + JNI_H_PATH = $(JAVA_HOME)/include/win32/jni.h + else + JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) + JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) + endif + endif endif diff --git a/com.oracle.max.vm.native/platform/usercygwinamd64.h b/com.oracle.max.vm.native/platform/usercygwinamd64.h new file mode 100644 index 0000000000..e1a4c0d496 --- /dev/null +++ b/com.oracle.max.vm.native/platform/usercygwinamd64.h @@ -0,0 +1,45 @@ +struct user_fpregs_struct +{ + unsigned short int cwd; + unsigned short int swd; + unsigned short int ftw; + unsigned short int fop; + __extension__ unsigned long long int rip; + __extension__ unsigned long long int rdp; + unsigned int mxcsr; + unsigned int mxcr_mask; + unsigned int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ + unsigned int padding[24]; +}; + +struct user_regs_struct +{ + __extension__ unsigned long long int r15; + __extension__ unsigned long long int r14; + __extension__ unsigned long long int r13; + __extension__ unsigned long long int r12; + __extension__ unsigned long long int rbp; + __extension__ unsigned long long int rbx; + __extension__ unsigned long long int r11; + __extension__ unsigned long long int r10; + __extension__ unsigned long long int r9; + __extension__ unsigned long long int r8; + __extension__ unsigned long long int rax; + __extension__ unsigned long long int rcx; + __extension__ unsigned long long int rdx; + __extension__ unsigned long long int rsi; + __extension__ unsigned long long int rdi; + __extension__ unsigned long long int orig_rax; + __extension__ unsigned long long int rip; + __extension__ unsigned long long int cs; + __extension__ unsigned long long int eflags; + __extension__ unsigned long long int rsp; + __extension__ unsigned long long int ss; + __extension__ unsigned long long int fs_base; + __extension__ unsigned long long int gs_base; + __extension__ unsigned long long int ds; + __extension__ unsigned long long int es; + __extension__ unsigned long long int fs; + __extension__ unsigned long long int gs; +}; diff --git a/com.oracle.max.vm.native/share/c.h b/com.oracle.max.vm.native/share/c.h index c4add88ca4..ed33c77f61 100644 --- a/com.oracle.max.vm.native/share/c.h +++ b/com.oracle.max.vm.native/share/c.h @@ -53,10 +53,12 @@ typedef long long Signed8; typedef float Float4; typedef double Float8; +#define true 1 +#define false 0 #if !defined(false) && !defined(true) typedef enum {false, true} boolean; #else - typedef int boolean; + typedef unsigned char boolean; #endif #define MAX_PATH_LENGTH 2048 diff --git a/com.oracle.max.vm.native/share/condition.c b/com.oracle.max.vm.native/share/condition.c index 90e052fcfe..b8b8feac0c 100644 --- a/com.oracle.max.vm.native/share/condition.c +++ b/com.oracle.max.vm.native/share/condition.c @@ -18,6 +18,15 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if os_WINDOWS +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 // needed for tools like MINGW in order to use condition variables which became available from Windows Vista and on. Visual Studio might define it on its own +#include + +#endif #include #include #include @@ -45,6 +54,10 @@ void condition_initialize(Condition condition) { } #elif os_MAXVE *condition = maxve_condition_create(); +#elif os_WINDOWS + InitializeConditionVariable(condition); + //initialize condtionVariable does not return anything! + #else # error #endif @@ -62,6 +75,8 @@ void condition_destroy(Condition condition) { if (pthread_cond_destroy(condition) != 0) { c_FATAL(); } +#elif os_WINDOWS +//condition variables cannot get destroyed https://stackoverflow.com/questions/28975958/why-does-windows-have-no-deleteconditionvariable-function-to-go-together-with #endif } @@ -80,7 +95,7 @@ void condition_destroy(Condition condition) { * @return false if an error occurred, true otherwise (i.e. the thread was notified or interrupted). * In either case, the current thread has reacquired the lock on 'mutex'. */ -boolean condition_wait(Condition condition, Mutex mutex) { +boolean condition_wait(Condition condition, Mutex mutex) { //mutex is not needed in windows #if log_MONITORS log_println("condition_wait (" THREAD_CONDVAR_MUTEX_FORMAT ")", thread_self(), condition, mutex); #endif @@ -101,6 +116,8 @@ boolean condition_wait(Condition condition, Mutex mutex) { /* (Doug) I assume 1 means EINTR */ return true; } +#elif os_WINDOWS + error = !SleepConditionVariableCS (condition, mutex, INFINITE); // non zero return value means success on Windows! #endif if (error != 0) { log_println("condition_wait (" THREAD_CONDVAR_MUTEX_FORMAT ") unexpected error code %d [%s]", thread_self(), condition, mutex, error, strerror(error)); @@ -112,7 +129,7 @@ boolean condition_wait(Condition condition, Mutex mutex) { return true; } -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) /* * This function is taken from HotSpot (os_linux.cpp). */ @@ -159,7 +176,7 @@ boolean condition_timedWait(Condition condition, Mutex mutex, Unsigned8 timeoutM log_println("condition_timedWait (" THREAD_CONDVAR_MUTEX_FORMAT ", %d)", thread_self(), condition, mutex, timeoutMilliSeconds); #endif int error; -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) struct timeval now; int status = gettimeofday(&now, NULL); c_ASSERT(status != -1); @@ -198,6 +215,8 @@ boolean condition_timedWait(Condition condition, Mutex mutex, Unsigned8 timeoutM /* (Doug) I assume 1 means EINTR */ return true; } +#elif os_WINDOWS + error = !SleepConditionVariableCS (condition, mutex, timeoutMilliSeconds); // non zero return value means success on Windows! #else # error #endif @@ -222,6 +241,9 @@ boolean condition_notify(Condition condition) { return cond_signal(condition) == 0; #elif os_MAXVE return maxve_condition_notify(*condition, 0) == 0; +#elif os_WINDOWS + WakeConditionVariable (condition); //WakeConditionVariable returns nothing + return true; #else # error #endif @@ -231,12 +253,15 @@ boolean condition_notifyAll(Condition condition) { #if log_MONITORS log_println("condition_notifyAll (" THREAD_CONDVAR_FORMAT ")", thread_self(), condition); #endif -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) return pthread_cond_broadcast(condition) == 0; #elif os_SOLARIS return cond_broadcast(condition) == 0; #elif os_MAXVE return maxve_condition_notify(*condition, 1) == 0; +#elif os_WINDOWS + WakeAllConditionVariable (condition); //WakeAllConditionVariable returns nothing + return true; #else # error #endif diff --git a/com.oracle.max.vm.native/share/condition.h b/com.oracle.max.vm.native/share/condition.h index 93c379f5ca..953fa41c4b 100644 --- a/com.oracle.max.vm.native/share/condition.h +++ b/com.oracle.max.vm.native/share/condition.h @@ -36,6 +36,10 @@ #elif os_MAXVE # include "maxve.h" typedef maxve_condition_t condition_Struct; +#elif os_WINDOWS + typedef CONDITION_VARIABLE condition_Struct; + + #endif typedef condition_Struct *Condition; diff --git a/com.oracle.max.vm.native/share/log.c b/com.oracle.max.vm.native/share/log.c index a5bedc320a..5e5a04a828 100644 --- a/com.oracle.max.vm.native/share/log.c +++ b/com.oracle.max.vm.native/share/log.c @@ -18,17 +18,28 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + + #include #include #include #include -#include #include "log.h" +#if os_WINDOWS +#include +#define pthread_self GetCurrentThread +#else +#include + +#endif + #include "jni.h" #include "mutex.h" #include "threads.h" + + #if !os_MAXVE static FILE *fileStream = NULL; #endif @@ -46,14 +57,14 @@ static mutex_Struct allocationProfiler_mutexStruct; void log_initialize(const char *path) { mutex_initialize(&log_mutexStruct); mutex_initialize(&allocationProfiler_mutexStruct); -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS if (path == NULL) { path = "stdout"; } if (strncmp(path, "stdout\0", 7) == 0) { fileStream = stdout; /* Set the file stream to flush whenever a newline character is encountered */ - setlinebuf(fileStream); + // setlinebuf(fileStream); } else if (strncmp(path, "stderr\0", 7) == 0) { fileStream = stderr; } else { @@ -63,7 +74,7 @@ void log_initialize(const char *path) { exit(1); } /* Set the file stream to flush whenever a newline character is encountered */ - setlinebuf(fileStream); + // setlinebuf(fileStream); } #endif } @@ -71,7 +82,7 @@ void log_initialize(const char *path) { void log_lock(void) { int result; if ((result = mutex_enter_nolog(&log_mutexStruct)) != 0) { - log_exit(-1, "Thread %p could not lock mutex %p: %s", thread_self(), &log_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not lock mutex %p: %s", pthread_self(), &log_mutexStruct, strerror(result)); } } @@ -79,14 +90,14 @@ void numaProfiler_lock(void) { int result; result = mutex_enter_nolog(&allocationProfiler_mutexStruct); if (result != 0) { - log_exit(-1, "Thread %p could not lock mutex %p: %s", thread_self(), &allocationProfiler_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not lock mutex %p: %s", pthread_self(), &allocationProfiler_mutexStruct, strerror(result)); } } void log_unlock(void) { int result; if ((result = mutex_exit_nolog(&log_mutexStruct)) != 0) { - log_exit(-1, "Thread %p could not unlock mutex %p: %s", thread_self(), &log_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not unlock mutex %p: %s", pthread_self(), &log_mutexStruct, strerror(result)); } } @@ -94,7 +105,7 @@ void numaProfiler_unlock(void) { int result; result = mutex_exit_nolog(&allocationProfiler_mutexStruct); if (result != 0) { - log_exit(-1, "Thread %p could not unlock mutex %p: %s", thread_self(), &allocationProfiler_mutexStruct, strerror(result)); + log_exit(-1, "Thread %d could not unlock mutex %p: %s", pthread_self(), &allocationProfiler_mutexStruct, strerror(result)); } } @@ -111,14 +122,14 @@ void log_print_format(const char *format, ...) { } void log_flush() { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS FILE* out = fileStream == NULL ? stdout : fileStream; fflush(out); #endif } void log_print_vformat(const char *format, va_list ap) { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS FILE* out = fileStream == NULL ? stdout : fileStream; vfprintf(out, format, ap); #else @@ -197,8 +208,8 @@ void log_print_newline() { } void log_print_symbol(Address address) { -#if !os_MAXVE - Dl_info info; +#if !os_MAXVE && !os_WINDOWS + Dl_info info; if (dladdr((void *) address, &info) != 0) { if (info.dli_sname == NULL) { log_print("%s (%p+%d)", info.dli_fname, info.dli_fbase, address - (Address) info.dli_fbase); diff --git a/com.oracle.max.vm.native/share/mutex.c b/com.oracle.max.vm.native/share/mutex.c index 4902d146fc..3ed0431939 100644 --- a/com.oracle.max.vm.native/share/mutex.c +++ b/com.oracle.max.vm.native/share/mutex.c @@ -20,6 +20,11 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +#include "os.h" +#if os_WINDOWS +#include +#endif + #include "mutex.h" #include "log.h" #include "threads.h" @@ -50,6 +55,8 @@ void mutex_initialize(Mutex mutex) { } #elif os_MAXVE *mutex = maxve_monitor_create(); +#elif os_WINDOWS + InitializeCriticalSection(mutex); //windows CS's are recursive be default ,mutex is pointer to Critical section # else c_UNIMPLEMENTED(); # endif @@ -65,6 +72,9 @@ int mutex_enter_nolog(Mutex mutex) { c_ASSERT(false); } return 0; +#elif os_WINDOWS + EnterCriticalSection(mutex); //mutex is pointer to Critical section. EnterCriticalSection returns nothing + return 0; //0 means success for funcs like pthread_mutex_lock #else c_UNIMPLEMENTED(); #endif @@ -73,8 +83,11 @@ int mutex_enter_nolog(Mutex mutex) { int mutex_try_enter(Mutex mutex) { #if os_SOLARIS return mutex_trylock(mutex); -#elif os_LINUX || os_DARWIN +#elif os_LINUX || os_DARWIN return pthread_mutex_trylock(mutex); +#elif os_WINDOWS + return !TryEnterCriticalSection(mutex); //mutex is pointer to Critical section. On windows non zero return value means success that's why we use ! at the result + #else c_UNIMPLEMENTED(); #endif @@ -98,6 +111,9 @@ int mutex_exit_nolog(Mutex mutex) { c_ASSERT(false); } return 0; +#elif os_WINDOWS + LeaveCriticalSection(mutex); //mutex is pointer to Critical section + return 0; #else c_UNIMPLEMENTED(); #endif @@ -124,5 +140,8 @@ void mutex_dispose(Mutex mutex) { } #elif os_MAXVE c_UNIMPLEMENTED(); +#elif os_WINDOWS + DeleteCriticalSection(mutex); //mutex is pointer to Critical section + #endif } diff --git a/com.oracle.max.vm.native/share/mutex.h b/com.oracle.max.vm.native/share/mutex.h index 962941271a..68ebec04de 100644 --- a/com.oracle.max.vm.native/share/mutex.h +++ b/com.oracle.max.vm.native/share/mutex.h @@ -35,8 +35,9 @@ #elif os_MAXVE # include typedef maxve_monitor_t mutex_Struct; +#elif os_WINDOWS +typedef CRITICAL_SECTION mutex_Struct; #endif - typedef mutex_Struct *Mutex; extern void mutex_initialize(Mutex mutex); diff --git a/com.oracle.max.vm.native/share/threadLocals.c b/com.oracle.max.vm.native/share/threadLocals.c index 5868340538..11b7a7ea24 100644 --- a/com.oracle.max.vm.native/share/threadLocals.c +++ b/com.oracle.max.vm.native/share/threadLocals.c @@ -18,7 +18,14 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include + #include "os.h" +#if !os_WINDOWS + #include +#else + #include + #include + #define aligned_alloc(a, b) _aligned_malloc(a, b) +#endif #include #include @@ -48,6 +55,9 @@ typedef maxve_Thread Thread; typedef maxve_SpecificsKey ThreadLocalsKey; typedef void (*ThreadLocalsBlockDestructor)(void *); +#elif os_WINDOWS + typedef DWORD ThreadLocalsKey; + #endif int theTLASize = -1; @@ -86,7 +96,7 @@ static void deallocateThreadLocalBlock(Address tlBlock, Size tlBlockSize) { * lazily commit memory reserved for the initial thread's stack. */ static void commitStackMemoryForInitialThread(Address base, int pageSize) { -#if os_LINUX +#if os_LINUX || os_WINDOWS /* Writing to the bottom page of the reserved stack (appears) not to be * sufficient on Linux. Using alloca() to allocate a chunk approximately * the size of the remaining stack seems to fix it. */ @@ -347,7 +357,7 @@ void threadLocalsBlock_destroy(Address tlBlock) { void tla_initialize(int tlaSize) { theTLASize = tlaSize; #if !TELE -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX int error = pthread_key_create(&theThreadLocalsKey, (ThreadLocalsBlockDestructor)(void *) threadLocalsBlock_destroy); #if log_THREADS log_println("tla_initialize: pthread_key_create returned code = %d", error); @@ -355,6 +365,8 @@ void tla_initialize(int tlaSize) { if (error != 0) { log_exit(-1, "tla_initialize: pthread_key_create returned non zero code = %d", error); } +#elif os_WINDOWS + theThreadLocalsKey = TlsAlloc(); #elif os_SOLARIS thr_keycreate(&theThreadLocalsKey, (ThreadLocalsBlockDestructor) threadLocalsBlock_destroy); #elif os_MAXVE @@ -368,7 +380,7 @@ void tla_initialize(int tlaSize) { Address threadLocalsBlock_current() { Address tlBlock; -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX tlBlock = (Address) pthread_getspecific(theThreadLocalsKey); #elif os_SOLARIS Address value; @@ -379,6 +391,8 @@ Address threadLocalsBlock_current() { tlBlock = value; #elif os_MAXVE tlBlock = (Address) maxve_thread_getSpecific(theThreadLocalsKey); +#elif os_WINDOWS + tlBlock = (Address) TlsGetValue(theThreadLocalsKey); #else c_UNIMPLEMENTED(); #endif @@ -386,12 +400,14 @@ Address threadLocalsBlock_current() { } void threadLocalsBlock_setCurrent(Address tlBlock) { -#if (os_DARWIN || os_LINUX) +#if (os_DARWIN || os_LINUX ) pthread_setspecific(theThreadLocalsKey, (void *) tlBlock); #elif os_SOLARIS thr_setspecific(theThreadLocalsKey, (void *) tlBlock); #elif os_MAXVE maxve_thread_setSpecific(theThreadLocalsKey, (void *) tlBlock); +#elif os_WINDOWS + TlsSetValue(theThreadLocalsKey, (LPVOID) tlBlock); #endif } diff --git a/com.oracle.max.vm.native/share/threads.h b/com.oracle.max.vm.native/share/threads.h index f360882742..63b48db454 100644 --- a/com.oracle.max.vm.native/share/threads.h +++ b/com.oracle.max.vm.native/share/threads.h @@ -80,8 +80,13 @@ typedef void (*VmThreadDetachMethod)(Address tla); * @return true if the sleep was interrupted */ extern jboolean thread_sleep(jlong numberOfMilliSeconds); +#if os_WINDOWS +DWORD WINAPI thread_run(LPVOID param); +#else + +void * thread_run(void *arg); -void *thread_run(void *arg); +#endif int thread_attachCurrent(void **penv, JavaVMAttachArgs* args, boolean daemon); int thread_detachCurrent(); diff --git a/com.oracle.max.vm.native/share/virtualMemory.c b/com.oracle.max.vm.native/share/virtualMemory.c index 1846d69f03..5ef4152e04 100644 --- a/com.oracle.max.vm.native/share/virtualMemory.c +++ b/com.oracle.max.vm.native/share/virtualMemory.c @@ -18,18 +18,28 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + + #include "virtualMemory.h" #include "log.h" + #if defined(MAXVE) -#include + #include /* No mmap function on MaxVE (yet)*/ #else -#include -#include -#include -#include - + #include + #include + #include + #if !os_WINDOWS + #include + #else + #ifdef _WIN32_WINNT + #undef _WIN32_WINNT + #endif + #define _WIN32_WINNT 0x0601 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. + #include + #endif #include "jni.h" #include "unistd.h" @@ -39,7 +49,7 @@ #endif /* There is a problem binding these identifiers in RedHat's include files, so we fake them: */ -#if os_LINUX +#if os_LINUX || os_WINDOWS # ifndef MAP_ANONYMOUS # define MAP_ANONYMOUS 0x20 # endif @@ -58,11 +68,16 @@ # define MAP_32BIT 0 # endif #endif - +#if !os_WINDOWS #define PROT (PROT_EXEC | PROT_READ | PROT_WRITE) +#endif + +#if !os_WINDOWS //we do not use mmap on Windows so this function is not needed. /* mmap returns MAP_FAILED on error, we convert to ALLOC_FAILED */ static Address check_mmap_result(void *result) { + + #if log_MMAP if(result == MAP_FAILED) { switch(errno) { @@ -99,8 +114,11 @@ static Address check_mmap_result(void *result) { } } #endif + return ((Address) (result == (void *) MAP_FAILED ? ALLOC_FAILED : result)); } +#endif + #ifdef arm static int attempt = 0; @@ -125,8 +143,36 @@ Address virtualMemory_allocatePrivateAnon(Address address, Size size, jboolean r address = allocAddress; } #endif +#if os_WINDOWS + //Windows got no Swap space, so jboolean reserveSwap is redundant + Address result; + if(protNone == JNI_TRUE){ + + result = (Address) VirtualAlloc( (void *) address, size, MEM_COMMIT | MEM_RESERVE| PAGE_WRITECOPY, PAGE_NOACCESS); + + //virtualalloc is the only win32 function that supports the PROT_NONE equivalent PAGE_NOACCESS + //PAGE_WRITECOPY is equivalent to MAP_PRIVATE + if(!result) + log_println("%d\n", GetLastError()); + } + else { + //if protnone is not used, we can use CreateFileMappingA + MapViewOfFile combination to emulate mmap() on Windows + //INVALID_HANDLE_VALUE means that we dont use an actual file but the system pagefile, similar to fd= -1 & MPI_ANON in mmap() + HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + //FILE_MAP_COPY is equivalent to MAP_PRIVATE +if(!fmapping) + log_println("%d\n", GetLastError()); + result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, 0, 0, size, (LPVOID)address); + if(!result) + log_println("%d\n", GetLastError()); + + + } + return result; + +#else int flags = MAP_PRIVATE | MAP_ANON; -#if os_LINUX +#if os_LINUX /* For some reason, subsequent calls to mmap to allocate out of the space * reserved here only work if the reserved space is in 32-bit space. */ #endif @@ -153,6 +199,7 @@ Address virtualMemory_allocatePrivateAnon(Address address, Size size, jboolean r #else return check_mmap_result(result); #endif +#endif } @@ -172,6 +219,15 @@ Address virtualMemory_mapFile(Size size, jint fd, Size offset) { address = check_mmap_result(result); allocAddress = address + size; return address; +#elif os_WINDOWS + HANDLE fmapping = CreateFileMappingA( (HANDLE)_get_osfhandle(fd) , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA + Address result = (Address) MapViewOfFile (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size); + //FILE_MAP_COPY is equivalent to mmap's MAP_PRIVATE. It maps a copy-on-write view of the file that is private to the process. + //MapViewOfFile needs lower and high order of offset (last and first 32 bits). We get high and lower orders of the offset (which might be 64bit long) by doing casts to DWORD( 32 BITS) and Binary shifts + if(!result) + log_println("%d\n", GetLastError()); + return result; #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_PRIVATE, fd, (off_t) offset)); #endif @@ -183,7 +239,20 @@ Java_com_sun_max_memory_VirtualMemory_virtualMemory_1mapFile(JNIEnv *env, jclass } Address virtualMemory_mapFileIn31BitSpace(jint size, jint fd, Size offset) { + #if os_WINDOWS //MAP_32BIT is not supported on Windows.... Also in Linux, it is no longer really needed + /*"It was added to allow thread stacks to be + allocated somewhere in the first 2 GB of memory, so as to + improve context-switch performance on some early 64-bit + processors. Modern x86-64 processors no longer have this + performance problem, so use of this flag is not required on + those systems. + + https://man7.org/linux/man-pages/man2/mmap.2.html + */ + return virtualMemory_mapFile(size, fd, offset); + #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_PRIVATE | MAP_32BIT, fd, (off_t) offset)); + #endif } JNIEXPORT jlong JNICALL @@ -192,7 +261,20 @@ Java_com_sun_max_memory_VirtualMemory_virtualMemory_1mapFileIn31BitSpace(JNIEnv } Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, Size offset) { + #if os_WINDOWS + HANDLE fmapping = CreateFileMappingA( (HANDLE)_get_osfhandle(fd) , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,0, NULL); + //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA + if(!fmapping) + log_println("%d\n", GetLastError()); + Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size,(LPVOID) address); + //the only diffrence is that we use MapViewOfFileEx instead MapViewOfFile. The first one allows us to provide an initial base address where the mapping begins (last argument) + + if(!result) + log_println("%d\n", GetLastError()); + return result; + #else return check_mmap_result(mmap((void *) address, (size_t) size, PROT, MAP_PRIVATE | MAP_FIXED, fd, (off_t) offset)); + #endif } // end of conditional exclusion of mmap stuff not available (or used) on MAXVE @@ -202,14 +284,23 @@ Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, Address virtualMemory_allocate(Size size, int type) { #if os_MAXVE return (Address) maxve_virtualMemory_allocate(size, type); +#elif os_WINDOWS + HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + Address result = (Address) MapViewOfFile (fmapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size); + if(!result) + log_println("%d\n", GetLastError()); + return result; #else return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)); #endif } Address virtualMemory_allocateIn31BitSpace(Size size, int type) { -#if os_LINUX +#if os_LINUX return check_mmap_result(mmap(0, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1, (off_t) 0)); + +#elif os_WINDOWS + return virtualMemory_allocate(size, type); //windows do not have equivalent of MAP_32BIT, also obsolete in Linux #elif os_MAXVE return (Address) maxve_virtualMemory_allocateIn31BitSpace(size, type); #else @@ -221,6 +312,17 @@ Address virtualMemory_allocateIn31BitSpace(Size size, int type) { Address virtualMemory_deallocate(Address start, Size size, int type) { #if os_MAXVE return (Address) maxve_virtualMemory_deallocate((void *)start, size, type); +#elif os_WINDOWS + if( UnmapViewOfFile((LPVOID) start) == 0){ // VirtualFree will fail for addresses mapped with MapViewOfFile so we use UnmapViewOfFile first + int result = VirtualFree((LPVOID)start, size, type); //if UnmapViewOfFile failed, we try virtualalloc (the memory might got mapped with VirtualAlloc) + //type can be MEM_RELEASE or whatever the user provides. (It was implemented for MAXVE that way) + if (!result) + return result; + else + return start; + } + else + return start; #else int result = munmap((void *) start, (size_t) size); return result == -1 ? 0 : start; @@ -230,6 +332,13 @@ Address virtualMemory_deallocate(Address start, Size size, int type) { boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int type) { #if os_SOLARIS || os_DARWIN || os_LINUX return check_mmap_result(mmap((void *) address, (size_t) size, PROT, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, (off_t) 0)) != ALLOC_FAILED; +#elif os_WINDOWS + HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); + //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA + Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, 0, 0, size,(LPVOID) address); + if(!result) + log_println("%d\n", GetLastError()); + return result; #elif os_MAXVE return (Address) maxve_virtualMemory_allocateAtFixedAddress((unsigned long)address, size, type) != ALLOC_FAILED; #else @@ -241,11 +350,18 @@ boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int typ void virtualMemory_protectPages(Address address, int count) { /* log_println("--- protected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ c_ASSERT(virtualMemory_pageAlign(address) == address); -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_NONE) != 0) { int error = errno; log_exit(error, "protectPages: mprotect(%p) failed: %s", address, strerror(error)); } +#elif os_WINDOWS + DWORD old; //needed for VirtualProtect + int error = GetLastError(); + if(!VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_NOACCESS, &old)) //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) + log_exit(error, "protectPages: VirtualProtect(%p) failed", address); + + #elif os_MAXVE maxve_virtualMemory_protectPages(address, count); #else @@ -256,11 +372,14 @@ void virtualMemory_protectPages(Address address, int count) { void virtualMemory_unprotectPages(Address address, int count) { /* log_println("--- unprotected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ c_ASSERT(virtualMemory_pageAlign(address) == address); -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_READ| PROT_WRITE) != 0) { int error = errno; log_exit(error, "unprotectPages: mprotect(%p) failed: %s", address, strerror(error)); } +#elif os_WINDOWS + DWORD old; //needed for VirtualProtect + VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_READWRITE, &old); //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) #elif os_MAXVE maxve_virtualMemory_unProtectPages(address, count); #else @@ -276,7 +395,13 @@ unsigned int virtualMemory_getPageSize(void) { return maxve_virtualMemory_pageSize(); #else if (pageSize == 0) { + #if os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + pageSize = systemInfo.dwPageSize ; + #else pageSize = getpagesize(); + #endif } return pageSize; #endif @@ -287,9 +412,12 @@ Size virtualMemory_getPhysicalMemorySize(void) { #if os_MAXVE // TODO return 0; -#elif os_SOLARIS || os_LINUX +#elif os_SOLARIS || os_LINUX Size numPhysicalPages = (Size) sysconf(_SC_PHYS_PAGES); physicalMemory = numPhysicalPages * virtualMemory_getPageSize(); +#elif os_WINDOWS + GetPhysicallyInstalledSystemMemory(&physicalMemory); + return physicalMemory * 1024; //we want bytes #elif os_DARWIN int query[2]; query[0] = CTL_HW; diff --git a/com.oracle.max.vm.native/substrate/barrier.c b/com.oracle.max.vm.native/substrate/barrier.c index 86bb92ad9d..20fbdcd928 100644 --- a/com.oracle.max.vm.native/substrate/barrier.c +++ b/com.oracle.max.vm.native/substrate/barrier.c @@ -1,6 +1,4 @@ /* - * Copyright (c) 2020, APT Group, Department of Computer Science, - * School of Engineering, The University of Manchester. All rights reserved. * Copyright (c) 2019, APT Group, School of Computer Science, * The University of Manchester. All rights reserved. * @@ -40,7 +38,7 @@ /* * Pre-processor override for whether to compile in the membarrier system call. - * Currently only affects Aarch64 and RISCV64. See syscall_membarrier() in this compilation + * Currently only affects Aarch64. See syscall_membarrier() in this compilation * unit. */ #ifndef USE_SYS_MEMBARRIER @@ -64,7 +62,7 @@ static int membarrier_init(void) __attribute__ ((unused)); void syscall_membarrier() { -#if isa_AARCH64 || isa_RISCV64 +#if isa_AARCH64 # if USE_SYS_MEMBARRIER static volatile int barrier_kind = 0; if (!barrier_kind) { diff --git a/com.oracle.max.vm.native/substrate/image.c b/com.oracle.max.vm.native/substrate/image.c index 9825dd7ab9..198ea69f91 100644 --- a/com.oracle.max.vm.native/substrate/image.c +++ b/com.oracle.max.vm.native/substrate/image.c @@ -20,10 +20,13 @@ */ #include "os.h" + #include #include #include +#if !os_WINDOWS #include +#endif #include #include @@ -277,7 +280,7 @@ static void checkTrailer(int fd) { if (trailerStructPtr->identification != theHeader->identification || trailerStructPtr->bootImageFormatVersion != theHeader->bootImageFormatVersion || trailerStructPtr->randomID != theHeader->randomID) { log_println("inconsistent trailer"); #if !MEMORY_IMAGE - offset = lseek(fd, -sizeof(trailerStruct), SEEK_END); + offset = lseek(fd, (long int)-sizeof(trailerStruct), SEEK_END); if (offset != fileSize - (off_t) sizeof(trailerStruct)) { log_exit(1, "could not set trailer position at end of file"); } @@ -304,7 +307,7 @@ static void mapHeapAndCode(int fd) { #endif #if MEMORY_IMAGE theHeap = (Address) &maxvm_image_start + heapOffsetInImage; -#elif os_SOLARIS || os_DARWIN || os_LINUX +#elif os_SOLARIS || os_DARWIN || os_LINUX || os_WINDOWS Address reservedVirtualSpace = (Address) 0; size_t virtualSpaceSize = 1024L * theHeader->reservedVirtualSpaceSize; c_ASSERT(virtualMemory_pageAlign((Size) virtualSpaceSize) == (Size) virtualSpaceSize); @@ -332,7 +335,7 @@ static void mapHeapAndCode(int fd) { log_exit(4, "could not reserve virtual space for boot image"); } } - if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { + if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { //CAUTION on Windows, the Base Address must be a multiple of dwAllocationGranularity else mapping fails (UNTESTED since no image file is availabe) log_exit(4, "could not map boot image"); } if (reservedVirtualSpace) { @@ -419,7 +422,7 @@ void image_load(char *imageFileName) { } #endif - readHeader(fd); + readHeader(fd); checkImage(); readStringInfo(fd); checkTrailer(fd); diff --git a/com.oracle.max.vm.native/substrate/jni.c b/com.oracle.max.vm.native/substrate/jni.c index 871108e597..a18a76141b 100644 --- a/com.oracle.max.vm.native/substrate/jni.c +++ b/com.oracle.max.vm.native/substrate/jni.c @@ -26,7 +26,10 @@ * arguments in such an array. This isolates the implementation of such functions * from the platform/compiler dependent way in which varargs are implemented. */ -#include +#include "os.h" +#if os_WINDOWS +#include +#endif #include #include #include @@ -37,7 +40,9 @@ #include "threads.h" #include "vm.h" - +#if !os_WINDOWS +#include +#endif #ifndef JNI_VERSION_1_6 #error The version of jni.h being included must define the JNI_VERSION_1_6 macro #endif @@ -808,11 +813,15 @@ jint JNICALL jni_GetEnv(JavaVM *javaVM, void **penv, jint version) { return JNI_OK; } } - +#if os_WINDOWS +__declspec( dllimport ) +#endif jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) { return c_UNIMPLEMENTED(); } - +#if os_WINDOWS +__declspec( dllimport ) +#endif jint JNICALL jni_DestroyJavaVM(JavaVM *vm) { return c_UNIMPLEMENTED(); } @@ -829,7 +838,9 @@ jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { return thread_detachCurrent(); } - +#if os_WINDOWS +__declspec( dllimport ) +#endif jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { return c_UNIMPLEMENTED(); } @@ -857,7 +868,7 @@ JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs_Impl(JavaVM **vm, jsize vmBufLen, j return JNI_OK; } -JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm, jsize vmBufLen, jsize *nVMs) { +JNIEXPORT jint JNICALL __imp_JNI_GetCreatedJavaVMs(JavaVM **vm, jsize vmBufLen, jsize *nVMs) { return JNI_GetCreatedJavaVMs_Impl(vm, vmBufLen, nVMs); } diff --git a/com.oracle.max.vm.native/substrate/jvm.c b/com.oracle.max.vm.native/substrate/jvm.c index c2eab15fbc..0fd63eb587 100644 --- a/com.oracle.max.vm.native/substrate/jvm.c +++ b/com.oracle.max.vm.native/substrate/jvm.c @@ -26,40 +26,71 @@ * In cases where we bypass JDK's native libraries (@see com.sun.max.vm.jdk) * we can simply omit unneeded JVM interface functions that would otherwise occur here. */ -#include +#include "os.h" +#if os_WINDOWS +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. +#include +#include +#define lseek64 _lseeki64 +#define open _open +#define close _close //open and close work on mingw but are deprecated in MSVC so we better use _ before the name. (Internally, they call win32 funcs like CreateFile() and are added by Microsoft for POSIX compatibility +#define ftruncate _chsize +#define ioctl(a, b, c) ioctlsocket(a, b, (u_long *) c) +#include +#endif + + + + +#include "vm.h" +#include "log.h" +#include "trap.h" +#include "mutex.h" +#include "threads.h" +#include "maxine.h" +#include "memory.h" + +#if !os_WINDOWS + #include #include #include -#include -#include + + #include #include #include #include +#endif +#include + +#include +#include + #if os_DARWIN #include -#else +#elif !os_WINDOWS #include #endif +#if !os_WINDOWS +#include +#endif -#include "vm.h" -#include "log.h" -#include "trap.h" -#include "mutex.h" -#include "threads.h" -#include "maxine.h" -#include "memory.h" #if os_SOLARIS #include #endif -#if os_DARWIN +#if os_DARWIN #define lseek64 lseek #include - #endif +#include + // Platform-independent error return values from OS functions enum OSReturn { @@ -253,7 +284,7 @@ JVM_ActiveProcessorCount(void) { } // Otherwise return number of online cpus return online_cpus; -#elif os_LINUX +#elif os_LINUX cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors int cpus_size = sizeof(cpu_set_t); int processor_count = sysconf(_SC_NPROCESSORS_CONF); @@ -279,6 +310,11 @@ JVM_ActiveProcessorCount(void) { int online_cpus = sysconf(_SC_NPROCESSORS_ONLN); c_ASSERT(online_cpus > 0); return online_cpus; +#elif os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + return systemInfo.dwNumberOfProcessors; //not sure if we need logical or physical processors + //alternatively we can read NUMBER_OF_PROCESSORS environment variable #else UNIMPLEMENTED(); return 0; @@ -287,12 +323,15 @@ JVM_ActiveProcessorCount(void) { #if os_SOLARIS || os_LINUX || os_DARWIN #include + #endif void * JVM_LoadLibrary(const char *name) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN return dlopen(name, RTLD_LAZY); +#elif os_WINDOWS + return LoadLibraryA(name); #else UNIMPLEMENTED(); return 0; @@ -303,6 +342,8 @@ void JVM_UnloadLibrary(void * handle) { #if os_SOLARIS || os_LINUX || os_DARWIN dlclose(handle); +#elif os_WINDOWS + FreeLibrary(handle); #else UNIMPLEMENTED(); #endif @@ -310,8 +351,10 @@ JVM_UnloadLibrary(void * handle) { void * JVM_FindLibraryEntry(void *handle, const char *name) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN return dlsym(handle, name); +#elif os_WINDOWS + return GetProcAddress(handle, name); #else UNIMPLEMENTED(); return 0; @@ -443,7 +486,9 @@ JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name) { /* Same as JDK7u4 (and before): do nothing as not yet implemented on either Solaris / Linux */ #endif } - +#if os_WINDOWS //Microsot uses an empty Yield() Macro (obsolete, not needed) in windows.h which breaks our code so we need to undef it. +#undef Yield +#endif void JVM_Yield(JNIEnv *env, jclass threadClass) { vm.Yield(env); @@ -591,7 +636,7 @@ JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index) { jvalue JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode) { UNIMPLEMENTED_WITH_ENV(); - return (jvalue) 0; + return (jvalue) (jint)0; } void @@ -725,7 +770,9 @@ JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, /* * Reflection support functions */ - +#if os_WINDOWS //Microsot defines GetClassName as GetClassNameA in windows.h which breaks our code so we need to undef it. +#undef GetClassName +#endif jstring JVM_GetClassName(JNIEnv *env, jclass cls) { return vm.GetClassName(env, cls); @@ -1084,36 +1131,37 @@ JVM_RaiseSignal(jint sig) { if (kill(getpid(), sig) < 0) { log_println("error raising signal %d in current process: %s", sig, strerror(errno)); } +#elif os_WINDOWS + if(raise(sig)) + log_println("error raising signal %d in current process: %s", sig, strerror(errno)); + #else UNIMPLEMENTED(); #endif return JNI_TRUE; } -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX || os_WINDOWS typedef struct { const char *name; int number; } Signal; Signal signals[] = { + #if !os_WINDOWS {"HUP", SIGHUP}, - {"INT", SIGINT}, + {"QUIT", SIGQUIT}, {"ILL", SIGILL}, {"TRAP", SIGTRAP}, - {"ABRT", SIGABRT}, #if os_DARWIN {"EMT", SIGEMT}, #endif - {"FPE", SIGFPE}, {"KILL", SIGKILL}, {"BUS", SIGBUS}, - {"SEGV", SIGSEGV}, {"SYS", SIGSYS}, {"PIPE", SIGPIPE}, {"ALRM", SIGALRM}, - {"TERM", SIGTERM}, {"URG", SIGURG}, {"STOP", SIGSTOP}, {"TSTP", SIGTSTP}, @@ -1132,12 +1180,23 @@ Signal signals[] = { #endif {"USR1", SIGUSR1}, {"USR2", SIGUSR2}, + + + #endif + {"ABRT", SIGABRT}, + {"FPE", SIGFPE}, + {"ILL", SIGILL}, + {"INT", SIGINT}, + {"SEGV", SIGSEGV}, + {"TERM", SIGTERM}, + + }; #endif jint JVM_FindSignal(const char *name) { -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX || os_WINDOWS unsigned int i; for (i = 0; i < ARRAY_LENGTH(signals); i++) { if(!strcmp(name, signals[i].name)) { @@ -1804,7 +1863,7 @@ jint JVM_GetLastErrorString(char *buffer, size_t length) { if (errno == 0) { return 0; } -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX || os_WINDOWS const char *s = strerror(errno); size_t n = strlen(s); if (n >= length) { @@ -1826,7 +1885,7 @@ jint JVM_GetLastErrorString(char *buffer, size_t length) { */ char *JVM_NativePath(char *path) { jvmni_log_println("JVM_NativePath(%s)", path); -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX || os_WINDOWS return path; #else UNIMPLEMENTED(); @@ -1902,6 +1961,7 @@ JVM_Write(jint fd, char *buf, jint nbytes) { jint JVM_Available(jint fd, jlong *pbytes) { jlong cur, end; + #if !os_WINDOWS struct stat st; if (fstat(fd, &st) >= 0) { if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { @@ -1912,6 +1972,7 @@ jint JVM_Available(jint fd, jlong *pbytes) { } } } + #endif if ((cur = lseek64(fd, 0L, SEEK_CUR)) == -1) { return 0; } else if ((end = lseek64(fd, 0L, SEEK_END)) == -1) { @@ -1945,7 +2006,9 @@ JVM_Lseek(jint fd, jlong offset, jint whence) { */ jint JVM_SetLength(jint fd, jlong length) { - return ftruncate(fd, length); + return + + ftruncate(fd, length); } /* @@ -1954,7 +2017,12 @@ JVM_SetLength(jint fd, jlong length) { */ jint JVM_Sync(jint fd) { - return fsync(fd); + #if !os_WINDOWS + return fsync(fd); + #else + return !FlushFileBuffers((HANDLE)_get_osfhandle(fd)); //_get_osfhandle transforms fd to HANDLE that is needed by FlushFileBuffers +//Windows return nonzero on success + #endif } /* @@ -1963,7 +2031,7 @@ JVM_Sync(jint fd) { jint JVM_InitializeSocketLibrary(void) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return 0; #else UNIMPLEMENTED(); @@ -1971,16 +2039,15 @@ JVM_InitializeSocketLibrary(void) { #endif } -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS #include -#include #else struct sockaddr; #endif jint JVM_Socket(jint domain, jint type, jint protocol) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return socket(domain, type, protocol); #else UNIMPLEMENTED(); @@ -1990,7 +2057,7 @@ JVM_Socket(jint domain, jint type, jint protocol) { jint JVM_SocketClose(jint fd) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return close(fd); #else UNIMPLEMENTED(); @@ -2000,7 +2067,7 @@ JVM_SocketClose(jint fd) { jint JVM_SocketShutdown(jint fd, jint howto) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return shutdown(fd, howto); #else UNIMPLEMENTED(); @@ -2010,7 +2077,9 @@ JVM_SocketShutdown(jint fd, jint howto) { jint JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS + + return recv(fd, buf, nBytes, flags); #else UNIMPLEMENTED(); @@ -2020,7 +2089,8 @@ JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) { jint JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS + return send(fd, buf, nBytes, flags); #else UNIMPLEMENTED(); @@ -2028,6 +2098,10 @@ JVM_Send(jint fd, char *buf, jint nBytes, jint flags) { #endif } +#if os_WINDOWS +extern int gettimeofday(struct timeval * tp); + +#endif jint JVM_Timeout(int fd, long timeout) { #if os_DARWIN || os_LINUX @@ -2085,6 +2159,36 @@ JVM_Timeout(int fd, long timeout) { } } else return res; } +#elif os_WINDOWS +Unsigned8 prevtime,newtime; + struct timeval t; + + gettimeofday(&t); + prevtime = ((Unsigned8)t.tv_sec * 1000) + t.tv_usec / 1000; + + for(;;) { + WSAPOLLFD pfd; + + pfd.fd = fd; + pfd.events = POLLIN | POLLERR; + + int res = WSAPoll(&pfd, 1, timeout); + + if (res == SOCKET_ERROR && errno == EINTR) { + + // On Windows any value < 0 means "forever" too + + if(timeout >= 0) { + gettimeofday(&t); + newtime = ((Unsigned8)t.tv_sec * 1000) + t.tv_usec / 1000; + timeout -= newtime - prevtime; + if(timeout <= 0) + return OS_OK; + prevtime = newtime; + } + } else + return res; + } #else UNIMPLEMENTED(); return 0; @@ -2093,7 +2197,7 @@ JVM_Timeout(int fd, long timeout) { jint JVM_Listen(jint fd, jint count) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return listen(fd, count); #else UNIMPLEMENTED(); @@ -2103,7 +2207,7 @@ JVM_Listen(jint fd, jint count) { jint JVM_Connect(jint fd, struct sockaddr *him, jint len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return connect(fd, him, len); #else UNIMPLEMENTED(); @@ -2113,7 +2217,7 @@ JVM_Connect(jint fd, struct sockaddr *him, jint len) { jint JVM_Bind(jint fd, struct sockaddr *him, jint len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return bind(fd, him, len); #else UNIMPLEMENTED(); @@ -2123,7 +2227,7 @@ JVM_Bind(jint fd, struct sockaddr *him, jint len) { jint JVM_Accept(jint fd, struct sockaddr *him, jint *len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS if (fd < 0) { return -1; } @@ -2173,7 +2277,8 @@ JVM_SocketAvailable(jint fd, jint *pbytes) { // note ioctl can return 0 when successful, JVM_SocketAvailable // is expected to return 0 on failure and 1 on success to the jdk. return (ret == OS_ERR) ? 0 : 1; -#elif os_LINUX +#elif os_LINUX || os_WINDOWS + // Linux doc says EINTR not returned, unlike Solaris int ret = ioctl(fd, FIONREAD, pbytes); @@ -2189,7 +2294,7 @@ JVM_SocketAvailable(jint fd, jint *pbytes) { jint JVM_GetSockName(jint fd, struct sockaddr *him, int *len) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return getsockname(fd, him, (socklen_t*) len); #else UNIMPLEMENTED(); @@ -2199,7 +2304,7 @@ JVM_GetSockName(jint fd, struct sockaddr *him, int *len) { jint JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return getsockopt(fd, level, optname, optval, (socklen_t*) optlen); #else UNIMPLEMENTED(); @@ -2209,7 +2314,7 @@ JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) { jint JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return setsockopt(fd, level, optname, optval, optlen); #else UNIMPLEMENTED(); @@ -2245,7 +2350,7 @@ JVM_GetHostByName(char* name) { int JVM_GetHostName(char* name, int namelen) { -#if os_SOLARIS || os_LINUX || os_DARWIN +#if os_SOLARIS || os_LINUX || os_DARWIN || os_WINDOWS return gethostname(name, namelen); #else UNIMPLEMENTED(); diff --git a/com.oracle.max.vm.native/substrate/jvmti.c b/com.oracle.max.vm.native/substrate/jvmti.c index c8b9dc0129..5e6c923371 100644 --- a/com.oracle.max.vm.native/substrate/jvmti.c +++ b/com.oracle.max.vm.native/substrate/jvmti.c @@ -18,7 +18,15 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if os_WINDOWS +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 // needed for tools like MINGW in order to use condition variables which became available from Windows Vista and on. Visual Studio might define it on its own +#include +#endif #include #include #include @@ -28,7 +36,7 @@ // (cwi): Java 7 added a new JVMTI function, so it is necessary to distinguish between Java 6 and Java 7. // This is the only #define that I found in the header files that allows this distinction. -#if os_LINUX || os_SOLARIS +#if os_LINUX || os_SOLARIS || os_WINDOWS #include #endif diff --git a/com.oracle.max.vm.native/substrate/maxine.c b/com.oracle.max.vm.native/substrate/maxine.c index a8a3dbf3bf..c6759acb1a 100644 --- a/com.oracle.max.vm.native/substrate/maxine.c +++ b/com.oracle.max.vm.native/substrate/maxine.c @@ -26,35 +26,61 @@ * hands control over to the VM's compiled code, which has been written in Java, * by calling a VM entry point as a C function. */ -#include + #include "os.h" + + #if !os_WINDOWS + #include + #include + #include + #include + #include + #include + #include +#else + #ifdef _WIN32_WINNT + #undef _WIN32_WINNT + #endif + #define _WIN32_WINNT 0x0600 //needed for tools like MINGW which declare an earlier version of Windows making some features of win32 api unavailable. Visual Studio might not need this. + #include + #include + #include + #include + #include + #define sleep(a) Sleep(a * 1000) + #define strdup _strdup + char last_dl_error [100]; //emulating dlerror() function not available on Windows +#endif + + #include #include -#include -#include + #include -#include #include -#include -#include -#include + #include #include "log.h" #include "isa.h" #include "image.h" #include "threads.h" -#include "os.h" #include "vm.h" #include "virtualMemory.h" #include "maxine.h" #include + + + + #if os_MAXVE #include "maxve.h" #endif -#ifdef arm +#ifdef arm +#if !os_WINDOWS #include #endif +#endif static void max_fd_limit() { @@ -76,7 +102,10 @@ static void max_fd_limit() { log_println("setrlimit failed"); } } +#elif os_WINDOWS + _setmaxstdio(16777216); //windows support setting the max number of fds but they do not have a global max defined. That numer is the theoeretical max fo 64 bit machines #endif + } #define IMAGE_FILE_NAME "maxine.vm" @@ -96,15 +125,18 @@ static void getExecutablePath(char *result) { #elif os_MAXVE result[0] = 0; return; -#elif os_LINUX +#elif os_LINUX char *linkName = "/proc/self/exe"; #elif os_SOLARIS char *linkName = "/proc/self/path/a.out"; +#elif os_WINDOWS + + int numberOfChars = GetModuleFileNameA(NULL,result, MAX_PATH_LENGTH); #else # error getExecutablePath() not supported on other platforms yet #endif -#if os_LINUX || os_SOLARIS +#if os_LINUX || os_SOLARIS // read the symbolic link to figure out what the executable is. int numberOfChars = readlink(linkName, result, MAX_PATH_LENGTH); if (numberOfChars < 0) { @@ -116,7 +148,11 @@ static void getExecutablePath(char *result) { char *p; // chop off the name of the executable for (p = result + (numberOfChars - 1); p >= result; p--) { + #if os_WINDOWS + if (*p == '\\') { + #else if (*p == '/') { + #endif p[1] = 0; break; } @@ -146,7 +182,14 @@ static void *openLibrary(char *path) { log_println("openLibrary(\"%s\")", path); } #endif +#if !os_WINDOWS void *result = dlopen(path, RTLD_LAZY); +#else + void *result = LoadLibraryA(path); + if (result==NULL) { + sprintf(last_dl_error, "dl function : LoadLibraryA error code : %lu", GetLastError ()); + } +#endif #if log_LINKER char* errorMessage = dlerror(); if (path == NULL) { @@ -162,8 +205,16 @@ static void *openLibrary(char *path) { } static void* loadSymbol(void* handle, const char* symbol) { + #if os_WINDOWS + void* result = GetProcAddress(handle, symbol); + if (!result) { + sprintf(last_dl_error, "dl function : GetProcAddress error code : %lu", GetLastError ()); + + } + #else void* result = dlsym(handle, symbol); -#if log_LINKER + #endif +#if log_LINKER //NOT IMPLEMENTED FOR WINDOWS, you can get info using the dlerror() function we defined #if os_MAXVE log_println("loadSymbol(%p, \"%s\") = %p", handle, symbol, result); #else @@ -183,7 +234,7 @@ static void* loadSymbol(void* handle, const char* symbol) { return result; } -#if os_DARWIN || os_SOLARIS || os_LINUX +#if os_DARWIN || os_SOLARIS || os_LINUX #include #include @@ -194,7 +245,7 @@ static void* loadSymbol(void* handle, const char* symbol) { #if os_DARWIN #include -#elif os_LINUX +#elif os_LINUX #include #elif os_SOLARIS #define _STRUCTURED_PROC 1 /* Use new definitions in procfs.h instead of those in procfs_old.h */ @@ -215,7 +266,7 @@ void debugger_initialize() { char *port = getenv("MAX_AGENT_PORT"); if (port != NULL) { -#if os_LINUX && defined(PR_SET_PTRACER) +#if (os_LINUX ) && defined(PR_SET_PTRACER) /* See info about PR_SET_PTRACER at https://wiki.ubuntu.com/Security/Features#ptrace */ char *val = getenv("MAX_AGENT_PID"); if (val == NULL) { @@ -269,7 +320,7 @@ void debugger_initialize() { #if log_TELE log_println("Stopping VM for debugger"); #endif -#if os_DARWIN || os_LINUX +#if os_DARWIN || os_LINUX || os_WINDOWS kill(getpid(), SIGTRAP); #elif os_SOLARIS int ctlfd = open("/proc/self/ctl", O_WRONLY); @@ -284,7 +335,7 @@ void debugger_initialize() { } } #else -#define debugger_initialize() +#define debugger_initialize() //not implemented for WINDOWS #endif /** @@ -293,6 +344,9 @@ void debugger_initialize() { typedef jint (*VMRunMethod)(Address tlBlock, int tlBlockSize, Address bootHeapRegionStart, void *openLibrary(char *), void *dlsym(void *, const char *), char *dlerror(void), void* vmInterface, JNIEnv jniEnv, void *jmmInterface, void *jvmtiInterface, int argc, char *argv[]); +#if os_WINDOWS +__declspec(dllexport) +#endif int maxine(int argc, char *argv[], char *executablePath) { VMRunMethod method; int exitCode = 0; @@ -341,6 +395,13 @@ int maxine(int argc, char *argv[], char *executablePath) { Address tlBlock = threadLocalsBlock_create(PRIMORDIAL_THREAD_ID, 0, 0); NativeThreadLocals ntl = NATIVE_THREAD_LOCALS_FROM_TLBLOCK(tlBlock); +#if os_WINDOWS +char *dlerror(){ + + + return last_dl_error; +} +#endif #if log_LOADER log_println("entering Java by calling MaxineVM.run(tlBlock=%p, bootHeapRegionStart=%p, openLibrary=%p, dlsym=%p, dlerror=%p, vmInterface=%p, jniEnv=%p, jmmInterface=%p, jvmtiInterface=%p, argc=%d, argv=%p)", @@ -405,8 +466,12 @@ void core_dump() { log_print("dumping core....\n heap @ "); log_print_symbol(image_heap()); log_print_newline(); + #if os_WINDOWS + raise(SIGABRT); + #else // Use kill instead of abort so the vm process keeps running after the core is created. kill(getpid(), SIGABRT); + #endif sleep(3); #endif } @@ -444,6 +509,23 @@ void *native_properties(void) { } #if os_MAXVE maxve_native_props(&nativeProperties); +#elif os_WINDOWS + + nativeProperties.user_name = malloc(MAX_PATH_LENGTH); + nativeProperties.user_dir = malloc(MAX_PATH_LENGTH); + nativeProperties.user_home = malloc(MAX_PATH_LENGTH); + + DWORD size = MAX_PATH_LENGTH; + GetUserNameA(nativeProperties.user_name, &size); + size = MAX_PATH_LENGTH; + char * tmp; + SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, (WCHAR **) &tmp); //Unfortunately, windows return home dir only in Unicode (Wide) format, not ANSI + nativeProperties.user_home = (char*) _wcsdup((const wchar_t * ) tmp); + CoTaskMemFree(tmp); //SHGetKnownFolderPath allocated that space and it is our responsibility to free it + GetCurrentDirectory(MAX_PATH_LENGTH, nativeProperties.user_dir); +//CAUTION nativeProperties.user_home contains the path in Unicode format so it cannot be printed with %s but rather with %ls using printf + + #else /* user properties */ { diff --git a/com.oracle.max.vm.native/substrate/maxine.h b/com.oracle.max.vm.native/substrate/maxine.h index 64df50d182..76ef87f53d 100644 --- a/com.oracle.max.vm.native/substrate/maxine.h +++ b/com.oracle.max.vm.native/substrate/maxine.h @@ -27,7 +27,7 @@ extern jlong native_nanoTime(void); extern jlong native_currentTimeMillis(void); extern void *native_executablePath(void); -extern void native_exit(int code); +extern void native_exit(jint code); extern void *native_environment(void); extern int maxine(int argc, char *argv[], char *executablePath); diff --git a/com.oracle.max.vm.native/substrate/memory.c b/com.oracle.max.vm.native/substrate/memory.c index 542f654493..1849aaa863 100644 --- a/com.oracle.max.vm.native/substrate/memory.c +++ b/com.oracle.max.vm.native/substrate/memory.c @@ -19,9 +19,13 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "os.h" - +#if !os_WINDOWS #include #include +#else +#include +#endif + #include #include diff --git a/com.oracle.max.vm.native/substrate/signal.c b/com.oracle.max.vm.native/substrate/signal.c index 9813304e5c..f07eb5cea2 100644 --- a/com.oracle.max.vm.native/substrate/signal.c +++ b/com.oracle.max.vm.native/substrate/signal.c @@ -24,6 +24,10 @@ /** * Native functions for SignalDispatcher.java. */ +#include "os.h" +#if os_WINDOWS +#include +#endif #include #include #include @@ -32,7 +36,9 @@ #include "threads.h" #include "log.h" -#if os_DARWIN +#if os_WINDOWS +static HANDLE signal_sem; +#elif os_DARWIN #include static semaphore_t signal_sem; #elif os_SOLARIS @@ -43,11 +49,11 @@ static semaphore_t signal_sem; #define sem_destroy sema_destroy #define sem_t sema_t static sem_t signal_sem; -#elif os_LINUX +#elif os_MAXVE +#else #include static sem_t signal_sem; -#elif os_MAXVE -// no signals, so nothing necessary + #endif boolean traceSignals = false; @@ -69,10 +75,15 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalNotify(JNIEnv *env, jcl if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_signal failed: %s", mach_error_string(kr)); } -#elif os_LINUX || os_SOLARIS +#elif os_LINUX || os_SOLARIS if (sem_post(&signal_sem) != 0) { log_exit(11, "sem_post failed: %s", strerror(errno)); } +#elif os_WINDOWS + if(!ReleaseSemaphore(signal_sem, 1, NULL)) + log_exit(GetLastError(), "ReleaseSemaphore failed"); + + #elif os_MAXVE #else c_UNIMPLEMENTED(); @@ -113,13 +124,18 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalWait(JNIEnv *env, jclas if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_wait failed: %s", mach_error_string(kr)); } -#elif os_LINUX || os_SOLARIS +#elif os_LINUX || os_SOLARIS int ret; - while ((ret = sem_wait(&signal_sem) == EINTR)) { + while ((ret = sem_wait(&signal_sem) == EINTR)) { //not sure if EINTR can occur on Windows (No sending signals is supported } if (ret != 0) { log_exit(11, "sem_wait failed: %s", strerror(errno)); } +#elif os_WINDOWS + if ( WaitForSingleObject(signal_sem,INFINITE) == WAIT_FAILED) + log_exit(GetLastError(), "WaitForSingleObject failed:"); + + #elif os_MAXVE #else c_UNIMPLEMENTED(); @@ -139,10 +155,13 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalInit(JNIEnv *env, jclas if (kr != KERN_SUCCESS) { log_exit(11, "semaphore_create failed: %s", mach_error_string(kr)); } -#elif os_LINUX +#elif os_LINUX if (sem_init(&signal_sem, 0, 0) != 0) { log_exit(11, "sem_init failed: %s", strerror(errno)); } +#elif os_WINDOWS + signal_sem = CreateSemaphoreA(NULL, 1, 50000,NULL); //Windows Semaphore needs to have initial val 1 not 0 like Linux. If it was 0 no thread could enter +//Unfortunately, Windows Semaphores need a maximum value representing how many can enter it so we use a random big value (50000) #elif os_SOLARIS if (sem_init(&signal_sem, 0, USYNC_THREAD, NULL) != 0) { log_exit(11, "sema_init failed: %s", strerror(errno)); @@ -176,6 +195,8 @@ Java_com_sun_max_vm_runtime_SignalDispatcher_nativeSignalFinalize(JNIEnv *env, j if (sem_destroy(&signal_sem) != 0) { log_exit(11, "sema_destroy failed: %s", strerror(errno)); } +#elif os_WINDOWS + CloseHandle(signal_sem); #endif } diff --git a/com.oracle.max.vm.native/substrate/sync.c b/com.oracle.max.vm.native/substrate/sync.c index bb6f59e38c..d0f4af3ead 100644 --- a/com.oracle.max.vm.native/substrate/sync.c +++ b/com.oracle.max.vm.native/substrate/sync.c @@ -18,6 +18,10 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "os.h" +#if os_WINDOWS +#include +#endif #include #include @@ -26,7 +30,6 @@ #include "log.h" #include "jni.h" #include "mutex.h" -#include "os.h" #include "word.h" #include "threads.h" diff --git a/com.oracle.max.vm.native/substrate/threads.c b/com.oracle.max.vm.native/substrate/threads.c index 6d82a2491b..3717429596 100644 --- a/com.oracle.max.vm.native/substrate/threads.c +++ b/com.oracle.max.vm.native/substrate/threads.c @@ -19,11 +19,16 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include "os.h" -#include +#if (!os_WINDOWS) + #include +#else + #include +#endif #include -#include "os.h" #include "isa.h" #include "virtualMemory.h" @@ -41,8 +46,9 @@ #include "trap.h" #include "threads.h" #include "threadLocals.h" +#if !os_WINDOWS #include - +#endif #if (os_DARWIN || os_LINUX) # include # include @@ -56,6 +62,16 @@ # include "maxve.h" typedef maxve_Thread Thread; #define thread_current() (maxve_get_current()) + +#elif os_WINDOWS + + #include + #include + #include + #include + typedef HANDLE Thread; +#define thread_current() ((Thread) GetCurrentThread()) + #endif #if log_NUMA_THREADS @@ -114,6 +130,20 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { } pthread_attr_destroy(&attr); +#elif os_WINDOWS + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + + NT_TIB *tib = (NT_TIB*)NtCurrentTeb(); + *stackBase = (DWORD_PTR)tib->StackBase - systemInfo.dwPageSize ; //In windows, guard size is always one memory page so we remove it from stacksize. + + + MEMORY_BASIC_INFORMATION mbi = {0}; + if (VirtualQuery((LPCVOID)(stackBase ), &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0) //we use virtualquery to get windows reserved stack size (not committed). + { + DWORD_PTR allocationStart = (DWORD_PTR)mbi.AllocationBase; + *stackSize = (size_t) stackBase - allocationStart; + } #elif os_DARWIN pthread_t self = pthread_self(); void *stackTop = pthread_get_stackaddr_np(self); @@ -146,7 +176,7 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { */ static Thread thread_create(jint id, Size stackSize, int priority) { Thread thread; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS int error; #endif @@ -158,8 +188,10 @@ static Thread thread_create(jint id, Size stackSize, int priority) { #if log_THREADS log_println("thread_create: id = %d, stack size = %ld", id, stackSize); #endif - -#if (os_LINUX || os_DARWIN) +#if os_WINDOWS +#define PTHREAD_STACK_MIN 0 +#endif +#if (os_LINUX || os_DARWIN ) if (stackSize < PTHREAD_STACK_MIN) { stackSize = PTHREAD_STACK_MIN; } @@ -184,7 +216,7 @@ static Thread thread_create(jint id, Size stackSize, int priority) { if (thread == NULL) { return (Thread) 0; } -#elif (os_LINUX || os_DARWIN) +#elif (os_LINUX || os_DARWIN ) pthread_attr_t attributes; pthread_attr_init(&attributes); @@ -200,6 +232,15 @@ static Thread thread_create(jint id, Size stackSize, int priority) { log_println("pthread_create failed with error: %d", error); return (Thread) 0; } +#elif (os_WINDOWS) + thread = CreateThread(NULL, stackSize, thread_run, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL); //we demand explicitly stack size to be reservedd + //Also guard is set automatically + if(!thread){ + log_println("thread_create failed with error: %d", GetLastError()); + return (Thread) 0; + } + //the only way to make thread detached is to invalidate its handle using CloseHandle(). However, this would result in returning an invalid Thread at the end of the function + #elif os_SOLARIS if (stackSize < thr_min_stack()) { stackSize = thr_min_stack(); @@ -226,7 +267,13 @@ void *thread_self() { * * @param arg the pre-allocated, but uninitialized, thread locals block. */ -void *thread_run(void *arg) { + #if os_WINDOWS +DWORD WINAPI thread_run(void *arg) //we prefer this signature in order to avoid compiler waring on Windows. + + #else +void * thread_run(void *arg) +#endif + { Address tlBlock = (Address) arg; TLA etla = ETLA_FROM_TLBLOCK(tlBlock); @@ -307,7 +354,11 @@ void *thread_run(void *arg) { setCurrentThreadSignalMaskOnThreadExit(result == 1); /* Successful thread exit */ - return NULL; + #if os_WINDOWS + return 0; + #else + return NULL; + #endif } /** @@ -478,10 +529,12 @@ Java_com_sun_max_vm_thread_VmThread_nativeYield(JNIEnv *env, jclass c) { thr_yield(); #elif os_DARWIN sched_yield(); -#elif os_LINUX +#elif os_LINUX pthread_yield(); #elif os_MAXVE maxve_yield(); +#elif os_WINDOWS + SwitchToThread(); #else c_UNIMPLEMENTED(); #endif @@ -504,7 +557,7 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre log_exit(11, "Error sending signal SIGUSR1 to native thread %p", nativeThread); } } -#elif os_LINUX || os_DARWIN +#elif os_LINUX || os_DARWIN // Signals the thread int result = pthread_kill((pthread_t) nativeThread, SIGUSR1); if (result != 0) { @@ -517,7 +570,12 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre } } #elif os_MAXVE + maxve_interrupt((void*) nativeThread); +#elif os_WINDOWS + c_UNIMPLEMENTED(); + + #else c_UNIMPLEMENTED(); #endif @@ -526,6 +584,20 @@ Java_com_sun_max_vm_thread_VmThread_nativeInterrupt(JNIEnv *env, jclass c, Addre jboolean thread_sleep(jlong numberOfMilliSeconds) { #if os_MAXVE return maxve_sleep(numberOfMilliSeconds * 1000000); +#elif os_WINDOWS +HANDLE timer; +LARGE_INTEGER li; +if(!(timer = CreateWaitableTimer(NULL, TRUE, NULL))) + return FALSE; + +li.QuadPart = -(numberOfMilliSeconds * 1000000); +if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)){ + CloseHandle(timer); + return FALSE; + } + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); + return TRUE; #else struct timespec time, remainder; diff --git a/com.oracle.max.vm.native/substrate/time.c b/com.oracle.max.vm.native/substrate/time.c index 60e90b0d39..06eb634748 100644 --- a/com.oracle.max.vm.native/substrate/time.c +++ b/com.oracle.max.vm.native/substrate/time.c @@ -21,15 +21,47 @@ #include "os.h" #include "jni.h" #include "maxine.h" - #include -#include +#if !os_WINDOWS +#include //MINGW may contain this file but it is not officially part of WINAPI so other SDKs (eg. Visual Studio do not include it) +#endif #if os_DARWIN #include #include #elif os_LINUX #include +#elif os_WINDOWS +#include +#include +int gettimeofday(struct timeval * tp) +{ + // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's + // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) + // until 00:00:00 January 1, 1970 + static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); + + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; + + GetSystemTime( &system_time ); + SystemTimeToFileTime( &system_time, &file_time ); + time = ((uint64_t)file_time.dwLowDateTime ) ; + time += ((uint64_t)file_time.dwHighDateTime) << 32; + + tp->tv_sec = (long) ((time - EPOCH) / 10000000L); + tp->tv_usec = (long) (system_time.wMilliseconds * 1000); + return 0; +} + +int clock_gettime(int x, struct timespec *spec) +{ __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); + wintime -=(int64_t)116444736000000000; //1jan1601 to 1jan1970 + spec->tv_sec =wintime / (int64_t)10000000; //seconds + spec->tv_nsec =wintime % (int64_t)10000000 *100; //nano-seconds + return 0; +} #endif @@ -69,7 +101,7 @@ jlong native_nanoTime(void) { struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)tv.tv_sec * (uint64_t)(1000 * 1000 * 1000) + (uint64_t)(tv.tv_usec * 1000); -#elif os_LINUX +#elif os_LINUX #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC (1) @@ -119,15 +151,24 @@ jlong native_nanoTime(void) { c_ASSERT(status != -1); jlong usecs = ((jlong) time.tv_sec) * (1000 * 1000) + (jlong) time.tv_usec; return 1000 * usecs; +#elif os_WINDOWS + struct timespec time; + clock_gettime(1, &time); + return ((jlong)time.tv_sec) * (1000 * 1000 * 1000) + (jlong) time.tv_nsec; +//NOT 100% TESTED #else return 1; #endif } jlong native_currentTimeMillis(void) { -#if os_SOLARIS || os_DARWIN || os_LINUX +#if os_SOLARIS || os_DARWIN || os_LINUX || os_WINDOWS struct timeval tv; + #if os_WINDOWS + gettimeofday(&tv); + #else gettimeofday(&tv, NULL); + #endif // we need to cast to jlong to avoid overflows in ARMv7 return ((jlong) tv.tv_sec * 1000) + ((jlong) tv.tv_usec / 1000); #else diff --git a/com.oracle.max.vm.native/substrate/trap.c b/com.oracle.max.vm.native/substrate/trap.c index 3030b388ae..7501e780fe 100644 --- a/com.oracle.max.vm.native/substrate/trap.c +++ b/com.oracle.max.vm.native/substrate/trap.c @@ -19,13 +19,15 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - +#include "os.h" +#if os_WINDOWS +#include +#endif #include "c.h" #include "threads.h" #include "virtualMemory.h" #include "log.h" #include "jni.h" -#include "os.h" #include "isa.h" #include "image.h" #include "trap.h" @@ -49,7 +51,7 @@ static Address theJavaTrapStub; static boolean traceTraps = false; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS //Windows do not support POSIX signals unfortunately. You can only raise some signals from within your own process/thread but not send it to another process/thread /** * All signals. @@ -77,13 +79,13 @@ static sigset_t blockedOnThreadExitSignals; int getTrapNumber(int signal) { switch (signal) { case SIGSEGV: -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS case SIGBUS: #endif return MEMORY_FAULT; case SIGFPE: return ARITHMETIC_EXCEPTION; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS case SIGUSR1: return ASYNC_INTERRUPT; default: @@ -96,12 +98,12 @@ int getTrapNumber(int signal) { #if os_SOLARIS #include #define thread_setSignalMask thr_sigsetmask -#elif os_DARWIN || os_LINUX +#elif os_DARWIN || os_LINUX #define thread_setSignalMask pthread_sigmask #endif void setCurrentThreadSignalMaskOnThreadExit(boolean isVmOperationThread) { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS if (!isVmOperationThread) { /* disable signals sent by Thread.interrupt() as thread is transitioning to not alive state. */ thread_setSignalMask(SIG_BLOCK, &blockedOnThreadExitSignals, NULL); @@ -110,7 +112,7 @@ void setCurrentThreadSignalMaskOnThreadExit(boolean isVmOperationThread) { } void setCurrentThreadSignalMask(boolean isVmOperationThread) { -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS if (isVmOperationThread) { thread_setSignalMask(SIG_SETMASK, &vmAndDefaultSignals, NULL); } else { @@ -120,9 +122,12 @@ void setCurrentThreadSignalMask(boolean isVmOperationThread) { #endif } -void* setSignalHandler(int signal, SignalHandlerFunction handler) { +void* setSignalHandler(int sig, SignalHandlerFunction handler) { //Changed 'signal' argument to 'sig' because it overlapped with windows signal() function #if os_MAXVE - maxve_register_fault_handler(signal, handler); + maxve_register_fault_handler(sig, handler); + return NULL; +#elif os_WINDOWS + signal(sig, handler); return NULL; #else struct sigaction newSigaction; @@ -132,14 +137,14 @@ void* setSignalHandler(int signal, SignalHandlerFunction handler) { sigemptyset(&newSigaction.sa_mask); newSigaction.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK; -#if os_SOLARIS || os_LINUX || os_DARWIN - if (signal == SIGUSR1) { +#if os_SOLARIS || os_LINUX || os_DARWIN + if (sig == SIGUSR1) { newSigaction.sa_flags = SA_SIGINFO | SA_ONSTACK; } #endif newSigaction.sa_sigaction = handler; - if (sigaction(signal, &newSigaction, &oldSigaction) != 0) { + if (sigaction(sig, &newSigaction, &oldSigaction) != 0) { log_exit(1, "sigaction failed"); } @@ -147,7 +152,7 @@ void* setSignalHandler(int signal, SignalHandlerFunction handler) { log_lock(); log_print("Registered handler %p [", handler); log_print_symbol((Address) handler); - log_print("] for signal %d", signal); + log_print("] for signal %d", sig); if (oldSigaction.sa_handler != NULL) { log_print(" replacing handler "); log_print_symbol((Address) oldSigaction.sa_handler); @@ -163,7 +168,7 @@ void* setSignalHandler(int signal, SignalHandlerFunction handler) { static Address getInstructionPointer(UContext *ucontext) { #if os_SOLARIS return ucontext->uc_mcontext.gregs[REG_PC]; -#elif os_LINUX +#elif os_LINUX # if isa_AMD64 return ucontext->uc_mcontext.gregs[REG_RIP]; # elif isa_IA32 @@ -179,6 +184,10 @@ static Address getInstructionPointer(UContext *ucontext) { return ucontext->uc_mcontext->__ss.__rip; #elif os_MAXVE return ucontext->rip; +#elif os_WINDOWS +#if isa_AMD64 + return ucontext->Rip; + #endif #else c_UNIMPLEMENTED(); #endif @@ -192,7 +201,7 @@ static void setInstructionPointer(UContext *ucontext, Address stub) { ucontext->uc_mcontext.gregs[REG_PC] = (greg_t) stub; #elif os_DARWIN ucontext->uc_mcontext->__ss.__rip = stub; -#elif os_LINUX +#elif os_LINUX # if isa_AMD64 ucontext->uc_mcontext.gregs[REG_RIP] = (greg_t) stub; # elif isa_IA32 @@ -206,15 +215,19 @@ static void setInstructionPointer(UContext *ucontext, Address stub) { # endif #elif os_MAXVE ucontext->rip = (unsigned long) stub; +#elseif os_WINDOWS +# if isa_AMD64 + ucontext->uc_mcontext.rip = (greg_t) stub; + #endif #else c_UNIMPLEMENTED(); #endif } -static Address getFaultAddress(SigInfo * sigInfo, UContext *ucontext) { +static Address getFaultAddress(SigInfo * sigInfo, UContext *ucontext) { //there is no siginfo_t struct in Windows #if (os_DARWIN || os_SOLARIS || os_LINUX ) return (Address) sigInfo->si_addr; -#elif (os_MAXVE) +#elif (os_MAXVE) || os_WINDOWS return (Address) sigInfo; #endif } @@ -228,7 +241,7 @@ char *vmSignalName(int signal) { case SIGSEGV: return "SIGSEGV"; case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS case SIGUSR1: return "SIGUSR1"; case SIGBUS: return "SIGBUS"; #endif @@ -269,12 +282,15 @@ static boolean handleDivideOverflow(UContext *ucontext) { if (rip[0] == 0xf7) { #if os_SOLARIS Address dividend = ucontext->uc_mcontext.gregs[REG_RAX]; -#elif os_LINUX +#elif os_LINUX Address dividend = ucontext->uc_mcontext.gregs[REG_RAX]; #elif os_DARWIN Address dividend = ucontext->uc_mcontext->__ss.__rax; #elif os_MAXVE Address dividend = ucontext->rax; +#elif os_WINDOWS + Address dividend = ucontext->Rax; + #else c_UNIMPLEMENTED(); #endif @@ -294,12 +310,15 @@ static boolean handleDivideOverflow(UContext *ucontext) { /* Set the remainder to 0. */ #if os_SOLARIS ucontext->uc_mcontext.gregs[REG_RDX] = 0; -#elif os_LINUX +#elif os_LINUX ucontext->uc_mcontext.gregs[REG_RDX] = 0; #elif os_DARWIN ucontext->uc_mcontext->__ss.__rdx = 0; #elif os_MAXVE ucontext->rdx = 0; +#elif os_WINDOWS + ucontext->Rdx = 0; + #else c_UNIMPLEMENTED(); #endif @@ -446,6 +465,9 @@ static void vmSignalHandler(int signal, SigInfo *signalInfo, UContext *ucontext) #elif isa_AMD64 && (os_SOLARIS || os_LINUX) tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->uc_mcontext.gregs[REG_R14]); ucontext->uc_mcontext.gregs[REG_R14] = (Address) dtla; +#elif isa_AMD64 && os_WINDOWS + tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->R14); + ucontext->R14 = (Address) dtla; #elif isa_AMD64 && os_DARWIN tla_store3(dtla, TRAP_LATCH_REGISTER, ucontext->uc_mcontext->__ss.__r14); ucontext->uc_mcontext->__ss.__r14 = (Address) dtla; @@ -471,11 +493,17 @@ static void vmSignalHandler(int signal, SigInfo *signalInfo, UContext *ucontext) /** * The handler for signals handled by SignalDispatcher.java. */ + #if os_WINDOWS + static void userSignalHandlerDef(int signal) { + void postSignal(int signal); + postSignal(signal); +} +#else static void userSignalHandlerDef(int signal, SigInfo *signalInfo, UContext *ucontext) { void postSignal(int signal); postSignal(signal); } - +#endif /* Defined global declared in trap.h */ SignalHandlerFunction userSignalHandler = (SignalHandlerFunction) userSignalHandlerDef; @@ -491,7 +519,7 @@ void nativeTrapInitialize(Address javaTrapStub) { setSignalHandler(SIGILL, (SignalHandlerFunction) vmSignalHandler); setSignalHandler(SIGFPE, (SignalHandlerFunction) vmSignalHandler); -#if !os_MAXVE +#if !os_MAXVE && !os_WINDOWS //no support for windows signals setSignalHandler(SIGBUS, (SignalHandlerFunction) vmSignalHandler); setSignalHandler(SIGUSR1, (SignalHandlerFunction) vmSignalHandler); diff --git a/com.oracle.max.vm.native/substrate/trap.h b/com.oracle.max.vm.native/substrate/trap.h index 620a4b9afe..990f1a582a 100644 --- a/com.oracle.max.vm.native/substrate/trap.h +++ b/com.oracle.max.vm.native/substrate/trap.h @@ -29,14 +29,22 @@ # include # include # include -# include +#if (!os_WINDOWS) + # include # include -#endif +#endif +#endif #include "os.h" -#if os_MAXVE +#if os_MAXVE #define SignalHandlerFunction fault_handler_t +#elif os_WINDOWS +typedef void SigInfo; + +typedef void (*SignalHandlerFunction)(int signal); //Windows want a signal handler with one argument (Remember, Windows do not support POSIX signals. They can only be used as exceptions raised from within the same process. You cannot send them to other threads/ procs) + +typedef CONTEXT UContext; #else typedef ucontext_t UContext; typedef siginfo_t SigInfo; diff --git a/com.oracle.max.vm.native/substrate/vm.h b/com.oracle.max.vm.native/substrate/vm.h index 880df618d4..8a4da41eed 100644 --- a/com.oracle.max.vm.native/substrate/vm.h +++ b/com.oracle.max.vm.native/substrate/vm.h @@ -36,6 +36,10 @@ * A set of VM functions implemented in Java that can (only) be called from C code. * These are defined in VMFunctionsSource.java. */ + #include "os.h" + #if os_WINDOWS + #undef GetClassName + #endif //Microsoft defines GetClassName as GetClassNameA in some header files which breaks our code typedef struct vmInterface_ { // START GENERATED CODE void (JNICALL *Unimplemented) (JNIEnv *env); From 9d92a321888c379ac2274ea60c51a96ea4d38fcf Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Tue, 14 Jul 2020 21:26:14 +0300 Subject: [PATCH 06/17] Fixed com.sun.max.config.jdk.Package constructor (Windows) Fixed com.sun.max.config.jdk.Package constructor. We avoid resetting any field in java.lang.UNIXProcess when running on Windows. Attempting to load java.lang.UNIX on Windows caused NoClassDefFoundError when we tried to load com.sun.max.config.jdk.Package class during image generation. As a result problematic classed were not added to Compilation Blacklist and many unexplainable compilation errors were emerging --- com.sun.max/src/com/sun/max/config/jdk/Package.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/com.sun.max/src/com/sun/max/config/jdk/Package.java b/com.sun.max/src/com/sun/max/config/jdk/Package.java index e69b0759cc..1d9dddffc9 100644 --- a/com.sun.max/src/com/sun/max/config/jdk/Package.java +++ b/com.sun.max/src/com/sun/max/config/jdk/Package.java @@ -31,6 +31,8 @@ import com.sun.max.vm.actor.member.*; import com.sun.max.vm.hosted.*; import com.sun.max.vm.jdk.*; +import static com.sun.max.platform.Platform.*; +import com.sun.max.platform.*; /** * Redirection for the standard set of JDK packages to include in the image. @@ -150,8 +152,11 @@ public Package() { if (JDK.JDK_VERSION == JDK.JDK_8) { Extensions.resetField("java.lang.invoke.MethodHandles$Lookup", "LOOKASIDE_TABLE"); Extensions.registerClassForReInit("java.lang.invoke.MethodHandles$Lookup"); - Extensions.resetField("java.lang.UNIXProcess", "processReaperExecutor"); - Extensions.registerClassForReInit("java.lang.UNIXProcess"); + + if(platform().os != OS.WINDOWS ){ + Extensions.resetField("java.lang.UNIXProcess", "processReaperExecutor"); + Extensions.registerClassForReInit("java.lang.UNIXProcess"); + } Extensions.resetField("java.io.File", "fs"); Extensions.registerClassForReInit("java.io.File"); @@ -170,11 +175,11 @@ public Package() { */ @Override public void loading() { + if (loadingDone) { return; } loadingDone = true; - // Classes that must not be in the boot image for various reasons HostedBootClassLoader.omitClass(java.io.File.class.getName() + "$LazyInitialization"); HostedBootClassLoader.omitClass(java.io.File.class.getName() + "$TempDirectory"); From 6a8734e50d09d0393761c314595d05bb8aa4d84b Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Tue, 14 Jul 2020 23:25:09 +0300 Subject: [PATCH 07/17] Added WINDOWS case at some Java OS specific codes --- com.sun.max/src/com/sun/max/platform/Platform.java | 2 +- .../src/com/sun/max/vm/compiler/target/RegisterConfigs.java | 2 +- com.sun.max/src/com/sun/max/vm/heap/HeapSchemeAdaptor.java | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/com.sun.max/src/com/sun/max/platform/Platform.java b/com.sun.max/src/com/sun/max/platform/Platform.java index 7c10fe9514..6e3a6a4d9b 100644 --- a/com.sun.max/src/com/sun/max/platform/Platform.java +++ b/com.sun.max/src/com/sun/max/platform/Platform.java @@ -142,7 +142,7 @@ private CiTarget createTarget() { if (os == OS.DARWIN) { // Darwin requires 16-byte stack frame alignment. stackAlignment = 16; - } else if (os == OS.SOLARIS || os == OS.LINUX) { + } else if (os == OS.SOLARIS || os == OS.LINUX || os == OS.WINDOWS) { // Linux apparently also requires it for functions that pass floating point functions on the stack. // One such function in the Maxine code base is log_print_float() in log.c which passes a float // value to fprintf on the stack. However, gcc doesn't fix the alignment itself so we simply diff --git a/com.sun.max/src/com/sun/max/vm/compiler/target/RegisterConfigs.java b/com.sun.max/src/com/sun/max/vm/compiler/target/RegisterConfigs.java index ef9a9dcb58..7e6faba0ce 100644 --- a/com.sun.max/src/com/sun/max/vm/compiler/target/RegisterConfigs.java +++ b/com.sun.max/src/com/sun/max/vm/compiler/target/RegisterConfigs.java @@ -188,7 +188,7 @@ public static RegisterConfigs create() { return new RegisterConfigs(standard, n2j, trampoline, template, compilerStub, uncommonTrapStub, trapStub); } } else if (platform().isa == ISA.AMD64) { - if (os == OS.LINUX || os == OS.SOLARIS || os == OS.DARWIN || os == OS.MAXVE) { + if (os == OS.LINUX || os == OS.SOLARIS || os == OS.DARWIN || os == OS.MAXVE || os == OS.WINDOWS) { allocatable = new CiRegister[] {rax, rcx, rdx, rbx, rsi, rdi, com.oracle.max.asm.target.amd64.AMD64.r8, com.oracle.max.asm.target.amd64.AMD64.r9, com.oracle.max.asm.target.amd64.AMD64.r10, com.oracle.max.asm.target.amd64.AMD64.r12, com.oracle.max.asm.target.amd64.AMD64.r13, com.oracle.max.asm.target.amd64.AMD64.r15, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15}; diff --git a/com.sun.max/src/com/sun/max/vm/heap/HeapSchemeAdaptor.java b/com.sun.max/src/com/sun/max/vm/heap/HeapSchemeAdaptor.java index 9a29cb6c9f..edf60a7723 100644 --- a/com.sun.max/src/com/sun/max/vm/heap/HeapSchemeAdaptor.java +++ b/com.sun.max/src/com/sun/max/vm/heap/HeapSchemeAdaptor.java @@ -215,6 +215,7 @@ public CodeManager createCodeManager() { case LINUX: case MAXVE: case DARWIN: + case WINDOWS: case SOLARIS: { // If you change this for any platform above, you may also want to revisit reservedVirtualSpaceSize, // bootRegionMappingConstraint and the native implementation of mapHeapAndCode. From b84facf623f1c2ccb83db58929cc232ea789114b Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Wed, 15 Jul 2020 07:01:59 +0300 Subject: [PATCH 08/17] Improved some Makefiles for Windows case -makefile omits Tele build on Windows -launch.mk uses "maxvm.exe" instead of bare "maxvm" (some cp (copy) implementations for Windows need the extension while others do not). -javatest.mk uses more source files for javatest.dll on Windows because Windows do not allow undefined references in DLLs. However, if not on Windows, we use the default source files -platform.mk we assign OS = windows when uname returns not only "WindowsNT" but if it also includes "MINGW" inside it. --- com.oracle.max.vm.native/javatest/javatest.mk | 7 +++++-- com.oracle.max.vm.native/launch/launch.mk | 4 ++++ com.oracle.max.vm.native/makefile | 7 ++++++- com.oracle.max.vm.native/platform/platform.mk | 7 +++++-- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/com.oracle.max.vm.native/javatest/javatest.mk b/com.oracle.max.vm.native/javatest/javatest.mk index 7a92b47a1a..7890bf514a 100644 --- a/com.oracle.max.vm.native/javatest/javatest.mk +++ b/com.oracle.max.vm.native/javatest/javatest.mk @@ -27,8 +27,11 @@ LIB = javatest include $(PROJECT)/platform/platform.mk -SOURCES = jvmni.c tests.c threads.c jnitests.c jvm.c jni.c threadLocals.c image.c log.c virtualMemory.c mutex.c c.c trap.c time.c jmm.c jvmti.c relocation.c signal.c dataio.c - +ifeq ($(OS),windows) + SOURCES = jvmni.c tests.c threads.c jnitests.c jvm.c jni.c threadLocals.c image.c log.c virtualMemory.c mutex.c c.c trap.c time.c jmm.c jvmti.c relocation.c signal.c dataio.c +else + SOURCES = jvmni.c tests.c threads.c jnitests.c +endif SOURCE_DIRS = javatest jni platform hosted share substrate include $(PROJECT)/share/share.mk diff --git a/com.oracle.max.vm.native/launch/launch.mk b/com.oracle.max.vm.native/launch/launch.mk index 4624b29373..04c0268ad5 100644 --- a/com.oracle.max.vm.native/launch/launch.mk +++ b/com.oracle.max.vm.native/launch/launch.mk @@ -32,6 +32,10 @@ SOURCES = maxvm.c SOURCE_DIRS = jni platform share substrate launch include $(PROJECT)/platform/platform.mk +ifeq ($(OS),windows) + MAIN = maxvm.exe #some cp implementations for windows require .exe at the end, while other work without it + +endif include $(PROJECT)/share/share.mk all : $(MAIN) diff --git a/com.oracle.max.vm.native/makefile b/com.oracle.max.vm.native/makefile index e5c253f008..1689f20130 100644 --- a/com.oracle.max.vm.native/makefile +++ b/com.oracle.max.vm.native/makefile @@ -27,8 +27,13 @@ # testing, inspecting (browsing, profiling and debugging) and running a Maxine VM. include platform/platform.mk +ifeq ($(OS),windows) + all : hosted substrate launch javatest +else + all : hosted substrate launch javatest tele -all : hosted substrate launch javatest tele + +endif hosted : build/$(OS)/hosted/makefile $(AT) (cd build/$(OS)/hosted; $(MAKE) all) diff --git a/com.oracle.max.vm.native/platform/platform.mk b/com.oracle.max.vm.native/platform/platform.mk index fe15588ab0..6c38e54e86 100644 --- a/com.oracle.max.vm.native/platform/platform.mk +++ b/com.oracle.max.vm.native/platform/platform.mk @@ -55,8 +55,6 @@ ifneq ($(MAIN),) TARGET := LAUNCH endif -OS := windows -ISA := amd64 # HOSTOS is the platform we are compiling on HOSTOS = $(shell uname -s) # TARGETOS is the platform we are compiling for (usually the same as HOSTOS) @@ -157,6 +155,11 @@ endif ifeq ($(TARGETOS),WindowsNT) OS := windows ISA := amd64 +else + ifeq ($(findstring MINGW,$(TARGETOS)), MINGW) + OS := windows + ISA := amd64 + endif endif # There are three variants for Maxine VE, owing to the 32/64 dom0 variants From f10954463488778379a147d7d4f83f449bfe7504 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Wed, 15 Jul 2020 16:04:01 +0300 Subject: [PATCH 09/17] Minor typo fix in JNI_H_PATH on Windows --- com.oracle.max.vm.native/platform/platform.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.oracle.max.vm.native/platform/platform.mk b/com.oracle.max.vm.native/platform/platform.mk index 6c38e54e86..8ae604e750 100644 --- a/com.oracle.max.vm.native/platform/platform.mk +++ b/com.oracle.max.vm.native/platform/platform.mk @@ -435,7 +435,7 @@ else else ifeq ($(OS),windows) JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/win32/ - JNI_H_PATH = $(JAVA_HOME)/include/win32/jni.h + JNI_H_PATH = $(JAVA_HOME)/include/jni.h else JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS) JNI_H_PATH = $(wildcard $(JAVA_HOME)/include/jni.h) From 226b9b97c6fd8b68a4146da48bb893a0c1d1d5e9 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Wed, 15 Jul 2020 16:30:35 +0300 Subject: [PATCH 10/17] Removed copy-pasted comments --- com.oracle.max.vm.native/platform/platform.mk | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/com.oracle.max.vm.native/platform/platform.mk b/com.oracle.max.vm.native/platform/platform.mk index 8ae604e750..7309157f3e 100644 --- a/com.oracle.max.vm.native/platform/platform.mk +++ b/com.oracle.max.vm.native/platform/platform.mk @@ -325,14 +325,7 @@ ifeq ($(OS),windows) CFLAGS = -g -Wall -Wno-long-long -Wextra -Wno-main -Wno-unused-parameter -fPIC -D_GNU_SOURCE -D$(ISA) -DWINDOWS -D__int64=int64_t -D$(TARGET) -D$(TARGET_WORD_SIZE) $(JDK) $(OTHER_CFLAGS) endif C_DEPENDENCIES_FLAGS = -M -DWINDOWS -D$(ISA) -D$(TARGET) -D$(TARGET_WORD_SIZE) - # The '-rpath' linker option is used so that LD_LIBRARY_PATH does not have to be configured at runtime to - # find Maxine's version of the libjvm.so library. - # The '-z execstack' is a workaround that stops the runtime dynamic linker from - # changing the protection of the main thread's stack (via mprotect) *after* the - # yellow guard page (for detecting stack overflow) has been mprotected. Without - # this flag, the main thread's complete stack (including the guard page) is - # mprotected with PROT_READ, PROT_WRITE, PROT_EXEC when dlopen() is called to - # open libjava.so. + LINK_MAIN = $(CC) -g -Xlinker -rpath -Xlinker $(shell cd $(PROJECT)/generated/$(OS) && /bin/pwd) -o $(MAIN) LINK_LIB = $(CC) -g -shared -mwindows From b14503abc74e8e4aadb81049f35e785ad603e325 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Wed, 15 Jul 2020 21:57:58 +0300 Subject: [PATCH 11/17] Update threads.c --- com.oracle.max.vm.native/substrate/threads.c | 22 ++++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/com.oracle.max.vm.native/substrate/threads.c b/com.oracle.max.vm.native/substrate/threads.c index 3717429596..802fa70f61 100644 --- a/com.oracle.max.vm.native/substrate/threads.c +++ b/com.oracle.max.vm.native/substrate/threads.c @@ -135,15 +135,17 @@ void thread_getStackInfo(Address *stackBase, Size* stackSize) { GetSystemInfo(&systemInfo); NT_TIB *tib = (NT_TIB*)NtCurrentTeb(); - *stackBase = (DWORD_PTR)tib->StackBase - systemInfo.dwPageSize ; //In windows, guard size is always one memory page so we remove it from stacksize. + *stackBase = (DWORD_PTR)tib->StackBase; //On windows, guard size is always one memory page so we remove it from stacksize. MEMORY_BASIC_INFORMATION mbi = {0}; - if (VirtualQuery((LPCVOID)(stackBase ), &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0) //we use virtualquery to get windows reserved stack size (not committed). + if (VirtualQuery((LPCVOID)(*stackBase - systemInfo.dwPageSize ), &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0) //we use virtualquery to get windows reserved stack size (not committed). { DWORD_PTR allocationStart = (DWORD_PTR)mbi.AllocationBase; - *stackSize = (size_t) stackBase - allocationStart; + *stackSize = (size_t) (*stackBase) - allocationStart; } + *stackBase = (DWORD_PTR)mbi.AllocationBase + systemInfo.dwAllocationGranularity; //tib->StackBase is actually the HIGHEST address of the stack, we want the lowest so we use AllocationBase + guard_size + *stackSize -= systemInfo.dwAllocationGranularity;//On windows, guard size is always one memory page so we remove it from stacksize. #elif os_DARWIN pthread_t self = pthread_self(); void *stackTop = pthread_get_stackaddr_np(self); @@ -294,7 +296,6 @@ void * thread_run(void *arg) threadLocalsBlock_create(id, tlBlock, 0); } NativeThreadLocals ntl = NATIVE_THREAD_LOCALS_FROM_TLBLOCK(tlBlock); - /* Grab the global thread lock so that: * 1. This thread can atomically be added to the thread list * 2. This thread is blocked if a GC is currently underway. Once we have the lock, @@ -585,18 +586,7 @@ jboolean thread_sleep(jlong numberOfMilliSeconds) { #if os_MAXVE return maxve_sleep(numberOfMilliSeconds * 1000000); #elif os_WINDOWS -HANDLE timer; -LARGE_INTEGER li; -if(!(timer = CreateWaitableTimer(NULL, TRUE, NULL))) - return FALSE; - -li.QuadPart = -(numberOfMilliSeconds * 1000000); -if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)){ - CloseHandle(timer); - return FALSE; - } - WaitForSingleObject(timer, INFINITE); - CloseHandle(timer); +Sleep(numberOfMilliSeconds); return TRUE; #else struct timespec time, remainder; From a5b8db7f5028d6ab04a8b22840022dc0ec03c2c5 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Wed, 15 Jul 2020 23:46:29 +0300 Subject: [PATCH 12/17] Create memory_map_test.c --- .../windows_tests/memory_map_test.c | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 com.oracle.max.vm.native/windows_tests/memory_map_test.c diff --git a/com.oracle.max.vm.native/windows_tests/memory_map_test.c b/com.oracle.max.vm.native/windows_tests/memory_map_test.c new file mode 100644 index 0000000000..9e94de1703 --- /dev/null +++ b/com.oracle.max.vm.native/windows_tests/memory_map_test.c @@ -0,0 +1,58 @@ +#include + +#include // size_t +#include // uint8_t, uint32_t +#include // printf +#include // Must be included before strsafe.h +#include +#include +// Display the error message corresponding to GetLastError() in a message box. + + uint8_t machine_code[] = {'k', 0xB8, 0x78, 0x56, 0x34, 0x12, 0xC3 }; + +int _tmain(int argc, _TCHAR **argv) { + // Allocate a new page of memory, setting its protections to read+write + LPVOID mem = VirtualAlloc(NULL, sizeof(machine_code), + MEM_COMMIT, PAGE_READWRITE); + if (mem == NULL) { + return 1; + } + + int fd = open("output.txt" , _O_RDWR ); + write( + fd, + machine_code, + sizeof(machine_code)); + _close(fd); + HANDLE open_img_result = CreateFileA( + "output.txt" , + GENERIC_READ | GENERIC_WRITE|GENERIC_EXECUTE , + FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL +); +if (open_img_result == INVALID_HANDLE_VALUE || !open_img_result) + printf("could not open image file: %d" , GetLastError()); + + + HANDLE fmapping = CreateFileMappingA( open_img_result , NULL , PAGE_EXECUTE_READWRITE| SEC_COMMIT ,0u ,0, NULL); + if(!fmapping) + printf("ss %d\n", GetLastError()); + mem = MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE |FILE_MAP_COPY, 0, 0,0, 0); + if(!mem) + printf("dd %d\n", GetLastError()); + + + // Point a function pointer at the newly allocated page, then call it + printf("fff %d \n", sizeof(machine_code)); + mem =mem +1; + uint32_t(*fn)() = (uint32_t(*)()) mem; + uint32_t result = fn(); + _tprintf(TEXT("result = 0x%x\n"), result); + return 0; + + +} + From 1c83562fb77046c109095fee5ad4d13b5a1cc936 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Thu, 16 Jul 2020 00:06:19 +0300 Subject: [PATCH 13/17] made some changes regarding the use of memory granularity instead of page size + better reading of image file on Windows --- com.oracle.max.vm.native/hosted/platform.c | 2 +- com.oracle.max.vm.native/share/threadLocals.c | 27 +++-- .../share/virtualMemory.c | 30 +++--- com.oracle.max.vm.native/substrate/image.c | 99 +++++++++++++++++-- com.oracle.max.vm.native/substrate/maxine.c | 22 +++-- 5 files changed, 144 insertions(+), 36 deletions(-) diff --git a/com.oracle.max.vm.native/hosted/platform.c b/com.oracle.max.vm.native/hosted/platform.c index b0c02489a3..5147627b04 100644 --- a/com.oracle.max.vm.native/hosted/platform.c +++ b/com.oracle.max.vm.native/hosted/platform.c @@ -66,7 +66,7 @@ Java_com_sun_max_platform_Platform_nativeGetPageSize(JNIEnv *env, jclass c) { #if os_WINDOWS SYSTEM_INFO systemInfo = {0}; GetSystemInfo(&systemInfo); - return systemInfo.dwPageSize ; + return systemInfo.dwAllocationGranularity ; //Windows do not care about page alignment but about memory allocatio granularity #else return (jint) sysconf(_SC_PAGESIZE); diff --git a/com.oracle.max.vm.native/share/threadLocals.c b/com.oracle.max.vm.native/share/threadLocals.c index 11b7a7ea24..d8e2022413 100644 --- a/com.oracle.max.vm.native/share/threadLocals.c +++ b/com.oracle.max.vm.native/share/threadLocals.c @@ -24,7 +24,9 @@ #else #include #include - #define aligned_alloc(a, b) _aligned_malloc(a, b) + #include + + #define aligned_alloc(a, b) _aligned_malloc(b, a) #endif #include #include @@ -78,7 +80,7 @@ static Address allocateThreadLocalBlock(size_t tlBlockSize) { return result; #else c_ASSERT(tlBlockSize < 100000000); - return (Address) aligned_alloc(4096, tlBlockSize); + return (Address) aligned_alloc(virtualMemory_getPageSize(), tlBlockSize); #endif } @@ -104,13 +106,17 @@ static void commitStackMemoryForInitialThread(Address base, int pageSize) { alloca(s); volatile char *p = (volatile char *) base; p[0] = p[0]; -#elif os_SOLARIS +#elif os_SOLARIS /* Writing to the bottom page of the reserved stack (appears) to be sufficient on Solaris. */ volatile char *p = (volatile char *) base; p[0] = p[0]; #elif os_DARWIN /* Mac OS X appears to commit the whole stack. */ -#endif +#elif os_WINDOWS // On Windows + //VirtualAlloc(base, pageSize,MEM_COMMIT,PAGE_READWRITE ); + + + #endif } /** @@ -123,9 +129,11 @@ static void commitStackMemoryForInitialThread(Address base, int pageSize) { * @param stackSize ignored if tlBlock != 0 */ Address threadLocalsBlock_create(jint id, Address tlBlock, Size stackSize) { - c_ASSERT(id != 0); + + c_ASSERT(id != 0); const int s = tlaSize(); const int tlaSize = s; + const int pageSize = virtualMemory_getPageSize(); const jboolean attaching = id < 0 || id == PRIMORDIAL_THREAD_ID; jboolean haveRedZone = false; @@ -168,12 +176,12 @@ Address threadLocalsBlock_create(jint id, Address tlBlock, Size stackSize) { /* Clear each of the thread local spaces: */ memset((void *) ttla, 0, tlaSize); + memset((void *) etla, 0, tlaSize); memset((void *) dtla, 0, tlaSize); /* Clear the NativeThreadLocals: */ memset((void *) ntl, 0, sizeof(NativeThreadLocalsStruct)); - ntl->handle = (Address) thread_self(); ntl->stackBase = stackBase; ntl->stackSize = stackSize; @@ -202,13 +210,13 @@ Address threadLocalsBlock_create(jint id, Address tlBlock, Size stackSize) { startGuardZone = ntl->redZone; guardZonePages = YELLOW_ZONE_PAGES + RED_ZONE_PAGES; - if (id == PRIMORDIAL_THREAD_ID) { commitStackMemoryForInitialThread(ntl->stackBase, pageSize); } } - tla_store(etla, ETLA, etla); + tla_store(etla, ETLA, etla); + tla_store(etla, DTLA, dtla); tla_store(etla, TTLA, ttla); @@ -264,8 +272,11 @@ Address threadLocalsBlock_create(jint id, Address tlBlock, Size stackSize) { maxve_initStack(ntl); #else virtualMemory_protectPages(startGuardZone, guardZonePages); + printf("vvvvvvv \n"); + #endif } + /* Protect the first page of the TL block (which contains the first word of the triggered thread locals) */ virtualMemory_protectPages(tlBlock, 1); diff --git a/com.oracle.max.vm.native/share/virtualMemory.c b/com.oracle.max.vm.native/share/virtualMemory.c index 5ef4152e04..c043583a62 100644 --- a/com.oracle.max.vm.native/share/virtualMemory.c +++ b/com.oracle.max.vm.native/share/virtualMemory.c @@ -148,7 +148,7 @@ Address virtualMemory_allocatePrivateAnon(Address address, Size size, jboolean r Address result; if(protNone == JNI_TRUE){ - result = (Address) VirtualAlloc( (void *) address, size, MEM_COMMIT | MEM_RESERVE| PAGE_WRITECOPY, PAGE_NOACCESS); + result = (Address) VirtualAlloc( (void *) address, size, MEM_RESERVE, PAGE_NOACCESS| PAGE_WRITECOPY); //virtualalloc is the only win32 function that supports the PROT_NONE equivalent PAGE_NOACCESS //PAGE_WRITECOPY is equivalent to MAP_PRIVATE @@ -158,13 +158,15 @@ Address virtualMemory_allocatePrivateAnon(Address address, Size size, jboolean r else { //if protnone is not used, we can use CreateFileMappingA + MapViewOfFile combination to emulate mmap() on Windows //INVALID_HANDLE_VALUE means that we dont use an actual file but the system pagefile, similar to fd= -1 & MPI_ANON in mmap() - HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_COMMIT,0u ,size, NULL); - //FILE_MAP_COPY is equivalent to MAP_PRIVATE + HANDLE fmapping = CreateFileMappingA( INVALID_HANDLE_VALUE , NULL , PAGE_EXECUTE_READWRITE | SEC_RESERVE,0u ,size, NULL); + // FILE_MAP_COPY is equivalent to MAP_PRIVATE if(!fmapping) log_println("%d\n", GetLastError()); - result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_COPY, 0, 0, size, (LPVOID)address); - if(!result) - log_println("%d\n", GetLastError()); + result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_ALL_ACCESS | FILE_MAP_COPY, 0, 0, size, (LPVOID)address); + // result = (Address) VirtualAlloc( (void *) address, size, MEM_RESERVE, PAGE_READWRITE); + + if(!result) + log_println("%d %d\n", GetLastError(), size); } @@ -266,7 +268,7 @@ Address virtualMemory_mapFileAtFixedAddress(Address address, Size size, jint fd, //_get_osfhandle returns a Windows HANDLE for the file descriptor fd, needed by CreateFileMappingA if(!fmapping) log_println("%d\n", GetLastError()); - Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size,(LPVOID) address); + Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_ALL_ACCESS| FILE_MAP_COPY, (DWORD)(offset >> 32), (DWORD) offset, size,(LPVOID) address); //the only diffrence is that we use MapViewOfFileEx instead MapViewOfFile. The first one allows us to provide an initial base address where the mapping begins (last argument) if(!result) @@ -349,7 +351,7 @@ boolean virtualMemory_allocateAtFixedAddress(Address address, Size size, int typ void virtualMemory_protectPages(Address address, int count) { /* log_println("--- protected %p .. %p", address, address + (count * virtualMemory_getPageSize())); */ - c_ASSERT(virtualMemory_pageAlign(address) == address); + c_ASSERT(virtualMemory_pageAlign(address) == address); #if os_SOLARIS || os_DARWIN || os_LINUX if (mprotect((void *) address, count * virtualMemory_getPageSize(), PROT_NONE) != 0) { int error = errno; @@ -357,9 +359,9 @@ void virtualMemory_protectPages(Address address, int count) { } #elif os_WINDOWS DWORD old; //needed for VirtualProtect - int error = GetLastError(); + int error = 0 ; if(!VirtualProtect((LPVOID) address,count * virtualMemory_getPageSize(), PAGE_NOACCESS, &old)) //PAGE_NOACCESS (WINAPI) = PROT_NONE (UNIX) - log_exit(error, "protectPages: VirtualProtect(%p) failed", address); + log_exit(error, "protectPages: VirtualProtect(%p) failed %d", address, GetLastError()); #elif os_MAXVE @@ -398,7 +400,7 @@ unsigned int virtualMemory_getPageSize(void) { #if os_WINDOWS SYSTEM_INFO systemInfo = {0}; GetSystemInfo(&systemInfo); - pageSize = systemInfo.dwPageSize ; + pageSize = systemInfo.dwAllocationGranularity ; #else pageSize = getpagesize(); #endif @@ -435,6 +437,12 @@ Size virtualMemory_getPhysicalMemorySize(void) { * Aligns a given address up to the next page-aligned address if it is not already page-aligned. */ Address virtualMemory_pageAlign(Address address) { + #if os_WINDOWS //aparrently windows do not care about page alignment but rather memory allocation granularity + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + long alignment = systemInfo.dwAllocationGranularity - 1 ; + #else long alignment = virtualMemory_getPageSize() - 1; + #endif return ((long)(address + alignment) & ~alignment); } diff --git a/com.oracle.max.vm.native/substrate/image.c b/com.oracle.max.vm.native/substrate/image.c index 198ea69f91..dcd416717a 100644 --- a/com.oracle.max.vm.native/substrate/image.c +++ b/com.oracle.max.vm.native/substrate/image.c @@ -25,7 +25,9 @@ #include #include #if !os_WINDOWS -#include + #include +#else + #include #endif #include #include @@ -236,7 +238,7 @@ static void checkImage(void) { log_exit(2, "image has insufficient alignment - expected: %d, found: %d", MIN_CACHE_ALIGNMENT, theHeader->cacheAlignment); } if (theHeader->pageSize != (jint) virtualMemory_getPageSize()) { - log_exit(2, "image has wrong page size - expected: %d, found: %d", virtualMemory_getPageSize(), theHeader->pageSize); + //log_exit(2, "image has wrong page size - expected: %d, found: %d", virtualMemory_getPageSize(), theHeader->pageSize); } FOR_ALL_THREAD_LOCALS(CHECK_THREAD_LOCAL) @@ -262,6 +264,7 @@ static void checkTrailer(int fd) { if (fileSize != expectedFileSize) { log_exit(2, "wrong image file size: expected %u bytes, read %u", expectedFileSize, fileSize); } + offset = lseek(fd, trailerOffset, SEEK_SET); if (offset != trailerOffset) { log_exit(1, "could not set trailer position in file"); @@ -297,7 +300,62 @@ static void checkTrailer(int fd) { exit(2); } } +#if os_WINDOWS + +static void mapHeapAndCode_winHandle(HANDLE open_img_result){ + int heapOffsetInImage = virtualMemory_pageAlign(sizeof(struct image_Header) + theHeader->stringDataSize + theHeader->relocationDataSize); + int heapAndCodeSize = theHeader->heapSize + theHeader->codeSize; + c_ASSERT(virtualMemory_pageAlign((Size) heapAndCodeSize) == (Size) heapAndCodeSize); + + + + Address reservedVirtualSpace = (Address) 0; + size_t virtualSpaceSize = 1024L * theHeader->reservedVirtualSpaceSize; + c_ASSERT(virtualMemory_pageAlign((Size) virtualSpaceSize) == (Size) virtualSpaceSize); + if (virtualSpaceSize != 0) { + // VM configuration asks for reserving an address space of size reservedVirtualSpaceSize. + // The following will create a mapping in virtual space of the requested size. + // The address returned might subsequently be used to memory map various regions, including the + // boot heap region, automatically splitting this mapping. + // In any case, the VM (mostly the heap scheme) is responsible for releasing unused reserved space. + reservedVirtualSpace = virtualMemory_allocatePrivateAnon((Address) 0, virtualSpaceSize, JNI_FALSE, JNI_FALSE, HEAP_VM); + if (reservedVirtualSpace == ALLOC_FAILED) { + log_exit(4, "could not reserve requested virtual space"); + } + } + if (theHeader->bootRegionMappingConstraint == 1) { + // Map the boot heap region at the start of the reserved space + theHeap = reservedVirtualSpace; + } else if (theHeader->bootRegionMappingConstraint == 2) { + // Map the boot heap region at the end of the reserved space. The start of the boot heap region is page-aligned. + theHeap = reservedVirtualSpace + virtualSpaceSize - heapAndCodeSize; + } else { + // Map the boot heap region anywhere outside of the reserved space. + theHeap = virtualMemory_allocatePrivateAnon((Address) 0, heapAndCodeSize, JNI_FALSE, JNI_FALSE, HEAP_VM); + if (theHeap == ALLOC_FAILED) { + log_exit(4, "could not reserve virtual space for boot image"); + } + } + virtualMemory_deallocate(theHeap,heapAndCodeSize, MEM_RELEASE ); //windows cannot map twice before freeing. However, we need the first map in order to get a validbase address (correctly aligned) for the second map + + HANDLE fmapping = CreateFileMappingA( open_img_result , NULL , PAGE_EXECUTE_READWRITE| SEC_COMMIT ,0u ,0, NULL); + if(!fmapping) + log_println("ss %d\n", GetLastError()); + Address result = (Address) MapViewOfFileEx (fmapping, FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE |FILE_MAP_COPY, (DWORD)((Size)heapOffsetInImage >> 32), (DWORD) heapOffsetInImage, heapAndCodeSize,(LPVOID) theHeap); + + if(!result) + log_println("error %d\n", GetLastError()); + if (reservedVirtualSpace) { + Address *addr = image_offset_as_address(Address *, reservedVirtualSpaceFieldOffset); + *addr = reservedVirtualSpace; + } + + theCode = theHeap + theHeader->heapSize; + theCodeEnd = theCode + theHeader->codeSize; + +} +#endif static void mapHeapAndCode(int fd) { int heapOffsetInImage = virtualMemory_pageAlign(sizeof(struct image_Header) + theHeader->stringDataSize + theHeader->relocationDataSize); int heapAndCodeSize = theHeader->heapSize + theHeader->codeSize; @@ -335,8 +393,12 @@ static void mapHeapAndCode(int fd) { log_exit(4, "could not reserve virtual space for boot image"); } } + #if os_WINDOWS + virtualMemory_deallocate(theHeap,heapAndCodeSize, MEM_RELEASE ); //windows cannot map twice before freeing. However, we need the first map in order to get a validbase address (correctly aligned) for the second map + #endif if (virtualMemory_mapFileAtFixedAddress(theHeap, heapAndCodeSize, fd, heapOffsetInImage) == ALLOC_FAILED) { //CAUTION on Windows, the Base Address must be a multiple of dwAllocationGranularity else mapping fails (UNTESTED since no image file is availabe) - log_exit(4, "could not map boot image"); + + log_exit(4, "could not map boot image"); } if (reservedVirtualSpace) { Address *addr = image_offset_as_address(Address *, reservedVirtualSpaceFieldOffset); @@ -386,7 +448,7 @@ static void relocate(int fd) { } n = read(fd, relocationData, theHeader->relocationDataSize); if (n != theHeader->relocationDataSize) { - log_exit(1, "could not read relocation data"); + log_exit(1, "could not read relocation data %d %d %d %d", n, theHeader->relocationDataSize, actualFileOffset, GetLastError()); } #else relocationData = (Byte*)(((char*)&maxvm_image_start) + wantedFileOffset); @@ -416,8 +478,25 @@ void image_load(char *imageFileName) { #if log_LOADER log_println("reading image from %s", imageFileName); #endif - fd = open(imageFileName, O_RDWR); - if (fd < 0) { +#if os_WINDOWS +HANDLE open_img_result = CreateFileA( + imageFileName , + GENERIC_READ | GENERIC_WRITE|GENERIC_EXECUTE , + FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL +); +if (open_img_result == INVALID_HANDLE_VALUE || !open_img_result) + log_exit(1, "could not open image file: %s %d", imageFileName, GetLastError()); + fd = open(imageFileName, _O_RDWR|_O_BINARY); //on windows, we use the image both as file handle (for executing) as well as a file descriptor (for reading) + +#else + fd = open(imageFileName, _O_RDWR); //on windows, we use the image both as file handle (for executing) as well as a file descriptor (for reading) + +#endif +if (fd < 0) { log_exit(1, "could not open image file: %s", imageFileName); } #endif @@ -426,11 +505,19 @@ void image_load(char *imageFileName) { checkImage(); readStringInfo(fd); checkTrailer(fd); + #if os_WINDOWS + //_close(fd); + mapHeapAndCode_winHandle( open_img_result); + //mapHeapAndCode(fd); + + #else mapHeapAndCode(fd); + #endif #if log_LOADER log_println("code @%p codeEnd @%p heap @%p", theCode, theCodeEnd, theHeap); #endif relocate(fd); + #if log_LOADER log_println("code @%p codeEnd @%p heap @%p", theCode, theCodeEnd, theHeap); #endif diff --git a/com.oracle.max.vm.native/substrate/maxine.c b/com.oracle.max.vm.native/substrate/maxine.c index c6759acb1a..c50c2bfda3 100644 --- a/com.oracle.max.vm.native/substrate/maxine.c +++ b/com.oracle.max.vm.native/substrate/maxine.c @@ -49,6 +49,12 @@ #define sleep(a) Sleep(a * 1000) #define strdup _strdup char last_dl_error [100]; //emulating dlerror() function not available on Windows + char *dlerror(){ + + + return last_dl_error; + } + #endif @@ -320,7 +326,7 @@ void debugger_initialize() { #if log_TELE log_println("Stopping VM for debugger"); #endif -#if os_DARWIN || os_LINUX || os_WINDOWS +#if os_DARWIN || os_LINUX kill(getpid(), SIGTRAP); #elif os_SOLARIS int ctlfd = open("/proc/self/ctl", O_WRONLY); @@ -392,22 +398,18 @@ int maxine(int argc, char *argv[], char *executablePath) { tla_initialize(image_header()->tlaSize); debugger_initialize(); method = image_offset_as_address(VMRunMethod, vmRunMethodOffset); - Address tlBlock = threadLocalsBlock_create(PRIMORDIAL_THREAD_ID, 0, 0); NativeThreadLocals ntl = NATIVE_THREAD_LOCALS_FROM_TLBLOCK(tlBlock); -#if os_WINDOWS -char *dlerror(){ - - - return last_dl_error; -} -#endif #if log_LOADER log_println("entering Java by calling MaxineVM.run(tlBlock=%p, bootHeapRegionStart=%p, openLibrary=%p, dlsym=%p, dlerror=%p, vmInterface=%p, jniEnv=%p, jmmInterface=%p, jvmtiInterface=%p, argc=%d, argv=%p)", tlBlock, image_heap(), openLibrary, loadSymbol, dlerror, getVMInterface(), jniEnv(), getJMMInterface(-1), getJVMTIInterface(-1), argc, argv); #endif - exitCode = (*method)(tlBlock, ntl->tlBlockSize, image_heap(), openLibrary, loadSymbol, dlerror, getVMInterface(), jniEnv(), getJMMInterface(-1), getJVMTIInterface(-1), argc, argv); + #if os_WINDOWS + printf("reached here \n"); + #endif + exitCode = (*method)(tlBlock, ntl->tlBlockSize, image_heap(), openLibrary, loadSymbol, dlerror, getVMInterface(), jniEnv(), getJMMInterface(-1), getJVMTIInterface(-1), argc, argv); + #if log_LOADER log_println("start method exited with code: %d", exitCode); From f9cd0298e1ff6704eab0fa66c2d7659f258e3c08 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Thu, 16 Jul 2020 00:14:04 +0300 Subject: [PATCH 14/17] mistkenly had commented out image page size check error print(works correclty) --- com.oracle.max.vm.native/substrate/image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.oracle.max.vm.native/substrate/image.c b/com.oracle.max.vm.native/substrate/image.c index dcd416717a..43d8c766c2 100644 --- a/com.oracle.max.vm.native/substrate/image.c +++ b/com.oracle.max.vm.native/substrate/image.c @@ -238,7 +238,7 @@ static void checkImage(void) { log_exit(2, "image has insufficient alignment - expected: %d, found: %d", MIN_CACHE_ALIGNMENT, theHeader->cacheAlignment); } if (theHeader->pageSize != (jint) virtualMemory_getPageSize()) { - //log_exit(2, "image has wrong page size - expected: %d, found: %d", virtualMemory_getPageSize(), theHeader->pageSize); + log_exit(2, "image has wrong page size - expected: %d, found: %d", virtualMemory_getPageSize(), theHeader->pageSize); } FOR_ALL_THREAD_LOCALS(CHECK_THREAD_LOCAL) From e20c3cf8a6fba3cfc36e1c3363593a15b118b763 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudakis Date: Thu, 16 Jul 2020 14:56:40 +0300 Subject: [PATCH 15/17] Removd Windows GetLastError() in a deugging print which broke compilation on Linux --- com.oracle.max.vm.native/substrate/image.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.oracle.max.vm.native/substrate/image.c b/com.oracle.max.vm.native/substrate/image.c index 43d8c766c2..4cb3ee7335 100644 --- a/com.oracle.max.vm.native/substrate/image.c +++ b/com.oracle.max.vm.native/substrate/image.c @@ -448,7 +448,7 @@ static void relocate(int fd) { } n = read(fd, relocationData, theHeader->relocationDataSize); if (n != theHeader->relocationDataSize) { - log_exit(1, "could not read relocation data %d %d %d %d", n, theHeader->relocationDataSize, actualFileOffset, GetLastError()); + log_exit(1, "could not read relocation data %d %d %d ", n, theHeader->relocationDataSize, actualFileOffset); } #else relocationData = (Byte*)(((char*)&maxvm_image_start) + wantedFileOffset); @@ -493,7 +493,7 @@ if (open_img_result == INVALID_HANDLE_VALUE || !open_img_result) fd = open(imageFileName, _O_RDWR|_O_BINARY); //on windows, we use the image both as file handle (for executing) as well as a file descriptor (for reading) #else - fd = open(imageFileName, _O_RDWR); //on windows, we use the image both as file handle (for executing) as well as a file descriptor (for reading) + fd = open(imageFileName, O_RDWR); //on windows, we use the image both as file handle (for executing) as well as a file descriptor (for reading) #endif if (fd < 0) { From 8774efd67e1d5eb32e4c351dff4e750e88270f9c Mon Sep 17 00:00:00 2001 From: Michael Nikoloudkis Date: Fri, 17 Jul 2020 01:29:16 +0300 Subject: [PATCH 16/17] Create output.txt --- com.oracle.max.vm.native/windows_tests/output.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 com.oracle.max.vm.native/windows_tests/output.txt diff --git a/com.oracle.max.vm.native/windows_tests/output.txt b/com.oracle.max.vm.native/windows_tests/output.txt new file mode 100644 index 0000000000..e69de29bb2 From bde46655a92cc3b838c6f9f5efbb83cd67059db7 Mon Sep 17 00:00:00 2001 From: Michael Nikoloudakis Date: Mon, 16 Nov 2020 02:13:18 +0200 Subject: [PATCH 17/17] Updated Status.rst --- docs/Status.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Status.rst b/docs/Status.rst index 23a6c32da9..d5f6e42ace 100644 --- a/docs/Status.rst +++ b/docs/Status.rst @@ -15,6 +15,8 @@ Maxine is being developed and tested on the following configurations: +----------------+----------------------+--------------------------+--------------------+ | x86_64 | macOS Mojave 10.14 | OpenJDK 8 (u222) | 2.9.0 | +----------------+----------------------+--------------------------+--------------------+ +| X86_64 | Windows 10 | OpenJDK 8 (u222) | 2.9.0 | ++----------------+----------------------+--------------------------+--------------------+ | Aarch64 | Ubuntu 18.04 | OpenJDK 8 (u222) | 2.9.0 | +----------------+----------------------+--------------------------+--------------------+ | RISC-V64 | Fedora 31 (on QEMU) | OpenJDK 8 (u222) | 2.9.0 |