diff options
Diffstat (limited to 'src/pal/src/include/pal/corunix.hpp')
-rw-r--r-- | src/pal/src/include/pal/corunix.hpp | 1359 |
1 files changed, 1359 insertions, 0 deletions
diff --git a/src/pal/src/include/pal/corunix.hpp b/src/pal/src/include/pal/corunix.hpp new file mode 100644 index 0000000000..e9e9503ed3 --- /dev/null +++ b/src/pal/src/include/pal/corunix.hpp @@ -0,0 +1,1359 @@ +// 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: + + corunix.hpp + +Abstract: + + Internal interface and object definitions + + + +--*/ + +#ifndef _CORUNIX_H +#define _CORUNIX_H + +#include "palinternal.h" + +namespace CorUnix +{ + typedef DWORD PAL_ERROR; + + // + // Forward declarations for classes defined in other headers + // + + class CPalThread; + + // + // Forward declarations for items in this header + // + + class CObjectType; + class IPalObject; + + // + // A simple counted string class. Using counted strings + // allows for some optimizations when searching for a matching string. + // + + class CPalString + { + protected: + + const WCHAR *m_pwsz; // NULL terminated + + // + // Length of string, not including terminating NULL + // + + DWORD m_dwStringLength; + + // + // Length of buffer backing string; must be at least 1+dwStringLength + // + + DWORD m_dwMaxLength; + + public: + + CPalString() + : + m_pwsz(NULL), + m_dwStringLength(0), + m_dwMaxLength(0) + { + }; + + CPalString( + const WCHAR *pwsz + ) + { + SetString(pwsz); + }; + + void + SetString( + const WCHAR *pwsz + ) + { + SetStringWithLength(pwsz, PAL_wcslen(pwsz)); + }; + + void + SetStringWithLength( + const WCHAR *pwsz, + DWORD dwStringLength + ) + { + m_pwsz = pwsz; + m_dwStringLength = dwStringLength; + m_dwMaxLength = m_dwStringLength + 1; + + }; + + PAL_ERROR + CopyString( + CPalString *psSource + ); + + void + FreeBuffer(); + + const WCHAR * + GetString() + { + return m_pwsz; + }; + + DWORD + GetStringLength() + { + return m_dwStringLength; + }; + + DWORD + GetMaxLength() + { + return m_dwMaxLength; + }; + + }; + + // + // Signature of the cleanup routine that is to be called for an object + // type when: + // 1) The object's refcount drops to 0 + // 2) A process is shutting down + // 3) A process has released all local references to the object + // + // The cleanup routine must only cleanup the object's shared state + // when the last parameter (fCleanupSharedSate) is TRUE. When + // fCleanupSharedState is FALSE the cleanup routine must not attempt + // to access the shared data for the object, as another process may + // have already deleted it. ($$REIVEW -- would someone ever need access + // to the shared data in order to cleanup process local state?) + // + // When the third paramter (fShutdown) is TRUE the process is in + // the act of exiting. The cleanup routine should not perform any + // unnecessary cleanup operations (e.g., closing file descriptors, + // since the OS will automatically close them when the process exits) + // in this situation. + // + + typedef void (*OBJECTCLEANUPROUTINE) ( + CPalThread *, // pThread + IPalObject *, // pObjectToCleanup + bool, // fShutdown + bool // fCleanupSharedState + ); + + // + // Signature of the initialization routine that is to be called + // when the first reference within a process to an existing + // object comes into existence. This routine is responsible for + // initializing the object's process local data, based on the + // immutable and shared data. The thread that this routine is + // called on holds an implicit read lock on the shared data. + // + + typedef PAL_ERROR (*OBJECTINITROUTINE) ( + CPalThread *, // pThread + CObjectType *, // pObjectType + void *, // pImmutableData + void *, // pSharedData + void * // pProcessLocalData + ); + + enum PalObjectTypeId + { + otiAutoResetEvent = 0, + otiManualResetEvent, + otiMutex, + otiNamedMutex, + otiSemaphore, + otiFile, + otiFileMapping, + otiSocket, + otiProcess, + otiThread, + otiIOCompletionPort, + ObjectTypeIdCount // This entry must come last in the enumeration + }; + + // + // There should be one instance of CObjectType for each supported + // type in a process; this allows for pointer equality tests + // to be used (though in general it's probably better to use + // checks based on the type ID). All members of this structure are + // immutable. + // + // The data size members control how much space will be allocated for + // instances of this object. Any or all of those members may be 0. + // + // dwSupportedAccessRights is the mask of valid access bits for this + // object type. Supported generic rights should not be included in + // this member. + // + // The generic access rights mapping (structure TBD) defines how the + // supported generic access rights (e.g., GENERIC_READ) map to the + // specific access rights for this object type. + // + // If instances of this object may have a security descriptor set on + // them eSecuritySupport should be set to SecuritySupported. If the OS can + // persist security information for the object type (as would be the case + // for, say, files) eSecurityPersistence should be set to + // OSPersistedSecurityInfo. + // + // If the object may have a name eObjectNameSupport should be + // ObjectCanHaveName. A named object can be opened in more than one + // process. + // + // If it is possible to duplicate a handle to an object across process + // boundaries then eHandleDuplicationSupport should be set to + // CrossProcessDuplicationAllowed. Note that it is possible to have + // an object type where eObjectNameSupport is ObjectCanHaveName and + // eHandleDuplicationSupport is LocalDuplicationOnly. For these object + // types an unnamed object instance will only have references from + // the creating process. + // + // If the object may be waited on eSynchronizationSupport should be + // WaitableObject. (Note that this implies that object type supports + // the SYNCHRONIZE access right.) + // + // The remaining members describe the wait-object semantics for the + // object type when eSynchronizationSupport is WaitableObject: + // + // * eSignalingSemantics: SingleTransitionObject for objects that, once + // they transition to the signaled state, can never transition back to + // the unsignaled state (e.g., processes and threads) + // + // * eThreadReleaseSemantics: if ThreadReleaseAltersSignalCount the object's + // signal count is decremented when a waiting thread is released; otherwise, + // the signal count is not modified (as is desired for a manual reset event). + // Must be ThreadReleaseHasNoSideEffects if eSignalingSemantics is + // SingleTransitionObject + // + // * eOwnershipSemantics: OwnershipTracked only for mutexes, for which the + // previous two items must also ObjectCanBeUnsignaled and + // ThreadReleaseAltersSignalCount. + // + + class CObjectType + { + public: + + enum SecuritySupport + { + SecuritySupported, + SecurityNotSupported + }; + + enum SecurityPersistence + { + OSPersistedSecurityInfo, + SecurityInfoNotPersisted + }; + + enum ObjectNameSupport + { + ObjectCanHaveName, + UnnamedObject + }; + + enum HandleDuplicationSupport + { + CrossProcessDuplicationAllowed, + LocalDuplicationOnly + }; + + enum SynchronizationSupport + { + WaitableObject, + UnwaitableObject + }; + + enum SignalingSemantics + { + ObjectCanBeUnsignaled, + SingleTransitionObject, + SignalingNotApplicable + }; + + enum ThreadReleaseSemantics + { + ThreadReleaseAltersSignalCount, + ThreadReleaseHasNoSideEffects, + ThreadReleaseNotApplicable + }; + + enum OwnershipSemantics + { + OwnershipTracked, + NoOwner, + OwnershipNotApplicable + }; + + private: + + // + // Array that maps object type IDs to the corresponding + // CObjectType instance + // + + static CObjectType* s_rgotIdMapping[]; + + PalObjectTypeId m_eTypeId; + OBJECTCLEANUPROUTINE m_pCleanupRoutine; + OBJECTINITROUTINE m_pInitRoutine; + DWORD m_dwImmutableDataSize; + DWORD m_dwProcessLocalDataSize; + DWORD m_dwSharedDataSize; + DWORD m_dwSupportedAccessRights; + // Generic access rights mapping + SecuritySupport m_eSecuritySupport; + SecurityPersistence m_eSecurityPersistence; + ObjectNameSupport m_eObjectNameSupport; + HandleDuplicationSupport m_eHandleDuplicationSupport; + SynchronizationSupport m_eSynchronizationSupport; + SignalingSemantics m_eSignalingSemantics; + ThreadReleaseSemantics m_eThreadReleaseSemantics; + OwnershipSemantics m_eOwnershipSemantics; + + public: + + CObjectType( + PalObjectTypeId eTypeId, + OBJECTCLEANUPROUTINE pCleanupRoutine, + OBJECTINITROUTINE pInitRoutine, + DWORD dwImmutableDataSize, + DWORD dwProcessLocalDataSize, + DWORD dwSharedDataSize, + DWORD dwSupportedAccessRights, + SecuritySupport eSecuritySupport, + SecurityPersistence eSecurityPersistence, + ObjectNameSupport eObjectNameSupport, + HandleDuplicationSupport eHandleDuplicationSupport, + SynchronizationSupport eSynchronizationSupport, + SignalingSemantics eSignalingSemantics, + ThreadReleaseSemantics eThreadReleaseSemantics, + OwnershipSemantics eOwnershipSemantics + ) + : + m_eTypeId(eTypeId), + m_pCleanupRoutine(pCleanupRoutine), + m_pInitRoutine(pInitRoutine), + m_dwImmutableDataSize(dwImmutableDataSize), + m_dwProcessLocalDataSize(dwProcessLocalDataSize), + m_dwSharedDataSize(dwSharedDataSize), + m_dwSupportedAccessRights(dwSupportedAccessRights), + m_eSecuritySupport(eSecuritySupport), + m_eSecurityPersistence(eSecurityPersistence), + m_eObjectNameSupport(eObjectNameSupport), + m_eHandleDuplicationSupport(eHandleDuplicationSupport), + m_eSynchronizationSupport(eSynchronizationSupport), + m_eSignalingSemantics(eSignalingSemantics), + m_eThreadReleaseSemantics(eThreadReleaseSemantics), + m_eOwnershipSemantics(eOwnershipSemantics) + { + s_rgotIdMapping[eTypeId] = this; + }; + + static + CObjectType * + GetObjectTypeById( + PalObjectTypeId otid + ) + { + return s_rgotIdMapping[otid]; + }; + + PalObjectTypeId + GetId( + void + ) + { + return m_eTypeId; + }; + + OBJECTCLEANUPROUTINE + GetObjectCleanupRoutine( + void + ) + { + return m_pCleanupRoutine; + }; + + OBJECTINITROUTINE + GetObjectInitRoutine( + void + ) + { + return m_pInitRoutine; + }; + + DWORD + GetImmutableDataSize( + void + ) + { + return m_dwImmutableDataSize; + }; + + DWORD + GetProcessLocalDataSize( + void + ) + { + return m_dwProcessLocalDataSize; + }; + + DWORD + GetSharedDataSize( + void + ) + { + return m_dwSharedDataSize; + }; + + DWORD + GetSupportedAccessRights( + void + ) + { + return m_dwSupportedAccessRights; + }; + + // Generic access rights mapping + + SecuritySupport + GetSecuritySupport( + void + ) + { + return m_eSecuritySupport; + }; + + SecurityPersistence + GetSecurityPersistence( + void + ) + { + return m_eSecurityPersistence; + }; + + ObjectNameSupport + GetObjectNameSupport( + void + ) + { + return m_eObjectNameSupport; + }; + + HandleDuplicationSupport + GetHandleDuplicationSupport( + void + ) + { + return m_eHandleDuplicationSupport; + }; + + SynchronizationSupport + GetSynchronizationSupport( + void + ) + { + return m_eSynchronizationSupport; + }; + + SignalingSemantics + GetSignalingSemantics( + void + ) + { + return m_eSignalingSemantics; + }; + + ThreadReleaseSemantics + GetThreadReleaseSemantics( + void + ) + { + return m_eThreadReleaseSemantics; + }; + + OwnershipSemantics + GetOwnershipSemantics( + void + ) + { + return m_eOwnershipSemantics; + }; + }; + + class CAllowedObjectTypes + { + private: + + bool m_rgfAllowedTypes[ObjectTypeIdCount]; + + public: + + bool + IsTypeAllowed(PalObjectTypeId eTypeId); + + // + // Constructor for multiple allowed types + // + + CAllowedObjectTypes( + PalObjectTypeId rgAllowedTypes[], + DWORD dwAllowedTypeCount + ); + + // + // Single allowed type constructor + // + + CAllowedObjectTypes( + PalObjectTypeId eAllowedType + ); + + // + // Allow all types or no types constructor + // + + CAllowedObjectTypes( + bool fAllowAllObjectTypes + ) + { + for (DWORD dw = 0; dw < ObjectTypeIdCount; dw += 1) + { + m_rgfAllowedTypes[dw] = fAllowAllObjectTypes; + } + }; + + ~CAllowedObjectTypes() + { + }; + }; + + // + // Attributes for a given object instance. If the object does not have + // a name the sObjectName member should be zero'd out. If the default + // security attributes are desired then pSecurityAttributes should + // be NULL. + // + + class CObjectAttributes + { + public: + + CPalString sObjectName; + LPSECURITY_ATTRIBUTES pSecurityAttributes; + + CObjectAttributes( + const WCHAR *pwszObjectName, + LPSECURITY_ATTRIBUTES pSecurityAttributes_ + ) + : + pSecurityAttributes(pSecurityAttributes_) + { + if (NULL != pwszObjectName) + { + sObjectName.SetString(pwszObjectName); + } + }; + + CObjectAttributes() + : + pSecurityAttributes(NULL) + { + }; + }; + + // + // ISynchStateController is used to modify any object's synchronization + // state. It is intended to be used from within the APIs exposed for + // various objects (e.g., SetEvent, ReleaseMutex, etc.). + // + // Each ISynchStateController instance implicitly holds what should be + // viewed as the global dispatcher lock, and as such should be released + // as quickly as possible. An ISynchStateController instance is bound to + // the thread that requested it; it may not be passed to a different + // thread. + // + + class ISynchStateController + { + public: + + virtual + PAL_ERROR + GetSignalCount( + LONG *plSignalCount + ) = 0; + + virtual + PAL_ERROR + SetSignalCount( + LONG lNewCount + ) = 0; + + virtual + PAL_ERROR + IncrementSignalCount( + LONG lAmountToIncrement + ) = 0; + + virtual + PAL_ERROR + DecrementSignalCount( + LONG lAmountToDecrement + ) = 0; + + // + // The following two routines may only be used for object types + // where eOwnershipSemantics is OwnershipTracked (i.e., mutexes). + // + + // + // SetOwner is intended to be used in the implementation of + // CreateMutex when bInitialOwner is TRUE. It must be called + // before the new object instance is registered with the + // handle manager. Any other call to this method is an error. + // + + virtual + PAL_ERROR + SetOwner( + CPalThread *pNewOwningThread + ) = 0; + + // + // DecrementOwnershipCount returns an error if the object + // is unowned, or if the thread this controller is bound to + // is not the owner of the object. + // + + virtual + PAL_ERROR + DecrementOwnershipCount( + void + ) = 0; + + virtual + void + ReleaseController( + void + ) = 0; + }; + + // + // ISynchWaitController is used to indicate a thread's desire to wait for + // an object (which possibly includes detecting instances where the wait + // can be satisfied without blocking). It is intended to be used by object + // wait function (WaitForSingleObject, etc.). + // + // Each ISynchWaitController instance implicitly holds what should be + // viewed as the global dispatcher lock, and as such should be released + // as quickly as possible. An ISynchWaitController instance is bound to + // the thread that requested it; it may not be passed to a different + // thread. + // + // A thread may hold multiple ISynchWaitController instances + // simultaneously. + // + + enum WaitType + { + SingleObject, + MultipleObjectsWaitOne, + MultipleObjectsWaitAll + }; + + class ISynchWaitController + { + public: + + // + // CanThreadWaitWithoutBlocking informs the caller if a wait + // operation may succeed immediately, but does not actually + // alter any object state. ReleaseWaitingThreadWithoutBlocking + // alters the object state, and will return an error if it is + // not possible for the wait to be immediately satisfied. + // + + virtual + PAL_ERROR + CanThreadWaitWithoutBlocking( + bool *pfCanWaitWithoutBlocking, // OUT + bool *pfAbandoned + ) = 0; + + virtual + PAL_ERROR + ReleaseWaitingThreadWithoutBlocking( + ) = 0; + + // + // dwIndex is intended for MultipleObjectsWaitOne situations. The + // index for the object that becomes signaled and satisfies the + // wait will be returned in the call to BlockThread. + // + + virtual + PAL_ERROR + RegisterWaitingThread( + WaitType eWaitType, + DWORD dwIndex, + bool fAltertable + ) = 0; + + // + // Why is there no unregister waiting thread routine? Unregistration + // is the responsibility of the synchronization provider, not the + // implementation of the wait object routines. (I can be convinced + // that this isn't the best approach, though...) + // + + virtual + void + ReleaseController( + void + ) = 0; + }; + + enum LockType + { + ReadLock, + WriteLock + }; + + class IDataLock + { + public: + + // + // If a thread obtains a write lock but does not actually + // modify any data it should set fDataChanged to FALSE. If + // a thread obtain a read lock and does actually modify any + // data it should be taken out back and shot. + // + + virtual + void + ReleaseLock( + CPalThread *pThread, // IN, OPTIONAL + bool fDataChanged + ) = 0; + }; + + // + // The following two enums are part of the local object + // optimizations + // + + enum ObjectDomain + { + ProcessLocalObject, + SharedObject + }; + + enum WaitDomain + { + LocalWait, // All objects in the wait set are local to this process + MixedWait, // Some objects are local; some are shared + SharedWait // All objects in the wait set are shared + }; + + class IPalObject + { + public: + + virtual + CObjectType * + GetObjectType( + VOID + ) = 0; + + virtual + CObjectAttributes * + GetObjectAttributes( + VOID + ) = 0; + + virtual + PAL_ERROR + GetImmutableData( + void **ppvImmutableData // OUT + ) = 0; + + // + // The following two routines obtain either a read or write + // lock on the data in question. If a thread needs to examine + // both process-local and shared data simultaneously it must obtain + // the shared data first. A thread may not hold data locks + // on two different objects at the same time. + // + + virtual + PAL_ERROR + GetProcessLocalData( + CPalThread *pThread, // IN, OPTIONAL + LockType eLockRequest, + IDataLock **ppDataLock, // OUT + void **ppvProcessLocalData // OUT + ) = 0; + + virtual + PAL_ERROR + GetSharedData( + CPalThread *pThread, // IN, OPTIONAL + LockType eLockRequest, + IDataLock **ppDataLock, // OUT + void **ppvSharedData // OUT + ) = 0; + + // + // The following two routines obtain the global dispatcher lock. + // If a thread needs to make use of a synchronization interface + // and examine object data it must obtain the synchronization + // interface first. A thread is allowed to hold synchronization + // interfaces for multiple objects at the same time if it obtains + // all of the interfaces through a single call (see IPalSynchronizationManager + // below). + // + // The single-call restriction allows the underlying implementation + // to possibly segement the global dispatcher lock. If this restriction + // were not in place (i.e., if a single thread were allowed to call + // GetSynchXXXController for multiple objects) no such segmentation + // would be possible as there would be no way know in what order a + // thread would choose to obtain the controllers. + // + // Note: this design precludes simultaneous acquisition of both + // the state and wait controller for an object but there are + // currently no places where doing so would be necessary. + // + + virtual + PAL_ERROR + GetSynchStateController( + CPalThread *pThread, // IN, OPTIONAL + ISynchStateController **ppStateController // OUT + ) = 0; + + virtual + PAL_ERROR + GetSynchWaitController( + CPalThread *pThread, // IN, OPTIONAL + ISynchWaitController **ppWaitController // OUT + ) = 0; + + virtual + DWORD + AddReference( + void + ) = 0; + + virtual + DWORD + ReleaseReference( + CPalThread *pThread + ) = 0; + + // + // This routine is mainly intended for the synchronization + // manager. The promotion / process synch lock must be held + // before calling this routine. + // + + virtual + ObjectDomain + GetObjectDomain( + void + ) = 0; + + // + // This routine is only for use by the synchronization manager + // (specifically, for GetSynch*ControllersForObjects). The + // caller must have acquired the appropriate lock before + // (whatever exactly that must be) before calling this routine. + // + + virtual + PAL_ERROR + GetObjectSynchData( + VOID **ppvSynchData // OUT + ) = 0; + + }; + + class IPalProcess + { + public: + virtual + DWORD + GetProcessID( + void + ) = 0; + }; + + class IPalObjectManager + { + public: + + // + // Object creation (e.g., what is done by CreateEvent) is a two step + // process. First, the new object is allocated and the initial + // properties set (e.g., initially signaled). Next, the object is + // registered, yielding a handle. If an object of the same name + // and appropriate type already existed the returned handle will refer + // to the previously existing object, and the newly allocated object + // will have been thrown away. + // + // (The two phase process minimizes the amount of time that any + // namespace locks need to be held. While some wasted work may be + // done in the existing object case that work only impacts the calling + // thread. Checking first for existence and then allocating and + // initializing on failure requires any namespace lock to be held for + // a much longer period of time, impacting the entire system.) + // + + virtual + PAL_ERROR + AllocateObject( + CPalThread *pThread, // IN, OPTIONAL + CObjectType *pType, + CObjectAttributes *pAttributes, + IPalObject **ppNewObject // OUT + ) = 0; + + // + // After calling RegisterObject pObjectToRegister is no + // longer valid. If successful there are two references + // on the returned object -- one for the handle, and one + // for the instance returned in ppRegisteredObject. The + // caller, therefore, is responsible for releasing the + // latter. + // + // For named object pAllowedTypes specifies what type of + // existing objects can be returned in ppRegisteredObjects. + // This is primarily intended for CreateEvent, so that + // a ManualResetEvent can be returned when attempting to + // register an AutoResetEvent (and vice-versa). pAllowedTypes + // must include the type of pObjectToRegister. + // + + virtual + PAL_ERROR + RegisterObject( + CPalThread *pThread, // IN, OPTIONAL + IPalObject *pObjectToRegister, + CAllowedObjectTypes *pAllowedTypes, + DWORD dwRightsRequested, + HANDLE *pHandle, // OUT + IPalObject **ppRegisteredObject // OUT + ) = 0; + + // + // LocateObject is used for OpenXXX routines. ObtainHandleForObject + // is needed for the OpenXXX routines and DuplicateHandle. + // + + virtual + PAL_ERROR + LocateObject( + CPalThread *pThread, // IN, OPTIONAL + CPalString *psObjectToLocate, + CAllowedObjectTypes *pAllowedTypes, + IPalObject **ppObject // OUT + ) = 0; + + // + // pProcessForHandle is to support cross-process handle + // duplication. It only needs to be specified when acquiring + // a handle meant for use in a different process; it should + // be left NULL when acquiring a handle for the current + // process. + // + + virtual + PAL_ERROR + ObtainHandleForObject( + CPalThread *pThread, // IN, OPTIONAL + IPalObject *pObject, + DWORD dwRightsRequested, + bool fInheritHandle, + IPalProcess *pProcessForHandle, // IN, OPTIONAL + HANDLE *pNewHandle // OUT + ) = 0; + + virtual + PAL_ERROR + RevokeHandle( + CPalThread *pThread, // IN, OPTIONAL + HANDLE hHandleToRevoke + ) = 0; + + // + // The Reference routines are called to obtain the + // object that a handle refers to. The caller must + // specify the rights that the handle must hold for + // the operation that it is about to perform. The caller + // is responsible for converting generic rights to specific + // rights. The caller must also specify what object types + // are permissible for the object. + // + // The returned object[s], on success, are referenced, + // and the caller is responsible for releasing those references + // when appropriate. + // + + virtual + PAL_ERROR + ReferenceObjectByHandle( + CPalThread *pThread, // IN, OPTIONAL + HANDLE hHandleToReference, + CAllowedObjectTypes *pAllowedTypes, + DWORD dwRightsRequired, + IPalObject **ppObject // OUT + ) = 0; + + // + // This routine is intended for WaitForMultipleObjects[Ex] + // + + virtual + PAL_ERROR + ReferenceMultipleObjectsByHandleArray( + CPalThread *pThread, // IN, OPTIONAL + HANDLE rghHandlesToReference[], + DWORD dwHandleCount, + CAllowedObjectTypes *pAllowedTypes, + DWORD dwRightsRequired, + IPalObject *rgpObjects[] // OUT + ) = 0; + + // + // This routine is for cross-process handle duplication. + // + + virtual + PAL_ERROR + ReferenceObjectByForeignHandle( + CPalThread *pThread, // IN, OPTIONAL + HANDLE hForeignHandle, + IPalProcess *pForeignProcess, + CAllowedObjectTypes *pAllowedTypes, + DWORD dwRightsRequired, + IPalObject **ppObject // OUT + ) = 0; + + }; + + extern IPalObjectManager *g_pObjectManager; + + enum ThreadWakeupReason + { + WaitSucceeded, + Alerted, + MutexAbondoned, + WaitTimeout, + WaitFailed + }; + + class IPalSynchronizationManager + { + public: + + // + // A thread calls BlockThread to put itself to sleep after it has + // registered itself with the objects it is to wait on. A thread + // need not have registered with any objects, as would occur in + // the implementation of Sleep[Ex]. + // + // Needless to say a thread must not be holding any PAL locks + // directly or implicitly (e.g., by holding a reference to a + // synchronization controller) when it calls this method. + // + + virtual + PAL_ERROR + BlockThread( + CPalThread *pCurrentThread, + DWORD dwTimeout, + bool fAlertable, + bool fIsSleep, + ThreadWakeupReason *peWakeupReason, // OUT + DWORD *pdwSignaledObject // OUT + ) = 0; + + virtual + PAL_ERROR + AbandonObjectsOwnedByThread( + CPalThread *pCallingThread, + CPalThread *pTargetThread + ) = 0; + + virtual + PAL_ERROR + QueueUserAPC( + CPalThread *pThread, + CPalThread *pTargetThread, + PAPCFUNC pfnAPC, + ULONG_PTR dwData + ) = 0; + + virtual + bool + AreAPCsPending( + CPalThread *pThread + ) = 0; + + virtual + PAL_ERROR + DispatchPendingAPCs( + CPalThread *pThread + ) = 0; + + virtual + PAL_ERROR + SendTerminationRequestToWorkerThread() = 0; + + // + // This routine is primarily meant for use by WaitForMultipleObjects[Ex]. + // The caller must individually release each of the returned controller + // interfaces. + // + + virtual + PAL_ERROR + GetSynchWaitControllersForObjects( + CPalThread *pThread, + IPalObject *rgObjects[], + DWORD dwObjectCount, + ISynchWaitController *rgControllers[] + ) = 0; + + virtual + PAL_ERROR + GetSynchStateControllersForObjects( + CPalThread *pThread, + IPalObject *rgObjects[], + DWORD dwObjectCount, + ISynchStateController *rgControllers[] + ) = 0; + + // + // These following routines are meant for use only by IPalObject + // implementations. The first two routines are used to + // allocate and free an object's synchronization state; the third + // is called during object promotion. + // + + virtual + PAL_ERROR + AllocateObjectSynchData( + CObjectType *pObjectType, + ObjectDomain eObjectDomain, + VOID **ppvSynchData // OUT + ) = 0; + + virtual + void + FreeObjectSynchData( + CObjectType *pObjectType, + ObjectDomain eObjectDomain, + VOID *pvSynchData + ) = 0; + + virtual + PAL_ERROR + PromoteObjectSynchData( + CPalThread *pThread, + VOID *pvLocalSynchData, + VOID **ppvSharedSynchData // OUT + ) = 0; + + // + // The next two routines provide access to the process-wide + // synchronization lock + // + + virtual + void + AcquireProcessLock( + CPalThread *pThread + ) = 0; + + virtual + void + ReleaseProcessLock( + CPalThread *pThread + ) = 0; + + // + // The final routines are used by IPalObject::GetSynchStateController + // and IPalObject::GetSynchWaitController + // + + virtual + PAL_ERROR + CreateSynchStateController( + CPalThread *pThread, // IN, OPTIONAL + CObjectType *pObjectType, + VOID *pvSynchData, + ObjectDomain eObjectDomain, + ISynchStateController **ppStateController // OUT + ) = 0; + + virtual + PAL_ERROR + CreateSynchWaitController( + CPalThread *pThread, // IN, OPTIONAL + CObjectType *pObjectType, + VOID *pvSynchData, + ObjectDomain eObjectDomain, + ISynchWaitController **ppWaitController // OUT + ) = 0; + }; + + extern IPalSynchronizationManager *g_pSynchronizationManager; + + class IFileTransactionLock + { + public: + + // + // Called when the transaction completes (which includes + // error completions, or the outright failure to queue + // the transaction). + // + + virtual + void + ReleaseLock() = 0; + }; + + class IFileLockController + { + public: + + // + // A transaction lock is acquired before a read or write + // operation, and released when that operation completes. + // The lock is not tied to the calling thread, since w/ + // asynch file IO the completion may occur on a different + // thread. + // + + enum FileTransactionLockType + { + ReadLock, + WriteLock + }; + + virtual + PAL_ERROR + GetTransactionLock( + CPalThread *pThread, // IN, OPTIONAL + FileTransactionLockType eLockType, + DWORD dwOffsetLow, + DWORD dwOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + IFileTransactionLock **ppTransactionLock // OUT + ) = 0; + + enum FileLockExclusivity + { + ExclusiveFileLock, + SharedFileLock + }; + + enum FileLockWaitMode + { + FailImmediately, + WaitForLockAcquisition + }; + + virtual + PAL_ERROR + CreateFileLock( + CPalThread *pThread, // IN, OPTIONAL + DWORD dwOffsetLow, + DWORD dwOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + FileLockExclusivity eFileLockExclusivity, + FileLockWaitMode eFileLockWaitMode + ) = 0; + + virtual + PAL_ERROR + ReleaseFileLock( + CPalThread *pThread, // IN, OPTIONAL + DWORD dwOffsetLow, + DWORD dwOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh + ) = 0; + + // + // ReleaseController should be called from the file object's + // cleanup routine. It must always be called, even if fShutdown is + // TRUE or fCleanupSharedState is FALSE. + // + + virtual + void + ReleaseController() = 0; + }; + + class IFileLockManager + { + public: + + // + // GetLockControllerForFile should be called by CreateFile. + // It will fail if the requested access rights and share + // mode are not compatible with existing lock controllers + // for the file. + // + + virtual + PAL_ERROR + GetLockControllerForFile( + CPalThread *pThread, // IN, OPTIONAL + LPCSTR szFileName, + DWORD dwAccessRights, + DWORD dwShareMode, + IFileLockController **ppLockController // OUT + ) = 0; + + // + // Gets the share mode for the file + // (returns SHARE_MODE_NOT_INITIALIZED if file lock controller + // not found) + // + virtual + PAL_ERROR + GetFileShareModeForFile( + LPCSTR szFileName, + DWORD* pdwShareMode) = 0; + }; + + extern IFileLockManager *g_pFileLockManager; +} + +#endif // _CORUNIX_H + |