mirror of
https://github.com/reactos/reactos.git
synced 2026-06-22 03:12:49 +08:00
- Start partial implementation of Executive Lightweight Callbacks: ExAllocateCallBack, ExInitializeCallBack, ExFreeCallBack, ExWaitForCallBacks, ExGetCallBackBlockRoutine, ExGetcallBackBlockContext, ExDoCallBack.
- Stub ExReferenceCallBackBlock and ExDereferenceCallBackBlock until I get the locking right. - These callbacks are used by Cm as well as Ps inside Windows NT and combine the power of PushLocks, Rundown Protection and Fast Referencing to ensure callbacks only get called once and thread safely. Not yet used in ROS. svn path=/trunk/; revision=25483
This commit is contained in:
@@ -514,7 +514,7 @@ typedef struct _CALLBACK_REGISTRATION
|
||||
typedef struct _EX_CALLBACK_ROUTINE_BLOCK
|
||||
{
|
||||
EX_RUNDOWN_REF RundownProtect;
|
||||
PVOID Function;
|
||||
PEX_CALLBACK_FUNCTION Function;
|
||||
PVOID Context;
|
||||
} EX_CALLBACK_ROUTINE_BLOCK, *PEX_CALLBACK_ROUTINE_BLOCK;
|
||||
|
||||
|
||||
@@ -40,6 +40,110 @@ KEVENT ExpCallbackEvent;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExInitializeCallback(IN OUT PEX_CALLBACK Callback)
|
||||
{
|
||||
/* Initialize the fast references */
|
||||
Callback->RoutineBlock.Object = NULL;
|
||||
}
|
||||
|
||||
PEX_CALLBACK_ROUTINE_BLOCK
|
||||
NTAPI
|
||||
ExAllocateCallBack(IN PEX_CALLBACK_FUNCTION Function,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PEX_CALLBACK_ROUTINE_BLOCK Callback;
|
||||
|
||||
/* Allocate a callback */
|
||||
Callback = ExAllocatePoolWithTag(PagedPool,
|
||||
sizeof(*Callback),
|
||||
TAG('C', 'b', 'r', 'b'));
|
||||
if (Callback)
|
||||
{
|
||||
/* Initialize it */
|
||||
Callback->Function = Function;
|
||||
Callback->Context = Context;
|
||||
ExInitializeRundownProtection(&Callback->RundownProtect);
|
||||
}
|
||||
|
||||
/* Return it */
|
||||
return Callback;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExFreeCallback(IN PEX_CALLBACK_ROUTINE_BLOCK Callback)
|
||||
{
|
||||
/* Just free it from memory */
|
||||
ExFreePool(Callback);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExWaitForCallBacks(IN PEX_CALLBACK_ROUTINE_BLOCK Callback)
|
||||
{
|
||||
/* Wait on the rundown */
|
||||
ExWaitForRundownProtectionRelease(&Callback->RundownProtect);
|
||||
}
|
||||
|
||||
PEX_CALLBACK_FUNCTION
|
||||
NTAPI
|
||||
ExGetCallBackBlockRoutine(IN PEX_CALLBACK_ROUTINE_BLOCK Callback)
|
||||
{
|
||||
/* Return the function */
|
||||
return Callback->Function;
|
||||
}
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
ExGetCallBackBlockContext(IN PEX_CALLBACK_ROUTINE_BLOCK Callback)
|
||||
{
|
||||
/* Return the context */
|
||||
return Callback->Context;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExDereferenceCallBackBlock(IN OUT PEX_CALLBACK CallBack,
|
||||
IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock)
|
||||
{
|
||||
/* FIXME: TODO */
|
||||
}
|
||||
|
||||
PEX_CALLBACK_ROUTINE_BLOCK
|
||||
NTAPI
|
||||
ExReferenceCallBackBlock(IN OUT PEX_CALLBACK CallBack)
|
||||
{
|
||||
/* FIXME: TODO */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI // FIXME: FORCEINLINE AFTER TESTING!
|
||||
ExDoCallBack(IN OUT PEX_CALLBACK Callback,
|
||||
IN PVOID Context,
|
||||
IN PVOID Argument1,
|
||||
IN PVOID Argument2)
|
||||
{
|
||||
PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock;
|
||||
PEX_CALLBACK_FUNCTION Function;
|
||||
|
||||
/* Reference the block */
|
||||
CallbackRoutineBlock = ExReferenceCallBackBlock(Callback);
|
||||
if (CallbackRoutineBlock)
|
||||
{
|
||||
/* Get the function */
|
||||
Function = ExGetCallBackBlockRoutine(CallbackRoutineBlock);
|
||||
|
||||
/* Do the callback */
|
||||
Function(Context, Argument1, Argument2);
|
||||
|
||||
/* Now dereference it */
|
||||
ExDereferenceCallBackBlock(Callback, CallbackRoutineBlock);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExpDeleteCallback(IN PVOID Object)
|
||||
|
||||
Reference in New Issue
Block a user