1/*
2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#include <windows.h>
27#include <errno.h>
28
29#include "shmem_md.h"
30#include "sysShmem.h"
31#include "shmemBase.h"  /* for exitTransportWithError */
32
33/* Use THIS_FILE when it is available. */
34#ifndef THIS_FILE
35    #define THIS_FILE __FILE__
36#endif
37
38/*
39 * These functions are not completely universal. For now, they are used
40 * exclusively for Jbug's shared memory transport mechanism. They have
41 * been implemented on Win32 only so far, so the abstractions may not be correct
42 * yet.
43 */
44
45static HANDLE memHandle = NULL;
46
47#ifdef DEBUG
48#define sysAssert(expression) {         \
49    if (!(expression)) {                \
50            exitTransportWithError \
51            ("\"%s\", line %d: assertion failure\n", \
52             THIS_FILE, __DATE__, __LINE__); \
53    }                                   \
54}
55#else
56#define sysAssert(expression) ((void) 0)
57#endif
58
59int
60sysSharedMemCreate(const char *name, int length,
61                   sys_shmem_t *mem, void **buffer)
62{
63    void *mappedMemory;
64    HANDLE memHandle;
65
66    sysAssert(buffer);
67    sysAssert(name);
68    sysAssert(length > 0);
69
70    memHandle  =
71        CreateFileMapping(INVALID_HANDLE_VALUE, /* backed by page file */
72                          NULL,               /* no inheritance */
73                          PAGE_READWRITE,
74                          0, length,          /* hi, lo order of length */
75                          name);
76    if (memHandle == NULL) {
77        return SYS_ERR;
78    } else if (GetLastError() == ERROR_ALREADY_EXISTS) {
79        /* If the call above didn't create it, consider it an error */
80        CloseHandle(memHandle);
81        memHandle = NULL;
82        return SYS_INUSE;
83    }
84
85    mappedMemory =
86        MapViewOfFile(memHandle,
87                      FILE_MAP_WRITE,       /* read/write */
88                      0, 0, 0);             /* map entire "file" */
89
90    if (mappedMemory == NULL) {
91        CloseHandle(memHandle);
92        memHandle = NULL;
93        return SYS_ERR;
94    }
95
96    *mem = memHandle;
97    *buffer = mappedMemory;
98    return SYS_OK;
99}
100
101int
102sysSharedMemOpen(const char *name, sys_shmem_t *mem, void **buffer)
103{
104    void *mappedMemory;
105    HANDLE memHandle;
106
107    sysAssert(name);
108    sysAssert(buffer);
109
110    memHandle =
111        OpenFileMapping(FILE_MAP_WRITE,     /* read/write */
112                        FALSE,              /* no inheritance */
113                        name);
114    if (memHandle == NULL) {
115        return SYS_ERR;
116    }
117
118    mappedMemory =
119        MapViewOfFile(memHandle,
120                      FILE_MAP_WRITE,       /* read/write */
121                      0, 0, 0);             /* map entire "file" */
122
123    if (mappedMemory == NULL) {
124        CloseHandle(memHandle);
125        memHandle = NULL;
126        return SYS_ERR;
127    }
128
129    *mem = memHandle;
130    *buffer = mappedMemory;
131    return SYS_OK;
132}
133
134int
135sysSharedMemClose(sys_shmem_t mem, void *buffer)
136{
137    if (buffer != NULL) {
138        if (!UnmapViewOfFile(buffer)) {
139            return SYS_ERR;
140        }
141    }
142
143    if (!CloseHandle(mem)) {
144        return SYS_ERR;
145    }
146
147    return SYS_OK;
148}
149
150int
151sysIPMutexCreate(const char *name, sys_ipmutex_t *mutexPtr)
152{
153    HANDLE mutex;
154
155    sysAssert(mutexPtr);
156    sysAssert(name);
157
158    mutex = CreateMutex(NULL,            /* no inheritance */
159                        FALSE,           /* no initial owner */
160                        name);
161    if (mutex == NULL) {
162        return SYS_ERR;
163    } else if (GetLastError() == ERROR_ALREADY_EXISTS) {
164        /* If the call above didn't create it, consider it an error */
165        CloseHandle(mutex);
166        return SYS_INUSE;
167    }
168
169    *mutexPtr = mutex;
170    return SYS_OK;
171}
172
173int
174sysIPMutexOpen(const char *name, sys_ipmutex_t *mutexPtr)
175{
176    HANDLE mutex;
177
178    sysAssert(mutexPtr);
179    sysAssert(name);
180
181    mutex = OpenMutex(SYNCHRONIZE,      /* able to wait/release */
182                      FALSE,            /* no inheritance */
183                      name);
184    if (mutex == NULL) {
185        return SYS_ERR;
186    }
187
188    *mutexPtr = mutex;
189    return SYS_OK;
190}
191
192int
193sysIPMutexEnter(sys_ipmutex_t mutex, sys_event_t event)
194{
195    HANDLE handles[2] = { mutex, event };
196    int count = event == NULL ? 1 : 2;
197    DWORD rc;
198
199    sysAssert(mutex);
200    rc = WaitForMultipleObjects(count, handles,
201                                FALSE,              /* wait for either, not both */
202                                INFINITE);          /* infinite timeout */
203    return (rc == WAIT_OBJECT_0) ? SYS_OK : SYS_ERR;
204}
205
206int
207sysIPMutexExit(sys_ipmutex_t mutex)
208{
209    sysAssert(mutex);
210    return ReleaseMutex(mutex) ? SYS_OK : SYS_ERR;
211}
212
213int
214sysIPMutexClose(sys_ipmutex_t mutex)
215{
216    return CloseHandle(mutex) ? SYS_OK : SYS_ERR;
217}
218
219int
220sysEventCreate(const char *name, sys_event_t *eventPtr, jboolean manualReset)
221{
222    HANDLE event;
223    BOOL reset = (manualReset == JNI_TRUE) ? TRUE : FALSE;
224
225    sysAssert(eventPtr);
226
227    event = CreateEvent(NULL,            /* no inheritance */
228                        reset,           /* manual reset */
229                        FALSE,           /* initially, not signalled */
230                        name);
231    if (event == NULL) {
232        return SYS_ERR;
233    } else if (GetLastError() == ERROR_ALREADY_EXISTS) {
234        /* If the call above didn't create it, consider it an error */
235        CloseHandle(event);
236        return SYS_INUSE;
237    }
238
239    *eventPtr = event;
240    return SYS_OK;
241}
242
243int
244sysEventOpen(const char *name, sys_event_t *eventPtr)
245{
246    HANDLE event;
247
248    sysAssert(eventPtr);
249    sysAssert(name);
250
251    event = OpenEvent(SYNCHRONIZE | EVENT_MODIFY_STATE,
252                                        /* able to wait/signal */
253                      FALSE,            /* no inheritance */
254                      name);
255    if (event == NULL) {
256        return SYS_ERR;
257    }
258
259    *eventPtr = event;
260    return SYS_OK;
261}
262
263int
264sysEventWait(sys_process_t otherProcess, sys_event_t event, long timeout)
265{
266    HANDLE handles[2];        /* process, event */
267    DWORD rc;
268    int count;
269    DWORD dwTimeout = (timeout == 0) ? INFINITE : (DWORD)timeout;
270
271    /*
272     * If the signalling process is specified, and it dies while we wait,
273     * detect it and return an error.
274     */
275    sysAssert(event);
276
277    handles[0] = event;
278    handles[1] = otherProcess;
279
280    count = (otherProcess == NULL) ? 1 : 2;
281
282    rc = WaitForMultipleObjects(count, handles,
283                                FALSE,        /* wait for either, not both */
284                                dwTimeout);
285    if (rc == WAIT_OBJECT_0) {
286        /* Signalled, return success */
287        return SYS_OK;
288    } else if (rc == WAIT_OBJECT_0 + 1) {
289        /* Other process died, return error */
290        return SYS_DIED;
291    } else if (rc == WAIT_TIMEOUT) {
292        /* timeout */
293        return SYS_TIMEOUT;
294    }
295    return SYS_ERR;
296}
297
298int
299sysEventSignal(sys_event_t event)
300{
301    sysAssert(event);
302    return SetEvent(event) ? SYS_OK : SYS_ERR;
303}
304
305int
306sysEventClose(sys_event_t event)
307{
308    return CloseHandle(event) ? SYS_OK : SYS_ERR;
309}
310
311jlong
312sysProcessGetID()
313{
314    return GetCurrentProcessId();
315}
316
317int
318sysProcessOpen(jlong processID, sys_process_t *processPtr)
319{
320    HANDLE process;
321
322    sysAssert(processPtr);
323
324    process = OpenProcess(SYNCHRONIZE,    /* able to wait on death */
325                          FALSE,          /* no inheritance */
326                          (DWORD)processID);
327    if (process == NULL) {
328        return SYS_ERR;
329    }
330
331    *processPtr = process;
332    return SYS_OK;
333}
334
335int
336sysProcessClose(sys_process_t *process)
337{
338    return CloseHandle(process) ? SYS_OK : SYS_ERR;
339}
340
341int
342sysGetLastError(char *buf, int len)
343{
344    long errval = GetLastError();
345    if (errval != 0) {
346        int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
347                              NULL, errval,
348                              0, buf, len, NULL);
349        if (n > 3) {
350            /* Drop final '.', CR, LF */
351            if (buf[n - 1] == '\n') n--;
352            if (buf[n - 1] == '\r') n--;
353            if (buf[n - 1] == '.') n--;
354            buf[n] = '\0';
355        }
356        return SYS_OK;
357    }
358    buf[0] = '\0';
359    return 0;
360}
361
362int
363sysTlsAlloc() {
364    return TlsAlloc();
365}
366
367void
368sysTlsFree(int index) {
369    TlsFree(index);
370}
371
372void
373sysTlsPut(int index, void *value) {
374    TlsSetValue(index, value);
375}
376
377void *
378sysTlsGet(int index) {
379    return TlsGetValue(index);
380}
381
382void
383sysSleep(long duration) {
384    Sleep((DWORD)duration);
385}
386