summaryrefslogtreecommitdiff
path: root/src/pal/src/synchobj/event.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/synchobj/event.cpp')
-rw-r--r--src/pal/src/synchobj/event.cpp589
1 files changed, 589 insertions, 0 deletions
diff --git a/src/pal/src/synchobj/event.cpp b/src/pal/src/synchobj/event.cpp
new file mode 100644
index 0000000000..54addad51c
--- /dev/null
+++ b/src/pal/src/synchobj/event.cpp
@@ -0,0 +1,589 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*++
+
+
+
+Module Name:
+
+ event.cpp
+
+Abstract:
+
+ Implementation of event synchronization object as described in
+ the WIN32 API
+
+Revision History:
+
+
+
+--*/
+
+#include "pal/event.hpp"
+#include "pal/thread.hpp"
+#include "pal/dbgmsg.h"
+
+using namespace CorUnix;
+
+/* ------------------- Definitions ------------------------------*/
+SET_DEFAULT_DEBUG_CHANNEL(SYNC);
+
+CObjectType CorUnix::otManualResetEvent(
+ otiManualResetEvent,
+ NULL, // No cleanup routine
+ NULL, // No initialization routine
+ 0, // No immutable data
+ 0, // No process local data
+ 0, // No shared data
+ EVENT_ALL_ACCESS, // Currently ignored (no Win32 security)
+ CObjectType::SecuritySupported,
+ CObjectType::SecurityInfoNotPersisted,
+ CObjectType::UnnamedObject,
+ CObjectType::LocalDuplicationOnly,
+ CObjectType::WaitableObject,
+ CObjectType::ObjectCanBeUnsignaled,
+ CObjectType::ThreadReleaseHasNoSideEffects,
+ CObjectType::NoOwner
+ );
+
+CObjectType CorUnix::otAutoResetEvent(
+ otiAutoResetEvent,
+ NULL, // No cleanup routine
+ NULL, // No initialization routine
+ 0, // No immutable data
+ 0, // No process local data
+ 0, // No shared data
+ EVENT_ALL_ACCESS, // Currently ignored (no Win32 security)
+ CObjectType::SecuritySupported,
+ CObjectType::SecurityInfoNotPersisted,
+ CObjectType::UnnamedObject,
+ CObjectType::LocalDuplicationOnly,
+ CObjectType::WaitableObject,
+ CObjectType::ObjectCanBeUnsignaled,
+ CObjectType::ThreadReleaseAltersSignalCount,
+ CObjectType::NoOwner
+ );
+
+PalObjectTypeId rgEventIds[] = {otiManualResetEvent, otiAutoResetEvent};
+CAllowedObjectTypes aotEvent(rgEventIds, sizeof(rgEventIds)/sizeof(rgEventIds[0]));
+
+/*++
+Function:
+ CreateEventA
+
+Note:
+ lpEventAttributes currentely ignored:
+ -- Win32 object security not supported
+ -- handles to event objects are not inheritable
+
+Parameters:
+ See MSDN doc.
+--*/
+
+HANDLE
+PALAPI
+CreateEventA(
+ IN LPSECURITY_ATTRIBUTES lpEventAttributes,
+ IN BOOL bManualReset,
+ IN BOOL bInitialState,
+ IN LPCSTR lpName)
+{
+ HANDLE hEvent = NULL;
+ CPalThread *pthr = NULL;
+ PAL_ERROR palError;
+
+ PERF_ENTRY(CreateEventA);
+ ENTRY("CreateEventA(lpEventAttr=%p, bManualReset=%d, bInitialState=%d, lpName=%p (%s)\n",
+ lpEventAttributes, bManualReset, bInitialState, lpName, lpName?lpName:"NULL");
+
+ pthr = InternalGetCurrentThread();
+
+ if (lpName != nullptr)
+ {
+ ASSERT("lpName: Cross-process named objects are not supported in PAL");
+ palError = ERROR_NOT_SUPPORTED;
+ }
+ else
+ {
+ palError = InternalCreateEvent(
+ pthr,
+ lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ NULL,
+ &hEvent
+ );
+ }
+
+ //
+ // We always need to set last error, even on success:
+ // we need to protect ourselves from the situation
+ // where last error is set to ERROR_ALREADY_EXISTS on
+ // entry to the function
+ //
+
+ pthr->SetLastError(palError);
+
+ LOGEXIT("CreateEventA returns HANDLE %p\n", hEvent);
+ PERF_EXIT(CreateEventA);
+ return hEvent;
+}
+
+
+/*++
+Function:
+ CreateEventW
+
+Note:
+ lpEventAttributes currentely ignored:
+ -- Win32 object security not supported
+ -- handles to event objects are not inheritable
+
+Parameters:
+ See MSDN doc.
+--*/
+
+HANDLE
+PALAPI
+CreateEventW(
+ IN LPSECURITY_ATTRIBUTES lpEventAttributes,
+ IN BOOL bManualReset,
+ IN BOOL bInitialState,
+ IN LPCWSTR lpName)
+{
+ HANDLE hEvent = NULL;
+ PAL_ERROR palError;
+ CPalThread *pthr = NULL;
+
+ PERF_ENTRY(CreateEventW);
+ ENTRY("CreateEventW(lpEventAttr=%p, bManualReset=%d, "
+ "bInitialState=%d, lpName=%p (%S)\n", lpEventAttributes, bManualReset,
+ bInitialState, lpName, lpName?lpName:W16_NULLSTRING);
+
+ pthr = InternalGetCurrentThread();
+
+ palError = InternalCreateEvent(
+ pthr,
+ lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ lpName,
+ &hEvent
+ );
+
+ //
+ // We always need to set last error, even on success:
+ // we need to protect ourselves from the situation
+ // where last error is set to ERROR_ALREADY_EXISTS on
+ // entry to the function
+ //
+
+ pthr->SetLastError(palError);
+
+ LOGEXIT("CreateEventW returns HANDLE %p\n", hEvent);
+ PERF_EXIT(CreateEventW);
+ return hEvent;
+}
+
+/*++
+Function:
+ InternalCreateEvent
+
+Note:
+ lpEventAttributes currentely ignored:
+ -- Win32 object security not supported
+ -- handles to event objects are not inheritable
+
+Parameters:
+ pthr -- thread data for calling thread
+ phEvent -- on success, receives the allocated event handle
+
+ See MSDN docs on CreateEvent for all other parameters
+--*/
+
+PAL_ERROR
+CorUnix::InternalCreateEvent(
+ CPalThread *pthr,
+ LPSECURITY_ATTRIBUTES lpEventAttributes,
+ BOOL bManualReset,
+ BOOL bInitialState,
+ LPCWSTR lpName,
+ HANDLE *phEvent
+ )
+{
+ CObjectAttributes oa(lpName, lpEventAttributes);
+ PAL_ERROR palError = NO_ERROR;
+ IPalObject *pobjEvent = NULL;
+ IPalObject *pobjRegisteredEvent = NULL;
+
+ _ASSERTE(NULL != pthr);
+ _ASSERTE(NULL != phEvent);
+
+ ENTRY("InternalCreateEvent(pthr=%p, lpEventAttributes=%p, bManualReset=%i, "
+ "bInitialState=%i, lpName=%p, phEvent=%p)\n",
+ pthr,
+ lpEventAttributes,
+ bManualReset,
+ bInitialState,
+ lpName,
+ phEvent
+ );
+
+ if (lpName != nullptr)
+ {
+ ASSERT("lpName: Cross-process named objects are not supported in PAL");
+ palError = ERROR_NOT_SUPPORTED;
+ goto InternalCreateEventExit;
+ }
+
+ palError = g_pObjectManager->AllocateObject(
+ pthr,
+ bManualReset ? &otManualResetEvent : &otAutoResetEvent,
+ &oa,
+ &pobjEvent
+ );
+
+ if (NO_ERROR != palError)
+ {
+ goto InternalCreateEventExit;
+ }
+
+ if (bInitialState)
+ {
+ ISynchStateController *pssc;
+
+ palError = pobjEvent->GetSynchStateController(
+ pthr,
+ &pssc
+ );
+
+ if (NO_ERROR == palError)
+ {
+ palError = pssc->SetSignalCount(1);
+ pssc->ReleaseController();
+ }
+
+ if (NO_ERROR != palError)
+ {
+ ASSERT("Unable to set new event state (%d)\n", palError);
+ goto InternalCreateEventExit;
+ }
+ }
+
+ palError = g_pObjectManager->RegisterObject(
+ pthr,
+ pobjEvent,
+ &aotEvent,
+ EVENT_ALL_ACCESS, // Currently ignored (no Win32 security)
+ phEvent,
+ &pobjRegisteredEvent
+ );
+
+ //
+ // pobjEvent is invalidated by the call to RegisterObject, so NULL it
+ // out here to ensure that we don't try to release a reference on
+ // it down the line.
+ //
+
+ pobjEvent = NULL;
+
+InternalCreateEventExit:
+
+ if (NULL != pobjEvent)
+ {
+ pobjEvent->ReleaseReference(pthr);
+ }
+
+ if (NULL != pobjRegisteredEvent)
+ {
+ pobjRegisteredEvent->ReleaseReference(pthr);
+ }
+
+ LOGEXIT("InternalCreateEvent returns %i\n", palError);
+
+ return palError;
+}
+
+
+/*++
+Function:
+ SetEvent
+
+See MSDN doc.
+--*/
+
+BOOL
+PALAPI
+SetEvent(
+ IN HANDLE hEvent)
+{
+ PAL_ERROR palError = NO_ERROR;
+ CPalThread *pthr = NULL;
+
+ PERF_ENTRY(SetEvent);
+ ENTRY("SetEvent(hEvent=%p)\n", hEvent);
+
+ pthr = InternalGetCurrentThread();
+
+ palError = InternalSetEvent(pthr, hEvent, TRUE);
+
+ if (NO_ERROR != palError)
+ {
+ pthr->SetLastError(palError);
+ }
+
+ LOGEXIT("SetEvent returns BOOL %d\n", (NO_ERROR == palError));
+ PERF_EXIT(SetEvent);
+ return (NO_ERROR == palError);
+}
+
+
+/*++
+Function:
+ ResetEvent
+
+See MSDN doc.
+--*/
+
+BOOL
+PALAPI
+ResetEvent(
+ IN HANDLE hEvent)
+{
+ PAL_ERROR palError = NO_ERROR;
+ CPalThread *pthr = NULL;
+
+ PERF_ENTRY(ResetEvent);
+ ENTRY("ResetEvent(hEvent=%p)\n", hEvent);
+
+ pthr = InternalGetCurrentThread();
+
+ palError = InternalSetEvent(pthr, hEvent, FALSE);
+
+ if (NO_ERROR != palError)
+ {
+ pthr->SetLastError(palError);
+ }
+
+ LOGEXIT("ResetEvent returns BOOL %d\n", (NO_ERROR == palError));
+ PERF_EXIT(ResetEvent);
+ return (NO_ERROR == palError);
+}
+
+/*++
+Function:
+ InternalCreateEvent
+
+Parameters:
+ pthr -- thread data for calling thread
+ hEvent -- handle to the event to set
+ fSetEvent -- if TRUE, set the event; if FALSE, reset it
+--*/
+
+PAL_ERROR
+CorUnix::InternalSetEvent(
+ CPalThread *pthr,
+ HANDLE hEvent,
+ BOOL fSetEvent
+ )
+{
+ PAL_ERROR palError = NO_ERROR;
+ IPalObject *pobjEvent = NULL;
+ ISynchStateController *pssc = NULL;
+
+ _ASSERTE(NULL != pthr);
+
+ ENTRY("InternalSetEvent(pthr=%p, hEvent=%p, fSetEvent=%i\n",
+ pthr,
+ hEvent,
+ fSetEvent
+ );
+
+ palError = g_pObjectManager->ReferenceObjectByHandle(
+ pthr,
+ hEvent,
+ &aotEvent,
+ 0, // Should be EVENT_MODIFY_STATE; currently ignored (no Win32 security)
+ &pobjEvent
+ );
+
+ if (NO_ERROR != palError)
+ {
+ ERROR("Unable to obtain object for handle %p (error %d)!\n", hEvent, palError);
+ goto InternalSetEventExit;
+ }
+
+ palError = pobjEvent->GetSynchStateController(
+ pthr,
+ &pssc
+ );
+
+ if (NO_ERROR != palError)
+ {
+ ASSERT("Error %d obtaining synch state controller\n", palError);
+ goto InternalSetEventExit;
+ }
+
+ palError = pssc->SetSignalCount(fSetEvent ? 1 : 0);
+
+ if (NO_ERROR != palError)
+ {
+ ASSERT("Error %d setting event state\n", palError);
+ goto InternalSetEventExit;
+ }
+
+InternalSetEventExit:
+
+ if (NULL != pssc)
+ {
+ pssc->ReleaseController();
+ }
+
+ if (NULL != pobjEvent)
+ {
+ pobjEvent->ReleaseReference(pthr);
+ }
+
+ LOGEXIT("InternalSetEvent returns %d\n", palError);
+
+ return palError;
+}
+
+// TODO: Implementation of OpenEventA() doesn't exist, do we need it? More generally, do we need the A versions at all?
+
+/*++
+Function:
+ OpenEventW
+
+Note:
+ dwDesiredAccess is currently ignored (no Win32 object security support)
+ bInheritHandle is currently ignored (handles to events are not inheritable)
+
+Parameters:
+ See MSDN doc.
+--*/
+
+HANDLE
+PALAPI
+OpenEventW(
+ IN DWORD dwDesiredAccess,
+ IN BOOL bInheritHandle,
+ IN LPCWSTR lpName)
+{
+ HANDLE hEvent = NULL;
+ PAL_ERROR palError = NO_ERROR;
+ CPalThread *pthr = NULL;
+
+ PERF_ENTRY(OpenEventW);
+ ENTRY("OpenEventW(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%S))\n",
+ dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:W16_NULLSTRING);
+
+ pthr = InternalGetCurrentThread();
+
+ /* validate parameters */
+ if (lpName == nullptr)
+ {
+ ERROR("name is NULL\n");
+ palError = ERROR_INVALID_PARAMETER;
+ goto OpenEventWExit;
+ }
+ else
+ {
+ ASSERT("lpName: Cross-process named objects are not supported in PAL");
+ palError = ERROR_NOT_SUPPORTED;
+ }
+
+OpenEventWExit:
+
+ if (NO_ERROR != palError)
+ {
+ pthr->SetLastError(palError);
+ }
+
+ LOGEXIT("OpenEventW returns HANDLE %p\n", hEvent);
+ PERF_EXIT(OpenEventW);
+
+ return hEvent;
+}
+
+/*++
+Function:
+ InternalOpenEvent
+
+Note:
+ dwDesiredAccess is currently ignored (no Win32 object security support)
+ bInheritHandle is currently ignored (handles to events are not inheritable)
+
+Parameters:
+ pthr -- thread data for calling thread
+ phEvent -- on success, receives the allocated event handle
+
+ See MSDN docs on OpenEvent for all other parameters.
+--*/
+
+PAL_ERROR
+CorUnix::InternalOpenEvent(
+ CPalThread *pthr,
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ LPCWSTR lpName,
+ HANDLE *phEvent
+ )
+{
+ PAL_ERROR palError = NO_ERROR;
+ IPalObject *pobjEvent = NULL;
+ CPalString sObjectName(lpName);
+
+ _ASSERTE(NULL != pthr);
+ _ASSERTE(NULL != lpName);
+ _ASSERTE(NULL != phEvent);
+
+ ENTRY("InternalOpenEvent(pthr=%p, dwDesiredAccess=%#x, bInheritHandle=%d, "
+ "lpName=%p, phEvent=%p)\n",
+ pthr,
+ dwDesiredAccess,
+ bInheritHandle,
+ lpName,
+ phEvent
+ );
+
+ palError = g_pObjectManager->LocateObject(
+ pthr,
+ &sObjectName,
+ &aotEvent,
+ &pobjEvent
+ );
+
+ if (NO_ERROR != palError)
+ {
+ goto InternalOpenEventExit;
+ }
+
+ palError = g_pObjectManager->ObtainHandleForObject(
+ pthr,
+ pobjEvent,
+ dwDesiredAccess,
+ bInheritHandle,
+ NULL,
+ phEvent
+ );
+
+ if (NO_ERROR != palError)
+ {
+ goto InternalOpenEventExit;
+ }
+
+InternalOpenEventExit:
+
+ if (NULL != pobjEvent)
+ {
+ pobjEvent->ReleaseReference(pthr);
+ }
+
+ LOGEXIT("InternalOpenEvent returns %d\n", palError);
+
+ return palError;
+}
+