1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*++
6
7
8
9Module Name:
10
11 event.cpp
12
13Abstract:
14
15 Implementation of event synchronization object as described in
16 the WIN32 API
17
18Revision History:
19
20
21
22--*/
23
24#include "pal/event.hpp"
25#include "pal/thread.hpp"
26#include "pal/dbgmsg.h"
27
28using namespace CorUnix;
29
30/* ------------------- Definitions ------------------------------*/
31SET_DEFAULT_DEBUG_CHANNEL(SYNC);
32
33CObjectType CorUnix::otManualResetEvent(
34 otiManualResetEvent,
35 NULL, // No cleanup routine
36 NULL, // No initialization routine
37 0, // No immutable data
38 NULL, // No immutable data copy routine
39 NULL, // No immutable data cleanup routine
40 0, // No process local data
41 NULL, // No process local data cleanup routine
42 0, // No shared data
43 EVENT_ALL_ACCESS, // Currently ignored (no Win32 security)
44 CObjectType::SecuritySupported,
45 CObjectType::SecurityInfoNotPersisted,
46 CObjectType::UnnamedObject,
47 CObjectType::LocalDuplicationOnly,
48 CObjectType::WaitableObject,
49 CObjectType::ObjectCanBeUnsignaled,
50 CObjectType::ThreadReleaseHasNoSideEffects,
51 CObjectType::NoOwner
52 );
53
54CObjectType CorUnix::otAutoResetEvent(
55 otiAutoResetEvent,
56 NULL, // No cleanup routine
57 NULL, // No initialization routine
58 0, // No immutable data
59 NULL, // No immutable data copy routine
60 NULL, // No immutable data cleanup routine
61 0, // No process local data
62 NULL, // No process local data cleanup routine
63 0, // No shared data
64 EVENT_ALL_ACCESS, // Currently ignored (no Win32 security)
65 CObjectType::SecuritySupported,
66 CObjectType::SecurityInfoNotPersisted,
67 CObjectType::UnnamedObject,
68 CObjectType::LocalDuplicationOnly,
69 CObjectType::WaitableObject,
70 CObjectType::ObjectCanBeUnsignaled,
71 CObjectType::ThreadReleaseAltersSignalCount,
72 CObjectType::NoOwner
73 );
74
75PalObjectTypeId rgEventIds[] = {otiManualResetEvent, otiAutoResetEvent};
76CAllowedObjectTypes aotEvent(rgEventIds, sizeof(rgEventIds)/sizeof(rgEventIds[0]));
77
78/*++
79Function:
80 CreateEventA
81
82Note:
83 lpEventAttributes currentely ignored:
84 -- Win32 object security not supported
85 -- handles to event objects are not inheritable
86
87Parameters:
88 See MSDN doc.
89--*/
90
91HANDLE
92PALAPI
93CreateEventA(
94 IN LPSECURITY_ATTRIBUTES lpEventAttributes,
95 IN BOOL bManualReset,
96 IN BOOL bInitialState,
97 IN LPCSTR lpName)
98{
99 HANDLE hEvent = NULL;
100 CPalThread *pthr = NULL;
101 PAL_ERROR palError;
102
103 PERF_ENTRY(CreateEventA);
104 ENTRY("CreateEventA(lpEventAttr=%p, bManualReset=%d, bInitialState=%d, lpName=%p (%s)\n",
105 lpEventAttributes, bManualReset, bInitialState, lpName, lpName?lpName:"NULL");
106
107 pthr = InternalGetCurrentThread();
108
109 if (lpName != nullptr)
110 {
111 ASSERT("lpName: Cross-process named objects are not supported in PAL");
112 palError = ERROR_NOT_SUPPORTED;
113 }
114 else
115 {
116 palError = InternalCreateEvent(
117 pthr,
118 lpEventAttributes,
119 bManualReset,
120 bInitialState,
121 NULL,
122 &hEvent
123 );
124 }
125
126 //
127 // We always need to set last error, even on success:
128 // we need to protect ourselves from the situation
129 // where last error is set to ERROR_ALREADY_EXISTS on
130 // entry to the function
131 //
132
133 pthr->SetLastError(palError);
134
135 LOGEXIT("CreateEventA returns HANDLE %p\n", hEvent);
136 PERF_EXIT(CreateEventA);
137 return hEvent;
138}
139
140
141/*++
142Function:
143 CreateEventW
144
145Note:
146 lpEventAttributes currentely ignored:
147 -- Win32 object security not supported
148 -- handles to event objects are not inheritable
149
150Parameters:
151 See MSDN doc.
152--*/
153
154HANDLE
155PALAPI
156CreateEventW(
157 IN LPSECURITY_ATTRIBUTES lpEventAttributes,
158 IN BOOL bManualReset,
159 IN BOOL bInitialState,
160 IN LPCWSTR lpName)
161{
162 HANDLE hEvent = NULL;
163 PAL_ERROR palError;
164 CPalThread *pthr = NULL;
165
166 PERF_ENTRY(CreateEventW);
167 ENTRY("CreateEventW(lpEventAttr=%p, bManualReset=%d, "
168 "bInitialState=%d, lpName=%p (%S)\n", lpEventAttributes, bManualReset,
169 bInitialState, lpName, lpName?lpName:W16_NULLSTRING);
170
171 pthr = InternalGetCurrentThread();
172
173 palError = InternalCreateEvent(
174 pthr,
175 lpEventAttributes,
176 bManualReset,
177 bInitialState,
178 lpName,
179 &hEvent
180 );
181
182 //
183 // We always need to set last error, even on success:
184 // we need to protect ourselves from the situation
185 // where last error is set to ERROR_ALREADY_EXISTS on
186 // entry to the function
187 //
188
189 pthr->SetLastError(palError);
190
191 LOGEXIT("CreateEventW returns HANDLE %p\n", hEvent);
192 PERF_EXIT(CreateEventW);
193 return hEvent;
194}
195
196/*++
197Function:
198 CreateEventExW
199
200Note:
201 lpEventAttributes and dwDesiredAccess are currently ignored:
202 -- Win32 object security not supported
203 -- handles to event objects are not inheritable
204 -- Access rights are not supported
205
206Parameters:
207 See MSDN doc.
208--*/
209
210HANDLE
211PALAPI
212CreateEventExW(
213 IN LPSECURITY_ATTRIBUTES lpEventAttributes,
214 IN LPCWSTR lpName,
215 IN DWORD dwFlags,
216 IN DWORD dwDesiredAccess)
217{
218 return
219 CreateEventW(
220 lpEventAttributes,
221 (dwFlags & CREATE_EVENT_MANUAL_RESET) != 0,
222 (dwFlags & CREATE_EVENT_INITIAL_SET) != 0,
223 lpName);
224}
225
226/*++
227Function:
228 InternalCreateEvent
229
230Note:
231 lpEventAttributes currentely ignored:
232 -- Win32 object security not supported
233 -- handles to event objects are not inheritable
234
235Parameters:
236 pthr -- thread data for calling thread
237 phEvent -- on success, receives the allocated event handle
238
239 See MSDN docs on CreateEvent for all other parameters
240--*/
241
242PAL_ERROR
243CorUnix::InternalCreateEvent(
244 CPalThread *pthr,
245 LPSECURITY_ATTRIBUTES lpEventAttributes,
246 BOOL bManualReset,
247 BOOL bInitialState,
248 LPCWSTR lpName,
249 HANDLE *phEvent
250 )
251{
252 CObjectAttributes oa(lpName, lpEventAttributes);
253 PAL_ERROR palError = NO_ERROR;
254 IPalObject *pobjEvent = NULL;
255 IPalObject *pobjRegisteredEvent = NULL;
256
257 _ASSERTE(NULL != pthr);
258 _ASSERTE(NULL != phEvent);
259
260 ENTRY("InternalCreateEvent(pthr=%p, lpEventAttributes=%p, bManualReset=%i, "
261 "bInitialState=%i, lpName=%p, phEvent=%p)\n",
262 pthr,
263 lpEventAttributes,
264 bManualReset,
265 bInitialState,
266 lpName,
267 phEvent
268 );
269
270 if (lpName != nullptr)
271 {
272 ASSERT("lpName: Cross-process named objects are not supported in PAL");
273 palError = ERROR_NOT_SUPPORTED;
274 goto InternalCreateEventExit;
275 }
276
277 palError = g_pObjectManager->AllocateObject(
278 pthr,
279 bManualReset ? &otManualResetEvent : &otAutoResetEvent,
280 &oa,
281 &pobjEvent
282 );
283
284 if (NO_ERROR != palError)
285 {
286 goto InternalCreateEventExit;
287 }
288
289 if (bInitialState)
290 {
291 ISynchStateController *pssc;
292
293 palError = pobjEvent->GetSynchStateController(
294 pthr,
295 &pssc
296 );
297
298 if (NO_ERROR == palError)
299 {
300 palError = pssc->SetSignalCount(1);
301 pssc->ReleaseController();
302 }
303
304 if (NO_ERROR != palError)
305 {
306 ASSERT("Unable to set new event state (%d)\n", palError);
307 goto InternalCreateEventExit;
308 }
309 }
310
311 palError = g_pObjectManager->RegisterObject(
312 pthr,
313 pobjEvent,
314 &aotEvent,
315 EVENT_ALL_ACCESS, // Currently ignored (no Win32 security)
316 phEvent,
317 &pobjRegisteredEvent
318 );
319
320 //
321 // pobjEvent is invalidated by the call to RegisterObject, so NULL it
322 // out here to ensure that we don't try to release a reference on
323 // it down the line.
324 //
325
326 pobjEvent = NULL;
327
328InternalCreateEventExit:
329
330 if (NULL != pobjEvent)
331 {
332 pobjEvent->ReleaseReference(pthr);
333 }
334
335 if (NULL != pobjRegisteredEvent)
336 {
337 pobjRegisteredEvent->ReleaseReference(pthr);
338 }
339
340 LOGEXIT("InternalCreateEvent returns %i\n", palError);
341
342 return palError;
343}
344
345
346/*++
347Function:
348 SetEvent
349
350See MSDN doc.
351--*/
352
353BOOL
354PALAPI
355SetEvent(
356 IN HANDLE hEvent)
357{
358 PAL_ERROR palError = NO_ERROR;
359 CPalThread *pthr = NULL;
360
361 PERF_ENTRY(SetEvent);
362 ENTRY("SetEvent(hEvent=%p)\n", hEvent);
363
364 pthr = InternalGetCurrentThread();
365
366 palError = InternalSetEvent(pthr, hEvent, TRUE);
367
368 if (NO_ERROR != palError)
369 {
370 pthr->SetLastError(palError);
371 }
372
373 LOGEXIT("SetEvent returns BOOL %d\n", (NO_ERROR == palError));
374 PERF_EXIT(SetEvent);
375 return (NO_ERROR == palError);
376}
377
378
379/*++
380Function:
381 ResetEvent
382
383See MSDN doc.
384--*/
385
386BOOL
387PALAPI
388ResetEvent(
389 IN HANDLE hEvent)
390{
391 PAL_ERROR palError = NO_ERROR;
392 CPalThread *pthr = NULL;
393
394 PERF_ENTRY(ResetEvent);
395 ENTRY("ResetEvent(hEvent=%p)\n", hEvent);
396
397 pthr = InternalGetCurrentThread();
398
399 palError = InternalSetEvent(pthr, hEvent, FALSE);
400
401 if (NO_ERROR != palError)
402 {
403 pthr->SetLastError(palError);
404 }
405
406 LOGEXIT("ResetEvent returns BOOL %d\n", (NO_ERROR == palError));
407 PERF_EXIT(ResetEvent);
408 return (NO_ERROR == palError);
409}
410
411/*++
412Function:
413 InternalCreateEvent
414
415Parameters:
416 pthr -- thread data for calling thread
417 hEvent -- handle to the event to set
418 fSetEvent -- if TRUE, set the event; if FALSE, reset it
419--*/
420
421PAL_ERROR
422CorUnix::InternalSetEvent(
423 CPalThread *pthr,
424 HANDLE hEvent,
425 BOOL fSetEvent
426 )
427{
428 PAL_ERROR palError = NO_ERROR;
429 IPalObject *pobjEvent = NULL;
430 ISynchStateController *pssc = NULL;
431
432 _ASSERTE(NULL != pthr);
433
434 ENTRY("InternalSetEvent(pthr=%p, hEvent=%p, fSetEvent=%i\n",
435 pthr,
436 hEvent,
437 fSetEvent
438 );
439
440 palError = g_pObjectManager->ReferenceObjectByHandle(
441 pthr,
442 hEvent,
443 &aotEvent,
444 0, // Should be EVENT_MODIFY_STATE; currently ignored (no Win32 security)
445 &pobjEvent
446 );
447
448 if (NO_ERROR != palError)
449 {
450 ERROR("Unable to obtain object for handle %p (error %d)!\n", hEvent, palError);
451 goto InternalSetEventExit;
452 }
453
454 palError = pobjEvent->GetSynchStateController(
455 pthr,
456 &pssc
457 );
458
459 if (NO_ERROR != palError)
460 {
461 ASSERT("Error %d obtaining synch state controller\n", palError);
462 goto InternalSetEventExit;
463 }
464
465 palError = pssc->SetSignalCount(fSetEvent ? 1 : 0);
466
467 if (NO_ERROR != palError)
468 {
469 ASSERT("Error %d setting event state\n", palError);
470 goto InternalSetEventExit;
471 }
472
473InternalSetEventExit:
474
475 if (NULL != pssc)
476 {
477 pssc->ReleaseController();
478 }
479
480 if (NULL != pobjEvent)
481 {
482 pobjEvent->ReleaseReference(pthr);
483 }
484
485 LOGEXIT("InternalSetEvent returns %d\n", palError);
486
487 return palError;
488}
489
490// TODO: Implementation of OpenEventA() doesn't exist, do we need it? More generally, do we need the A versions at all?
491
492/*++
493Function:
494 OpenEventW
495
496Note:
497 dwDesiredAccess is currently ignored (no Win32 object security support)
498 bInheritHandle is currently ignored (handles to events are not inheritable)
499
500Parameters:
501 See MSDN doc.
502--*/
503
504HANDLE
505PALAPI
506OpenEventW(
507 IN DWORD dwDesiredAccess,
508 IN BOOL bInheritHandle,
509 IN LPCWSTR lpName)
510{
511 HANDLE hEvent = NULL;
512 PAL_ERROR palError = NO_ERROR;
513 CPalThread *pthr = NULL;
514
515 PERF_ENTRY(OpenEventW);
516 ENTRY("OpenEventW(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%S))\n",
517 dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:W16_NULLSTRING);
518
519 pthr = InternalGetCurrentThread();
520
521 /* validate parameters */
522 if (lpName == nullptr)
523 {
524 ERROR("name is NULL\n");
525 palError = ERROR_INVALID_PARAMETER;
526 goto OpenEventWExit;
527 }
528 else
529 {
530 ASSERT("lpName: Cross-process named objects are not supported in PAL");
531 palError = ERROR_NOT_SUPPORTED;
532 }
533
534OpenEventWExit:
535
536 if (NO_ERROR != palError)
537 {
538 pthr->SetLastError(palError);
539 }
540
541 LOGEXIT("OpenEventW returns HANDLE %p\n", hEvent);
542 PERF_EXIT(OpenEventW);
543
544 return hEvent;
545}