-
Notifications
You must be signed in to change notification settings - Fork 582
Add async cleanup APIs for external execution mode #5127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 8 commits
48b02ae
57a0b40
e92ec55
93b9656
a7179b0
2f394ae
e5ecf95
67a48ee
49d380c
080dd95
55f7ce8
8a9ee72
c6fd9a2
fc4bab7
ac0aab9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,12 @@ | |
#include "registration.c.clog.h" | ||
#endif | ||
|
||
typedef struct QUIC_REGISTRATION_EX { | ||
QUIC_REGISTRATION Registration; | ||
QUIC_REGISTRATION_CLOSE_COMPLETE_HANDLER CloseHandler; | ||
void* CloseContext; | ||
} QUIC_REGISTRATION_EX; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of making a new EX struct. Just put this stuff inside the existing registration struct. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've removed the QUIC_REGISTRATION_EX struct and instead added the CloseHandler and CloseContext fields directly to the existing QUIC_REGISTRATION struct. This eliminates the need for a separate wrapper struct and makes the code cleaner. 49d380c |
||
|
||
_IRQL_requires_max_(PASSIVE_LEVEL) | ||
QUIC_STATUS | ||
QUIC_API | ||
|
@@ -61,16 +67,20 @@ MsQuicRegistrationOpen( | |
goto Error; | ||
} | ||
|
||
Registration = CXPLAT_ALLOC_NONPAGED(RegistrationSize, QUIC_POOL_REGISTRATION); | ||
if (Registration == NULL) { | ||
QUIC_REGISTRATION_EX* RegistrationEx = CXPLAT_ALLOC_NONPAGED(RegistrationSize + sizeof(QUIC_REGISTRATION_EX) - sizeof(QUIC_REGISTRATION), QUIC_POOL_REGISTRATION); | ||
if (RegistrationEx == NULL) { | ||
QuicTraceEvent( | ||
AllocFailure, | ||
"Allocation of '%s' failed. (%llu bytes)", | ||
"registration", | ||
sizeof(QUIC_REGISTRATION) + AppNameLength + 1); | ||
sizeof(QUIC_REGISTRATION_EX) + AppNameLength + 1); | ||
Status = QUIC_STATUS_OUT_OF_MEMORY; | ||
goto Error; | ||
} | ||
|
||
Registration = &RegistrationEx->Registration; | ||
RegistrationEx->CloseHandler = NULL; | ||
RegistrationEx->CloseContext = NULL; | ||
|
||
CxPlatZeroMemory(Registration, RegistrationSize); | ||
Registration->Type = QUIC_HANDLE_TYPE_REGISTRATION; | ||
|
@@ -143,6 +153,54 @@ MsQuicRegistrationOpen( | |
return Status; | ||
} | ||
|
||
_IRQL_requires_max_(PASSIVE_LEVEL) | ||
void | ||
QuicRegistrationRundownComplete( | ||
_In_ void* Context | ||
) | ||
{ | ||
QUIC_REGISTRATION_EX* RegistrationEx = CXPLAT_CONTAINING_RECORD(Context, QUIC_REGISTRATION_EX, Registration); | ||
QUIC_REGISTRATION* Registration = &RegistrationEx->Registration; | ||
|
||
QuicWorkerPoolUninitialize(Registration->WorkerPool); | ||
CxPlatRundownUninitialize(&Registration->Rundown); | ||
CxPlatDispatchLockUninitialize(&Registration->ConnectionLock); | ||
CxPlatLockUninitialize(&Registration->ConfigLock); | ||
|
||
// Store callback info locally before freeing | ||
QUIC_REGISTRATION_CLOSE_COMPLETE_HANDLER Handler = RegistrationEx->CloseHandler; | ||
void* HandlerContext = RegistrationEx->CloseContext; | ||
|
||
CXPLAT_FREE(RegistrationEx, QUIC_POOL_REGISTRATION); | ||
|
||
// Call the callback as the very last thing in the function | ||
if (Handler != NULL) { | ||
Handler(HandlerContext); | ||
} | ||
} | ||
|
||
// Forward declaration | ||
_IRQL_requires_max_(PASSIVE_LEVEL) | ||
QUIC_STATUS | ||
QUIC_API | ||
MsQuicRegistrationCloseAsync( | ||
_In_ _Pre_defensive_ __drv_freesMem(Mem) | ||
HQUIC Handle, | ||
_In_opt_ QUIC_REGISTRATION_CLOSE_COMPLETE_HANDLER Handler, | ||
_In_opt_ void* Context | ||
); | ||
|
||
// Helper function for MsQuicRegistrationClose | ||
void | ||
QUIC_API | ||
QuicRegistrationCloseComplete( | ||
void* Context | ||
) | ||
{ | ||
CXPLAT_EVENT* Event = (CXPLAT_EVENT*)Context; | ||
CxPlatEventSet(*Event); | ||
} | ||
|
||
_IRQL_requires_max_(PASSIVE_LEVEL) | ||
void | ||
QUIC_API | ||
|
@@ -158,12 +216,57 @@ MsQuicRegistrationClose( | |
QUIC_TRACE_API_REGISTRATION_CLOSE, | ||
Handle); | ||
|
||
// Create an event to wait on | ||
CXPLAT_EVENT CompletionEvent; | ||
CxPlatEventInitialize(&CompletionEvent, TRUE, FALSE); | ||
|
||
// Call the async version with our event as the context | ||
MsQuicRegistrationCloseAsync( | ||
Handle, | ||
QuicRegistrationCloseComplete, | ||
&CompletionEvent); | ||
|
||
// Wait for the event to be set by the completion callback | ||
CxPlatEventWaitForever(CompletionEvent); | ||
|
||
// Clean up the event | ||
CxPlatEventUninitialize(CompletionEvent); | ||
|
||
QuicTraceEvent( | ||
ApiExit, | ||
"[ api] Exit"); | ||
} | ||
} | ||
|
||
_IRQL_requires_max_(PASSIVE_LEVEL) | ||
QUIC_STATUS | ||
QUIC_API | ||
MsQuicRegistrationCloseAsync( | ||
nibanks marked this conversation as resolved.
Show resolved
Hide resolved
|
||
_In_ _Pre_defensive_ __drv_freesMem(Mem) | ||
HQUIC Handle, | ||
_In_opt_ QUIC_REGISTRATION_CLOSE_COMPLETE_HANDLER Handler, | ||
_In_opt_ void* Context | ||
) | ||
{ | ||
QUIC_STATUS Status = QUIC_STATUS_INVALID_PARAMETER; | ||
|
||
if (Handle != NULL && Handle->Type == QUIC_HANDLE_TYPE_REGISTRATION) { | ||
QuicTraceEvent( | ||
ApiEnter, | ||
"[ api] Enter %u (%p).", | ||
QUIC_TRACE_API_REGISTRATION_CLOSE_ASYNC, | ||
Handle); | ||
|
||
#pragma prefast(suppress: __WARNING_25024, "Pointer cast already validated.") | ||
QUIC_REGISTRATION* Registration = (QUIC_REGISTRATION*)Handle; | ||
QUIC_REGISTRATION_EX* RegistrationEx = CXPLAT_CONTAINING_RECORD(Registration, QUIC_REGISTRATION_EX, Registration); | ||
|
||
RegistrationEx->CloseHandler = Handler; | ||
RegistrationEx->CloseContext = Context; | ||
|
||
QuicTraceEvent( | ||
RegistrationCleanup, | ||
"[ reg][%p] Cleaning up", | ||
"[ reg][%p] Cleaning up (async)", | ||
Registration); | ||
|
||
if (Registration->ExecProfile != QUIC_EXECUTION_PROFILE_TYPE_INTERNAL) { | ||
|
@@ -172,19 +275,20 @@ MsQuicRegistrationClose( | |
CxPlatLockRelease(&MsQuicLib.Lock); | ||
} | ||
|
||
CxPlatRundownReleaseAndWait(&Registration->Rundown); | ||
|
||
QuicWorkerPoolUninitialize(Registration->WorkerPool); | ||
CxPlatRundownUninitialize(&Registration->Rundown); | ||
CxPlatDispatchLockUninitialize(&Registration->ConnectionLock); | ||
CxPlatLockUninitialize(&Registration->ConfigLock); | ||
|
||
CXPLAT_FREE(Registration, QUIC_POOL_REGISTRATION); | ||
Status = QUIC_STATUS_SUCCESS; | ||
|
||
// Release the rundown - this starts the cleanup process | ||
CxPlatRundownRelease(&Registration->Rundown); | ||
|
||
// Return pending as we don't know when it will complete | ||
Status = QUIC_STATUS_PENDING; | ||
|
||
QuicTraceEvent( | ||
ApiExit, | ||
"[ api] Exit"); | ||
} | ||
|
||
return Status; | ||
} | ||
|
||
_IRQL_requires_max_(DISPATCH_LEVEL) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file has no changes. Please remove it from this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed this file from the PR as it has no changes.