- 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:
Alex Ionescu
2007-01-16 05:31:05 +00:00
parent b51d473275
commit 9416d6ffa4
2 changed files with 105 additions and 1 deletions

View File

@@ -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;

View File

@@ -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)