diff options
Diffstat (limited to 'src/pal/src/synchobj/event.cpp')
-rw-r--r-- | src/pal/src/synchobj/event.cpp | 589 |
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; +} + |