QuicConfigurationSettingsChanged(Configuration);
- BOOLEAN Result = CxPlatRundownAcquire(&Registration->Rundown);
+ BOOLEAN Result = QuicRegistrationRundownAcquire(Registration, QUIC_REG_REF_CONFIGURATION);
CXPLAT_FRE_ASSERT(Result);
CxPlatLockAcquire(&Registration->ConfigLock);
QuicSettingsCleanup(&Configuration->Settings);
- CxPlatRundownRelease(&Configuration->Registration->Rundown);
+ QuicRegistrationRundownRelease(Configuration->Registration, QUIC_REG_REF_CONFIGURATION);
QuicTraceEvent(
ConfigurationDestroyed,
QuicPerfCounterDecrement(Partition, QUIC_PERF_COUNTER_CONN_CONNECTED);
}
if (Connection->Registration != NULL) {
- CxPlatRundownRelease(&Connection->Registration->Rundown);
+ QuicRegistrationRundownRelease(Connection->Registration, QUIC_REG_REF_CONNECTION);
}
if (Connection->CloseReasonPhrase != NULL) {
CXPLAT_FREE(Connection->CloseReasonPhrase, QUIC_POOL_CLOSE_REASON);
CxPlatDispatchLockAcquire(&Connection->Registration->ConnectionLock);
CxPlatListEntryRemove(&Connection->RegistrationLink);
CxPlatDispatchLockRelease(&Connection->Registration->ConnectionLock);
- CxPlatRundownRelease(&Connection->Registration->Rundown);
+ QuicRegistrationRundownRelease(Connection->Registration, QUIC_REG_REF_CONNECTION);
QuicTraceEvent(
ConnUnregistered,
{
QuicConnUnregister(Connection);
- if (!CxPlatRundownAcquire(&Registration->Rundown)) {
+ if (!QuicRegistrationRundownAcquire(Registration, QUIC_REG_REF_CONNECTION)) {
return FALSE;
}
Connection->State.Registered = TRUE;
if (RegistrationShuttingDown) {
Connection->State.Registered = FALSE;
Connection->Registration = NULL;
- CxPlatRundownRelease(&Registration->Rundown);
+ QuicRegistrationRundownRelease(Registration, QUIC_REG_REF_CONNECTION);
} else {
QuicTraceEvent(
ConnRegistered,
#if DEBUG
CXPLAT_TEL_ASSERT(Connection->RefTypeCount[Ref] > 0);
uint16_t result = (uint16_t)InterlockedDecrement16((volatile short*)&Connection->RefTypeCount[Ref]);
- CXPLAT_TEL_ASSERT(result != 0xFFFF);
+ CXPLAT_TEL_ASSERT(result != UINT16_MAX);
#else
UNREFERENCED_PARAMETER(Ref);
#endif
BOOLEAN RegistrationShuttingDown;
- BOOLEAN Result = CxPlatRundownAcquire(&Registration->Rundown);
+ BOOLEAN Result = QuicRegistrationRundownAcquire(Registration, QUIC_REG_REF_LISTENER);
CXPLAT_DBG_ASSERT(Result); UNREFERENCED_PARAMETER(Result);
CxPlatDispatchLockAcquire(&Registration->ConnectionLock);
CxPlatDispatchLockRelease(&Registration->ConnectionLock);
if (RegistrationShuttingDown) {
- CxPlatRundownRelease(&Registration->Rundown);
+ QuicRegistrationRundownRelease(Registration, QUIC_REG_REF_LISTENER);
CxPlatEventUninitialize(Listener->StopEvent);
CXPLAT_FREE(Listener, QUIC_POOL_LISTENER);
Listener = NULL;
CxPlatEventUninitialize(Listener->StopEvent);
CXPLAT_DBG_ASSERT(Listener->AlpnList == NULL);
CXPLAT_FREE(Listener, QUIC_POOL_LISTENER);
- CxPlatRundownRelease(&Registration->Rundown);
+ QuicRegistrationRundownRelease(Registration, QUIC_REG_REF_LISTENER);
}
_IRQL_requires_max_(PASSIVE_LEVEL)
CxPlatLockRelease(&MsQuicLib.Lock);
}
+#if DEBUG
+ CXPLAT_DBG_ASSERT(!CxPlatRefDecrement(&Registration->RefTypeBiasedCount[QUIC_REG_REF_HANDLE_OWNER]));
+#endif
+
CxPlatRundownReleaseAndWait(&Registration->Rundown);
QuicWorkerPoolUninitialize(Registration->WorkerPool);
+#if DEBUG
+ for (uint32_t i = 0; i < QUIC_REG_REF_COUNT; i++) {
+ //
+ // Since this is after CxPlatRundownReleaseAndWait returns,
+ // no thread should be modifying these counters.
+ //
+ CXPLAT_DBG_ASSERT(QuicReadLongPtrNoFence(&Registration->RefTypeBiasedCount[i]) == 1);
+ }
+#endif
CxPlatRundownUninitialize(&Registration->Rundown);
CxPlatDispatchLockUninitialize(&Registration->ConnectionLock);
CxPlatLockUninitialize(&Registration->ConfigLock);
CxPlatListInitializeHead(&Registration->Connections);
CxPlatListInitializeHead(&Registration->Listeners);
CxPlatRundownInitialize(&Registration->Rundown);
+#if DEBUG
+ CxPlatRefInitializeMultiple(Registration->RefTypeBiasedCount, QUIC_REG_REF_COUNT);
+ CxPlatRefIncrement(&Registration->RefTypeBiasedCount[QUIC_REG_REF_HANDLE_OWNER]);
+#endif
CxPlatEventInitialize(&Registration->CloseEvent, TRUE, FALSE);
Registration->AppNameLength = (uint8_t)(AppNameLength + 1);
if (AppNameLength != 0) {
if (Registration != NULL) {
CXPLAT_DBG_ASSERT(!Registration->CloseThread);
CxPlatEventUninitialize(Registration->CloseEvent);
+#if DEBUG
+ CxPlatRefDecrement(&Registration->RefTypeBiasedCount[QUIC_REG_REF_HANDLE_OWNER]);
+#endif
CxPlatRundownUninitialize(&Registration->Rundown);
CxPlatDispatchLockUninitialize(&Registration->ConnectionLock);
CxPlatLockUninitialize(&Registration->ConfigLock);
QUIC_CONNECTION_REJECT_APP
} QUIC_CONNECTION_ACCEPT_RESULT;
+typedef enum QUIC_REGISTRATION_REF {
+
+ QUIC_REG_REF_HANDLE_OWNER,
+ QUIC_REG_REF_CONFIGURATION,
+ QUIC_REG_REF_CONNECTION,
+ QUIC_REG_REF_LISTENER,
+
+ QUIC_REG_REF_COUNT
+
+} QUIC_REGISTRATION_REF;
+
//
// Represents per application registration state.
//
//
CXPLAT_RUNDOWN_REF Rundown;
+#if DEBUG
+ //
+ // Detailed ref counts. The actual reference count is in the Rundown.
+ // Note: These ref counts are biased by 1, so lowest they go is 1. It is an
+ // error for them to ever be zero.
+ //
+ CXPLAT_REF_COUNT RefTypeBiasedCount[QUIC_REG_REF_COUNT];
+#endif
+
//
// Shutdown error code if set.
//
#define QUIC_REG_VERIFY(Registration, Expr)
#endif
+//
+// Adds a rundown reference to the Registration.
+//
+_IRQL_requires_max_(DISPATCH_LEVEL)
+QUIC_INLINE
+BOOLEAN
+QuicRegistrationRundownAcquire(
+ _In_ QUIC_REGISTRATION* Registration,
+ _In_ QUIC_REGISTRATION_REF Ref
+ )
+{
+ BOOLEAN Result = CxPlatRundownAcquire(&Registration->Rundown);
+#if DEBUG
+ if (Result) {
+ //
+ // Only increment the detailed ref count if the Rundown acquire succeeded.
+ //
+ CxPlatRefIncrement(&Registration->RefTypeBiasedCount[Ref]);
+ }
+#else
+ UNREFERENCED_PARAMETER(Ref);
+#endif
+
+ return Result;
+}
+
+//
+// Releases a rundown reference on the Registration.
+//
+_IRQL_requires_max_(DISPATCH_LEVEL)
+QUIC_INLINE
+void
+QuicRegistrationRundownRelease(
+ _In_ QUIC_REGISTRATION* Registration,
+ _In_ QUIC_REGISTRATION_REF Ref
+ )
+{
+#if DEBUG
+ CXPLAT_DBG_ASSERT(!CxPlatRefDecrement(&Registration->RefTypeBiasedCount[Ref]));
+#else
+ UNREFERENCED_PARAMETER(Ref);
+#endif
+
+ CxPlatRundownRelease(&Registration->Rundown);
+}
+
//
// Tracing rundown for the registration.
//
return __sync_sub_and_fetch(Addend, (int64_t)1);
}
-#define QuicReadPtrNoFence(p) ((void*)(*p)) // TODO
+#define QuicReadPtrNoFence(p) __atomic_load_n((p), __ATOMIC_RELAXED)
+
+#define QuicReadLongPtrNoFence(p) __atomic_load_n((p), __ATOMIC_RELAXED)
//
// Assertion interfaces.
_In_ uint32_t Initial
);
+void
+CxPlatRefInitializeMultiple(
+ _Out_writes_(Count) CXPLAT_REF_COUNT* RefCounts,
+ _In_ uint32_t Count
+ );
+
void
CxPlatRefIncrement(
_Inout_ CXPLAT_REF_COUNT* RefCount
*RefCount = 1;
}
+QUIC_INLINE
+void
+CxPlatRefInitializeMultiple(
+ _Out_writes_(Count) CXPLAT_REF_COUNT* RefCounts,
+ _In_ uint32_t Count
+ )
+{
+ for (uint32_t i = 0; i < Count; i++) {
+ CxPlatRefInitialize(&RefCounts[i]);
+ }
+}
+
#define CxPlatRefUninitialize(RefCount)
QUIC_INLINE
*RefCount = (LONG_PTR)Initial;
}
+QUIC_INLINE
+void
+CxPlatRefInitializeMultiple(
+ _Out_writes_(Count) CXPLAT_REF_COUNT* RefCounts,
+ _In_ uint32_t Count
+ )
+{
+ for (uint32_t i = 0; i < Count; i++) {
+ CxPlatRefInitialize(&RefCounts[i]);
+ }
+}
+
#define CxPlatRefUninitialize(RefCount)
QUIC_INLINE
*RefCount = (int64_t)Initial;
}
+void
+CxPlatRefInitializeMultiple(
+ _Out_writes_(Count) CXPLAT_REF_COUNT* RefCounts,
+ _In_ uint32_t Count
+ )
+{
+ for (uint32_t i = 0; i < Count; i++) {
+ CxPlatRefInitialize(&RefCounts[i]);
+ }
+}
+
void
CxPlatRefIncrement(
_Inout_ CXPLAT_REF_COUNT* RefCount