Skip to content

Commit 96de8bf

Browse files
guhetierCopilot
andcommitted
Invert platform/core worker-statistics dependency; return NOT_SUPPORTED in kernel mode
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2e58a74 commit 96de8bf

5 files changed

Lines changed: 113 additions & 39 deletions

File tree

src/core/library.c

Lines changed: 70 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,67 @@ QuicLibrarySetGlobalParam(
15061506
return Status;
15071507
}
15081508

1509+
#ifndef _KERNEL_MODE
1510+
//
1511+
// Fills the caller's buffer with the per-worker statistics for the global
1512+
// worker pool, mapping the platform's raw statistics into the public shape.
1513+
//
1514+
_IRQL_requires_max_(PASSIVE_LEVEL)
1515+
QUIC_STATUS
1516+
QuicLibraryGetGlobalWorkerStatistics(
1517+
_Inout_ uint32_t* BufferLength,
1518+
_Out_writes_bytes_opt_(*BufferLength)
1519+
void* Buffer
1520+
)
1521+
{
1522+
if (MsQuicLib.WorkerPool == NULL) {
1523+
return QUIC_STATUS_INVALID_STATE;
1524+
}
1525+
1526+
uint32_t WorkerCount = CxPlatWorkerPoolGetCount(MsQuicLib.WorkerPool);
1527+
uint32_t RequiredSize =
1528+
sizeof(QUIC_WORKER_STATISTICS_LIST) +
1529+
WorkerCount * sizeof(QUIC_WORKER_STATISTICS);
1530+
1531+
if (*BufferLength < RequiredSize) {
1532+
*BufferLength = RequiredSize;
1533+
return QUIC_STATUS_BUFFER_TOO_SMALL;
1534+
}
1535+
1536+
if (Buffer == NULL) {
1537+
return QUIC_STATUS_INVALID_PARAMETER;
1538+
}
1539+
1540+
QUIC_WORKER_STATISTICS_LIST* List = (QUIC_WORKER_STATISTICS_LIST*)Buffer;
1541+
List->WorkerCount = WorkerCount;
1542+
List->WorkerStatsSize = sizeof(QUIC_WORKER_STATISTICS);
1543+
1544+
QUIC_WORKER_STATISTICS* PublicStats =
1545+
(QUIC_WORKER_STATISTICS*)((uint8_t*)Buffer + sizeof(QUIC_WORKER_STATISTICS_LIST));
1546+
CxPlatZeroMemory(PublicStats, WorkerCount * sizeof(QUIC_WORKER_STATISTICS));
1547+
1548+
if (WorkerCount > 0) {
1549+
CXPLAT_WORKER_STATISTICS* RawStats =
1550+
CXPLAT_ALLOC_PAGED(
1551+
WorkerCount * sizeof(CXPLAT_WORKER_STATISTICS),
1552+
QUIC_POOL_GENERIC);
1553+
if (RawStats == NULL) {
1554+
return QUIC_STATUS_OUT_OF_MEMORY;
1555+
}
1556+
CxPlatWorkerPoolGetStatistics(MsQuicLib.WorkerPool, RawStats, WorkerCount);
1557+
for (uint32_t i = 0; i < WorkerCount; i++) {
1558+
PublicStats[i].IdealProcessor = RawStats[i].IdealProcessor;
1559+
PublicStats[i].CumulativeActiveTimeUs = RawStats[i].CumulativeActiveTimeUs;
1560+
PublicStats[i].CumulativeWallTimeUs = RawStats[i].CumulativeWallTimeUs;
1561+
}
1562+
CXPLAT_FREE(RawStats, QUIC_POOL_GENERIC);
1563+
}
1564+
1565+
*BufferLength = RequiredSize;
1566+
return QUIC_STATUS_SUCCESS;
1567+
}
1568+
#endif // !_KERNEL_MODE
1569+
15091570
_IRQL_requires_max_(PASSIVE_LEVEL)
15101571
QUIC_STATUS
15111572
QuicLibraryGetGlobalParam(
@@ -1876,43 +1937,18 @@ QuicLibraryGetGlobalParam(
18761937
break;
18771938
}
18781939

1879-
#ifndef _KERNEL_MODE
18801940
case QUIC_PARAM_GLOBAL_WORKER_STATISTICS: {
1881-
1882-
if (MsQuicLib.WorkerPool == NULL) {
1883-
Status = QUIC_STATUS_INVALID_STATE;
1884-
break;
1885-
}
1886-
1887-
uint32_t WorkerCount = CxPlatWorkerPoolGetCount(MsQuicLib.WorkerPool);
1888-
uint32_t RequiredSize =
1889-
sizeof(QUIC_WORKER_STATISTICS_LIST) +
1890-
WorkerCount * sizeof(QUIC_WORKER_STATISTICS);
1891-
1892-
if (*BufferLength < RequiredSize) {
1893-
*BufferLength = RequiredSize;
1894-
Status = QUIC_STATUS_BUFFER_TOO_SMALL;
1895-
break;
1896-
}
1897-
1898-
if (Buffer == NULL) {
1899-
Status = QUIC_STATUS_INVALID_PARAMETER;
1900-
break;
1901-
}
1902-
1903-
QUIC_WORKER_STATISTICS_LIST* List = (QUIC_WORKER_STATISTICS_LIST*)Buffer;
1904-
List->WorkerCount = WorkerCount;
1905-
List->WorkerStatsSize = sizeof(QUIC_WORKER_STATISTICS);
1906-
1907-
QUIC_WORKER_STATISTICS* Stats =
1908-
(QUIC_WORKER_STATISTICS*)((uint8_t*)Buffer + sizeof(QUIC_WORKER_STATISTICS_LIST));
1909-
CxPlatWorkerPoolGetStatistics(MsQuicLib.WorkerPool, Stats, WorkerCount);
1910-
1911-
*BufferLength = RequiredSize;
1912-
Status = QUIC_STATUS_SUCCESS;
1941+
#ifdef _KERNEL_MODE
1942+
//
1943+
// Worker statistics are not supported in kernel mode, where the worker
1944+
// threads are not owned by the platform worker pool.
1945+
//
1946+
Status = QUIC_STATUS_NOT_SUPPORTED;
1947+
#else
1948+
Status = QuicLibraryGetGlobalWorkerStatistics(BufferLength, Buffer);
1949+
#endif
19131950
break;
19141951
}
1915-
#endif
19161952

19171953
default:
19181954
Status = QUIC_STATUS_INVALID_PARAMETER;

src/inc/quic_platform.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,14 +557,24 @@ CxPlatWorkerPoolWorkerPoll(
557557
_In_ QUIC_EXECUTION* Execution
558558
);
559559

560+
//
561+
// Raw per-worker statistics owned by the platform layer. The core layer maps
562+
// these into the public QUIC_WORKER_STATISTICS shape, keeping the platform
563+
// layer free of any dependency on core/public types.
564+
//
565+
typedef struct CXPLAT_WORKER_STATISTICS {
566+
uint64_t CumulativeActiveTimeUs; // Time the worker spent active (not idle).
567+
uint64_t CumulativeWallTimeUs; // Wall time since the worker thread started.
568+
uint16_t IdealProcessor; // CPU the worker is affinitized to.
569+
} CXPLAT_WORKER_STATISTICS;
570+
560571
//
561572
// Gets the statistics for all workers in the pool.
562573
//
563-
typedef struct QUIC_WORKER_STATISTICS QUIC_WORKER_STATISTICS; // Forward declaration
564574
void
565575
CxPlatWorkerPoolGetStatistics(
566576
_In_ CXPLAT_WORKER_POOL* WorkerPool,
567-
_Out_writes_(WorkerCount) QUIC_WORKER_STATISTICS* Stats,
577+
_Out_writes_(WorkerCount) CXPLAT_WORKER_STATISTICS* Stats,
568578
_In_ uint32_t WorkerCount
569579
);
570580

src/platform/platform_worker.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ CXPLAT_THREAD_CALLBACK(CxPlatWorkerThread, Context)
881881
void
882882
CxPlatWorkerPoolGetStatistics(
883883
_In_ CXPLAT_WORKER_POOL* WorkerPool,
884-
_Out_writes_(WorkerCount) QUIC_WORKER_STATISTICS* Stats,
884+
_Out_writes_(WorkerCount) CXPLAT_WORKER_STATISTICS* Stats,
885885
_In_ uint32_t WorkerCount
886886
)
887887
{
@@ -892,7 +892,7 @@ CxPlatWorkerPoolGetStatistics(
892892
//
893893
// Note: The active time that has not been accumulated yet is ignored.
894894
//
895-
CxPlatZeroMemory(Stats, WorkerCount * sizeof(QUIC_WORKER_STATISTICS));
895+
CxPlatZeroMemory(Stats, WorkerCount * sizeof(CXPLAT_WORKER_STATISTICS));
896896
for (uint32_t i = 0; i < WorkerCount; i++) {
897897
CXPLAT_WORKER* Worker = &WorkerPool->Workers[i];
898898
Stats[i].IdealProcessor = Worker->IdealProcessor;

src/test/bin/winkernel/control.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ ExecuteTestRequest(
466466
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
467467
RegisterTestFunction(QuicTestValidateEncryptDecryptPerfCounters);
468468
#endif
469-
#ifndef _KERNEL_MODE
469+
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
470470
RegisterTestFunction(QuicTestGetWorkerStatistics);
471471
RegisterTestFunction(QuicTestValidateWorkerStatistics);
472472
#endif

src/test/lib/ApiTest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6057,6 +6057,19 @@ QuicTestGetWorkerStatistics()
60576057
MsQuicRegistration Registration;
60586058
TEST_QUIC_SUCCEEDED(Registration.GetInitStatus());
60596059

6060+
#ifdef _KERNEL_MODE
6061+
//
6062+
// Worker statistics are not supported in kernel mode.
6063+
//
6064+
uint32_t UnsupportedLength = 0;
6065+
TEST_EQUAL(
6066+
MsQuic->GetParam(
6067+
nullptr,
6068+
QUIC_PARAM_GLOBAL_WORKER_STATISTICS,
6069+
&UnsupportedLength,
6070+
nullptr),
6071+
QUIC_STATUS_NOT_SUPPORTED);
6072+
#else
60606073
//
60616074
// Test getting the required size with zero-length buffer.
60626075
//
@@ -6130,6 +6143,7 @@ QuicTestGetWorkerStatistics()
61306143
}
61316144

61326145
delete[] Buffer;
6146+
#endif // _KERNEL_MODE
61336147
}
61346148

61356149
void
@@ -6142,6 +6156,19 @@ QuicTestValidateWorkerStatistics()
61426156
MsQuicRegistration Registration(true);
61436157
TEST_QUIC_SUCCEEDED(Registration.GetInitStatus());
61446158

6159+
#ifdef _KERNEL_MODE
6160+
//
6161+
// Worker statistics are not supported in kernel mode.
6162+
//
6163+
uint32_t UnsupportedLength = 0;
6164+
TEST_EQUAL(
6165+
MsQuic->GetParam(
6166+
nullptr,
6167+
QUIC_PARAM_GLOBAL_WORKER_STATISTICS,
6168+
&UnsupportedLength,
6169+
nullptr),
6170+
QUIC_STATUS_NOT_SUPPORTED);
6171+
#else
61456172
MsQuicConfiguration ServerConfiguration(Registration, "MsQuicTest", ServerSelfSignedCredConfig);
61466173
TEST_QUIC_SUCCEEDED(ServerConfiguration.GetInitStatus());
61476174

@@ -6227,6 +6254,7 @@ QuicTestValidateWorkerStatistics()
62276254

62286255
delete[] BeforeBuffer;
62296256
delete[] AfterBuffer;
6257+
#endif // _KERNEL_MODE
62306258
}
62316259
#endif // QUIC_API_ENABLE_PREVIEW_FEATURES
62326260

0 commit comments

Comments
 (0)