1 : /*
2 : * Copyright 2008 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : /*
8 : * NaCl semaphore implementation (Windows)
9 : */
10 :
11 : #include <windows.h>
12 :
13 : #include "native_client/src/include/portability.h"
14 : #include "native_client/src/shared/platform/nacl_sync.h"
15 : #include "native_client/src/shared/platform/win/nacl_semaphore.h"
16 :
17 :
18 : /* Generic test for success on any status value (non-negative numbers
19 : * indicate success).
20 : */
21 : #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
22 :
23 : /* semaphore object query structure */
24 :
25 : typedef struct _SEMAINFO {
26 : unsigned int count; /* current semaphore count */
27 : unsigned int limit; /* max semaphore count */
28 : } SEMAINFO, *PSEMAINFO;
29 :
30 : /* only one query type for semaphores */
31 : #define SEMAQUERYINFOCLASS 0
32 : #define WINAPI __stdcall
33 :
34 : /* NT Function call. */
35 : NTSTATUS WINAPI NtQuerySemaphore(HANDLE Handle,
36 : unsigned int InfoClass,
37 : PSEMAINFO SemaInfo,
38 : unsigned int InfoSize,
39 : unsigned int *RetLen);
40 :
41 :
42 :
43 1 : int NaClSemCtor(struct NaClSemaphore *sem, int32_t value) {
44 1 : sem->sem_handle = CreateSemaphore(NULL, value, SEM_VALUE_MAX, NULL);
45 1 : if (NULL == sem->sem_handle) {
46 0 : return 0;
47 : }
48 1 : sem->interrupt_event = CreateEvent(NULL, TRUE, FALSE, NULL);
49 1 : if (NULL == sem->interrupt_event) {
50 0 : CloseHandle(sem->sem_handle);
51 0 : return 0;
52 : }
53 1 : return 1;
54 1 : }
55 :
56 1 : void NaClSemDtor(struct NaClSemaphore *sem) {
57 1 : CloseHandle(sem->sem_handle);
58 1 : CloseHandle(sem->interrupt_event);
59 1 : }
60 :
61 0 : NaClSyncStatus NaClSemWait(struct NaClSemaphore *sem) {
62 : DWORD rv;
63 : NaClSyncStatus status;
64 : HANDLE handles[2];
65 0 : handles[0] = sem->sem_handle;
66 0 : handles[1] = sem->interrupt_event;
67 :
68 0 : rv = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
69 0 : switch (rv) {
70 : case WAIT_OBJECT_0:
71 0 : status = NACL_SYNC_OK;
72 0 : break;
73 : case WAIT_OBJECT_0 + 1:
74 0 : status = NACL_SYNC_SEM_INTERRUPTED;
75 0 : break;
76 : default:
77 0 : status = NACL_SYNC_INTERNAL_ERROR;
78 : }
79 0 : return status;
80 0 : }
81 :
82 1 : NaClSyncStatus NaClSemTryWait(struct NaClSemaphore *sem) {
83 : DWORD rv;
84 1 : rv = WaitForSingleObject(sem->sem_handle, 0);
85 1 : return (rv == WAIT_OBJECT_0) ? NACL_SYNC_OK : NACL_SYNC_BUSY;
86 1 : }
87 :
88 1 : NaClSyncStatus NaClSemPost(struct NaClSemaphore *sem) {
89 1 : if (ReleaseSemaphore(sem->sem_handle, 1, NULL)) {
90 1 : return NACL_SYNC_OK;
91 : }
92 0 : if (ERROR_TOO_MANY_POSTS == GetLastError()) {
93 0 : return NACL_SYNC_SEM_RANGE_ERROR;
94 : }
95 0 : return NACL_SYNC_INTERNAL_ERROR;
96 1 : }
97 :
98 0 : int32_t NaClSemGetValue(struct NaClSemaphore *sem) {
99 : /*
100 : * TODO(greogyrd): please uncomment these decls when they're needed / when
101 : * the code below is re-enabled. These were commented-out to eliminate
102 : * windows compiler warnings.
103 : SEMAINFO sem_info;
104 : UINT ret_length;
105 : NTSTATUS status;
106 : */
107 0 : int32_t count = -1;
108 : UNREFERENCED_PARAMETER(sem);
109 : /* TODO(gregoryd): cannot use NtQuerySemaphore without linking to ntdll.lib
110 : status = NtQuerySemaphore(
111 : sem->sem_handle,
112 : SEMAQUERYINFOCLASS,
113 : &sem_info,
114 : sizeof sem_info,
115 : &ret_length
116 : );
117 :
118 : if (!NT_SUCCESS(status)) {
119 : count = -1;
120 : } else {
121 : count = sem_info.count;
122 : }
123 : */
124 0 : return count;
125 0 : }
126 :
127 0 : void NaClSemIntr(struct NaClSemaphore *sem) {
128 0 : SetEvent(sem->interrupt_event);
129 0 : }
130 :
131 0 : void NaClSemReset(struct NaClSemaphore *sem) {
132 0 : ResetEvent(sem->interrupt_event);
133 0 : }
|