From 9416d6ffa4549298978deeef4e2298f13ee32365 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Tue, 16 Jan 2007 05:31:05 +0000 Subject: [PATCH] - 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 --- reactos/include/ndk/extypes.h | 2 +- reactos/ntoskrnl/ex/callback.c | 104 +++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/reactos/include/ndk/extypes.h b/reactos/include/ndk/extypes.h index 8b3a694d1ab..47439cd8f75 100644 --- a/reactos/include/ndk/extypes.h +++ b/reactos/include/ndk/extypes.h @@ -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; diff --git a/reactos/ntoskrnl/ex/callback.c b/reactos/ntoskrnl/ex/callback.c index 15f0498f52b..095fedc719a 100644 --- a/reactos/ntoskrnl/ex/callback.c +++ b/reactos/ntoskrnl/ex/callback.c @@ -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)