| /* |
| * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #include <windows.h> |
| #include <errno.h> |
| |
| #include "shmem_md.h" |
| #include "sysShmem.h" |
| #include "shmemBase.h" /* for exitTransportWithError */ |
| |
| /* Use THIS_FILE when it is available. */ |
| #ifndef THIS_FILE |
| #define THIS_FILE __FILE__ |
| #endif |
| |
| /* |
| * These functions are not completely universal. For now, they are used |
| * exclusively for Jbug's shared memory transport mechanism. They have |
| * been implemented on Win32 only so far, so the abstractions may not be correct |
| * yet. |
| */ |
| |
| static HANDLE memHandle = NULL; |
| |
| #ifdef DEBUG |
| #define sysAssert(expression) { \ |
| if (!(expression)) { \ |
| exitTransportWithError \ |
| ("\"%s\", line %d: assertion failure\n", \ |
| THIS_FILE, __DATE__, __LINE__); \ |
| } \ |
| } |
| #else |
| #define sysAssert(expression) ((void) 0) |
| #endif |
| |
| int |
| sysSharedMemCreate(const char *name, int length, |
| sys_shmem_t *mem, void **buffer) |
| { |
| void *mappedMemory; |
| HANDLE memHandle; |
| |
| sysAssert(buffer); |
| sysAssert(name); |
| sysAssert(length > 0); |
| |
| memHandle = |
| CreateFileMapping(INVALID_HANDLE_VALUE, /* backed by page file */ |
| NULL, /* no inheritance */ |
| PAGE_READWRITE, |
| 0, length, /* hi, lo order of length */ |
| name); |
| if (memHandle == NULL) { |
| return SYS_ERR; |
| } else if (GetLastError() == ERROR_ALREADY_EXISTS) { |
| /* If the call above didn't create it, consider it an error */ |
| CloseHandle(memHandle); |
| memHandle = NULL; |
| return SYS_INUSE; |
| } |
| |
| mappedMemory = |
| MapViewOfFile(memHandle, |
| FILE_MAP_WRITE, /* read/write */ |
| 0, 0, 0); /* map entire "file" */ |
| |
| if (mappedMemory == NULL) { |
| CloseHandle(memHandle); |
| memHandle = NULL; |
| return SYS_ERR; |
| } |
| |
| *mem = memHandle; |
| *buffer = mappedMemory; |
| return SYS_OK; |
| } |
| |
| int |
| sysSharedMemOpen(const char *name, sys_shmem_t *mem, void **buffer) |
| { |
| void *mappedMemory; |
| HANDLE memHandle; |
| |
| sysAssert(name); |
| sysAssert(buffer); |
| |
| memHandle = |
| OpenFileMapping(FILE_MAP_WRITE, /* read/write */ |
| FALSE, /* no inheritance */ |
| name); |
| if (memHandle == NULL) { |
| return SYS_ERR; |
| } |
| |
| mappedMemory = |
| MapViewOfFile(memHandle, |
| FILE_MAP_WRITE, /* read/write */ |
| 0, 0, 0); /* map entire "file" */ |
| |
| if (mappedMemory == NULL) { |
| CloseHandle(memHandle); |
| memHandle = NULL; |
| return SYS_ERR; |
| } |
| |
| *mem = memHandle; |
| *buffer = mappedMemory; |
| return SYS_OK; |
| } |
| |
| int |
| sysSharedMemClose(sys_shmem_t mem, void *buffer) |
| { |
| if (buffer != NULL) { |
| if (!UnmapViewOfFile(buffer)) { |
| return SYS_ERR; |
| } |
| } |
| |
| if (!CloseHandle(mem)) { |
| return SYS_ERR; |
| } |
| |
| return SYS_OK; |
| } |
| |
| int |
| sysIPMutexCreate(const char *name, sys_ipmutex_t *mutexPtr) |
| { |
| HANDLE mutex; |
| |
| sysAssert(mutexPtr); |
| sysAssert(name); |
| |
| mutex = CreateMutex(NULL, /* no inheritance */ |
| FALSE, /* no initial owner */ |
| name); |
| if (mutex == NULL) { |
| return SYS_ERR; |
| } else if (GetLastError() == ERROR_ALREADY_EXISTS) { |
| /* If the call above didn't create it, consider it an error */ |
| CloseHandle(mutex); |
| return SYS_INUSE; |
| } |
| |
| *mutexPtr = mutex; |
| return SYS_OK; |
| } |
| |
| int |
| sysIPMutexOpen(const char *name, sys_ipmutex_t *mutexPtr) |
| { |
| HANDLE mutex; |
| |
| sysAssert(mutexPtr); |
| sysAssert(name); |
| |
| mutex = OpenMutex(SYNCHRONIZE, /* able to wait/release */ |
| FALSE, /* no inheritance */ |
| name); |
| if (mutex == NULL) { |
| return SYS_ERR; |
| } |
| |
| *mutexPtr = mutex; |
| return SYS_OK; |
| } |
| |
| int |
| sysIPMutexEnter(sys_ipmutex_t mutex, sys_event_t event) |
| { |
| HANDLE handles[2] = { mutex, event }; |
| int count = event == NULL ? 1 : 2; |
| DWORD rc; |
| |
| sysAssert(mutex); |
| rc = WaitForMultipleObjects(count, handles, |
| FALSE, /* wait for either, not both */ |
| INFINITE); /* infinite timeout */ |
| return (rc == WAIT_OBJECT_0) ? SYS_OK : SYS_ERR; |
| } |
| |
| int |
| sysIPMutexExit(sys_ipmutex_t mutex) |
| { |
| sysAssert(mutex); |
| return ReleaseMutex(mutex) ? SYS_OK : SYS_ERR; |
| } |
| |
| int |
| sysIPMutexClose(sys_ipmutex_t mutex) |
| { |
| return CloseHandle(mutex) ? SYS_OK : SYS_ERR; |
| } |
| |
| int |
| sysEventCreate(const char *name, sys_event_t *eventPtr, jboolean manualReset) |
| { |
| HANDLE event; |
| BOOL reset = (manualReset == JNI_TRUE) ? TRUE : FALSE; |
| |
| sysAssert(eventPtr); |
| |
| event = CreateEvent(NULL, /* no inheritance */ |
| reset, /* manual reset */ |
| FALSE, /* initially, not signalled */ |
| name); |
| if (event == NULL) { |
| return SYS_ERR; |
| } else if (GetLastError() == ERROR_ALREADY_EXISTS) { |
| /* If the call above didn't create it, consider it an error */ |
| CloseHandle(event); |
| return SYS_INUSE; |
| } |
| |
| *eventPtr = event; |
| return SYS_OK; |
| } |
| |
| int |
| sysEventOpen(const char *name, sys_event_t *eventPtr) |
| { |
| HANDLE event; |
| |
| sysAssert(eventPtr); |
| sysAssert(name); |
| |
| event = OpenEvent(SYNCHRONIZE | EVENT_MODIFY_STATE, |
| /* able to wait/signal */ |
| FALSE, /* no inheritance */ |
| name); |
| if (event == NULL) { |
| return SYS_ERR; |
| } |
| |
| *eventPtr = event; |
| return SYS_OK; |
| } |
| |
| int |
| sysEventWait(sys_process_t otherProcess, sys_event_t event, long timeout) |
| { |
| HANDLE handles[2]; /* process, event */ |
| DWORD rc; |
| int count; |
| DWORD dwTimeout = (timeout == 0) ? INFINITE : (DWORD)timeout; |
| |
| /* |
| * If the signalling process is specified, and it dies while we wait, |
| * detect it and return an error. |
| */ |
| sysAssert(event); |
| |
| handles[0] = event; |
| handles[1] = otherProcess; |
| |
| count = (otherProcess == NULL) ? 1 : 2; |
| |
| rc = WaitForMultipleObjects(count, handles, |
| FALSE, /* wait for either, not both */ |
| dwTimeout); |
| if (rc == WAIT_OBJECT_0) { |
| /* Signalled, return success */ |
| return SYS_OK; |
| } else if (rc == WAIT_OBJECT_0 + 1) { |
| /* Other process died, return error */ |
| return SYS_DIED; |
| } else if (rc == WAIT_TIMEOUT) { |
| /* timeout */ |
| return SYS_TIMEOUT; |
| } |
| return SYS_ERR; |
| } |
| |
| int |
| sysEventSignal(sys_event_t event) |
| { |
| sysAssert(event); |
| return SetEvent(event) ? SYS_OK : SYS_ERR; |
| } |
| |
| int |
| sysEventClose(sys_event_t event) |
| { |
| return CloseHandle(event) ? SYS_OK : SYS_ERR; |
| } |
| |
| jlong |
| sysProcessGetID() |
| { |
| return GetCurrentProcessId(); |
| } |
| |
| int |
| sysProcessOpen(jlong processID, sys_process_t *processPtr) |
| { |
| HANDLE process; |
| |
| sysAssert(processPtr); |
| |
| process = OpenProcess(SYNCHRONIZE, /* able to wait on death */ |
| FALSE, /* no inheritance */ |
| (DWORD)processID); |
| if (process == NULL) { |
| return SYS_ERR; |
| } |
| |
| *processPtr = process; |
| return SYS_OK; |
| } |
| |
| int |
| sysProcessClose(sys_process_t *process) |
| { |
| return CloseHandle(process) ? SYS_OK : SYS_ERR; |
| } |
| |
| int |
| sysGetLastError(char *buf, int len) |
| { |
| long errval = GetLastError(); |
| if (errval != 0) { |
| int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, |
| NULL, errval, |
| 0, buf, len, NULL); |
| if (n > 3) { |
| /* Drop final '.', CR, LF */ |
| if (buf[n - 1] == '\n') n--; |
| if (buf[n - 1] == '\r') n--; |
| if (buf[n - 1] == '.') n--; |
| buf[n] = '\0'; |
| } |
| return SYS_OK; |
| } |
| buf[0] = '\0'; |
| return 0; |
| } |
| |
| int |
| sysTlsAlloc() { |
| return TlsAlloc(); |
| } |
| |
| void |
| sysTlsFree(int index) { |
| TlsFree(index); |
| } |
| |
| void |
| sysTlsPut(int index, void *value) { |
| TlsSetValue(index, value); |
| } |
| |
| void * |
| sysTlsGet(int index) { |
| return TlsGetValue(index); |
| } |
| |
| void |
| sysSleep(long duration) { |
| Sleep((DWORD)duration); |
| } |