diff --git a/.azure/azure-pipelines.ci.yml b/.azure/azure-pipelines.ci.yml index 6fcbefad4..7545406c0 100644 --- a/.azure/azure-pipelines.ci.yml +++ b/.azure/azure-pipelines.ci.yml @@ -731,76 +731,13 @@ stages: displayName: SpinQuic dependsOn: - build_windows_debug - - build_linux_debug - - build_macos_debug jobs: - - template: ./templates/run-spinquic.yml - parameters: - image: windows-2022 - platform: windows - tls: schannel - allocFail: 100 - extraArtifactDir: '_Sanitize' - extraTestArgs: -ExtraArtifactDir Sanitize - - template: ./templates/run-spinquic.yml - parameters: - image: windows-2022 - platform: windows - tls: schannel - allocFail: 100 - extraPrepareArgs: -InstallDuoNic -InstallXdpDriver - extraArtifactDir: '_Xdp' - extraTestArgs: -ExtraArtifactDir Xdp -Target 192.168.1.11 - template: ./templates/run-spinquic.yml parameters: pool: MsQuic-Win-Latest platform: windows tls: schannel allocFail: 100 - - template: ./templates/run-spinquic.yml - parameters: - image: windows-2019 - platform: windows - allocFail: 100 - tls: openssl - - template: ./templates/run-spinquic.yml - parameters: - image: windows-2022 - platform: windows - allocFail: 100 - tls: openssl - - template: ./templates/run-spinquic.yml - parameters: - image: windows-2022 - platform: windows - allocFail: 100 - tls: openssl3 - - template: ./templates/run-spinquic.yml - parameters: - image: ubuntu-latest - platform: linux - tls: openssl - allocFail: 100 - - template: ./templates/run-spinquic.yml - parameters: - image: ubuntu-latest - platform: linux - tls: openssl - allocFail: 100 - extraArtifactDir: '_Sanitize' - extraTestArgs: -ExtraArtifactDir Sanitize - - template: ./templates/run-spinquic.yml - parameters: - image: ubuntu-latest - platform: linux - tls: openssl3 - allocFail: 100 - - template: ./templates/run-spinquic.yml - parameters: - image: macOS-12 - platform: macos - tls: openssl - allocFail: 100 # # DotNet Tests diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6ffba3c2d..3a439d1eb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -79,10 +79,6 @@ jobs: if: matrix.codecheck != '-CodeCheck' # TODO: FIX: Release builds with CodeCheck fail shell: pwsh run: scripts/build.ps1 -Config Release -Platform ${{ matrix.plat }} -Arch ${{ matrix.arch }} -Tls ${{ matrix.tls }} ${{ matrix.static }} ${{ matrix.clang }} ${{ matrix.codecheck }} - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce - with: - name: ${{ matrix.plat }}-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.tls }}${{ matrix.systemcrypto }}${{ matrix.static }}${{ matrix.clang }}${{ matrix.codecheck }} - path: artifacts/bin build-ubuntu-cross-compile: name: Build @@ -123,10 +119,6 @@ jobs: - name: Build Release shell: pwsh run: scripts/build.ps1 -Config Release -Arch ${{ matrix.arch }} -ToolchainFile ${{ matrix.toolchain }} -Tls ${{ matrix.tls }} -DisableLogs -OneBranch ${{ matrix.static }} - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce - with: - name: ${{ matrix.plat }}-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.tls }}${{ matrix.static }} - path: artifacts/bin build-macOS: name: Build @@ -156,10 +148,6 @@ jobs: - name: Build Release shell: pwsh run: scripts/build.ps1 -Config Release -Platform ${{ matrix.plat }} -Arch ${{ matrix.arch }} -Tls ${{ matrix.tls }} ${{ matrix.static }} - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce - with: - name: ${{ matrix.plat }}-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.tls }}${{ matrix.static }} - path: artifacts/bin build-windows: name: Build @@ -214,18 +202,6 @@ jobs: - name: Build Release shell: pwsh run: scripts/build.ps1 -Config Release -Platform ${{ matrix.plat }} -Arch ${{ matrix.arch }} -Tls ${{ matrix.tls }} ${{ matrix.static }} ${{ matrix.xdp }} - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce - with: - name: ${{ matrix.plat }}-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.tls }}${{ matrix.static }}${{ matrix.xdp }} - path: | - artifacts/bin - !artifacts/bin/xdp - !artifacts/bin/**/*.ilk - !artifacts/bin/**/*.cer - !artifacts/bin/**/*.exp - !artifacts/bin/**/*.lastcodeanalysissucceeded - !artifacts/bin/**/*.pgd - !artifacts/bin/**/*.lib build-windows-kernel: name: Build @@ -258,15 +234,3 @@ jobs: - name: Build Release shell: pwsh run: msbuild msquic.kernel.sln /p:Configuration=Release /p:Platform=${{ matrix.arch }} /p:QUIC_VER_SUFFIX=-official - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce - with: - name: ${{ matrix.plat }}-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.tls }} - path: | - artifacts/bin - !artifacts/bin/xdp - !artifacts/bin/**/*.ilk - !artifacts/bin/**/*.cer - !artifacts/bin/**/*.exp - !artifacts/bin/**/*.lastcodeanalysissucceeded - !artifacts/bin/**/*.pgd - !artifacts/bin/**/*.lib diff --git a/.github/workflows/stress.yml b/.github/workflows/stress.yml index bb2a83187..735037d75 100644 --- a/.github/workflows/stress.yml +++ b/.github/workflows/stress.yml @@ -24,30 +24,46 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-20.04, windows-2022] + os: [ubuntu-20.04, macos-12, windows-2019, windows-2022] arch: [x64] tls: [schannel, openssl, openssl3] + xdp: ['', '-UseXdp'] sanitize: ['', '-Sanitize'] exclude: - os: ubuntu-20.04 tls: schannel + - os: macos-12 + tls: schannel # Linux and Windows Schannel use ASAN - os: ubuntu-20.04 sanitize: '' - tls: schannel sanitize: '' - # OpenSSL on Windows doesn't work with ASAN + # OpenSSL on Windows and macOS doesn't work with ASAN + - os: macos-12 + sanitize: '-Sanitize' + - os: windows-2019 + tls: openssl + sanitize: '-Sanitize' + - os: windows-2019 + tls: openssl3 + sanitize: '-Sanitize' - os: windows-2022 tls: openssl sanitize: '-Sanitize' - os: windows-2022 tls: openssl3 sanitize: '-Sanitize' + # XDP stuff is Windows only + - os: ubuntu-20.04 + xdp: '-UseXdp' + - os: macos-12 + xdp: '-UseXdp' runs-on: ${{ matrix.os }} name: Stress env: main-timeout: 3600000 - main-repeat: 20 + main-repeat: 100 main-allocfail: 100 pr-timeout: 600000 pr-repeat: 20 @@ -64,22 +80,22 @@ jobs: if: runner.os == 'Windows' uses: ilammy/setup-nasm@321e6ed62a1fc77024a3bd853deb33645e8b22c4 - name: Prepare Machine - run: scripts/prepare-machine.ps1 -Tls ${{ matrix.tls }} -ForBuild -ForTest + run: scripts/prepare-machine.ps1 -Tls ${{ matrix.tls }} -ForBuild -ForTest ${{ matrix.xdp }} shell: pwsh - name: Build shell: pwsh - run: scripts/build.ps1 -Config Debug -Arch ${{ matrix.arch }} -Tls ${{ matrix.tls }} -DisableTest -DisablePerf -DynamicCRT ${{ matrix.sanitize }} + run: scripts/build.ps1 -Config Debug -Arch ${{ matrix.arch }} -Tls ${{ matrix.tls }} -DisableTest -DisablePerf -DynamicCRT ${{ matrix.xdp }} ${{ matrix.sanitize }} - name: spinquic (PR) if: github.event_name == 'pull_request' shell: pwsh - run: scripts/spin.ps1 -AZP -Config Debug -Arch ${{ matrix.arch }} -Tls ${{ matrix.tls }} -Timeout ${{ env.pr-timeout }} -RepeatCount ${{ env.pr-repeat }} -AllocFail ${{ env.pr-allocfail }} + run: scripts/spin.ps1 -AZP -Config Debug -Arch ${{ matrix.arch }} -Tls ${{ matrix.tls }} -Timeout ${{ env.pr-timeout }} -RepeatCount ${{ env.pr-repeat }} -AllocFail ${{ env.pr-allocfail }} ${{ matrix.xdp }} - name: spinquic (Official) if: github.event_name != 'pull_request' shell: pwsh - run: scripts/spin.ps1 -AZP -Config Debug -Arch ${{ matrix.arch }} -Tls ${{ matrix.tls }} -Timeout ${{ env.main-timeout }} -RepeatCount ${{ env.main-repeat }} -AllocFail ${{ env.main-allocfail }} + run: scripts/spin.ps1 -AZP -Config Debug -Arch ${{ matrix.arch }} -Tls ${{ matrix.tls }} -Timeout ${{ env.main-timeout }} -RepeatCount ${{ env.main-repeat }} -AllocFail ${{ env.main-allocfail }} ${{ matrix.xdp }} - name: Upload on Failure uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce if: failure() with: - name: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.tls }} + name: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.tls }}${{ matrix.xdp }}${{ matrix.sanitize }} path: artifacts diff --git a/scripts/prepare-machine.ps1 b/scripts/prepare-machine.ps1 index 7eccff4b1..3747fa376 100644 --- a/scripts/prepare-machine.ps1 +++ b/scripts/prepare-machine.ps1 @@ -79,6 +79,9 @@ param ( [Parameter(Mandatory = $false)] [switch]$InstallXdpSdk, + [Parameter(Mandatory = $false)] + [switch]$UseXdp, + [Parameter(Mandatory = $false)] [switch]$InstallArm64Toolchain, @@ -112,6 +115,16 @@ if ($PSVersionTable.PSVersion.Major -lt 7) { "Please visit https://github.com/microsoft/msquic/blob/main/docs/BUILD.md#powershell-usage") } +if ($UseXdp) { + # Helper for XDP usage + if ($ForBuild) { + $InstallXdpSdk = $true; + } + if ($ForTest) { + $InstallXdpDriver = $true; + } +} + if (!$ForOneBranch -and !$ForOneBranchPackage -and !$ForBuild -and !$ForTest -and !$InstallXdpDriver -and !$UninstallXdp) { # When no args are passed, assume we want to build and test everything # locally (i.e. a dev environment). Set Tls to OpenSSL to make sure diff --git a/scripts/spin.ps1 b/scripts/spin.ps1 index 8b11e19b4..d2a607455 100644 --- a/scripts/spin.ps1 +++ b/scripts/spin.ps1 @@ -92,7 +92,10 @@ param ( [string]$ExtraArtifactDir = "", [Parameter(Mandatory = $false)] - [switch]$AZP = $false + [switch]$AZP = $false, + + [Parameter(Mandatory = $false)] + [switch]$UseXdp ) Set-StrictMode -Version 'Latest' @@ -110,7 +113,12 @@ $RootDir = Split-Path $PSScriptRoot -Parent # Path to the run-executable Powershell script. $RunExecutable = Join-Path $RootDir "scripts/run-executable.ps1" -#Validate the code coverage switch. +# Helper for XDP usage. +if ($UseXdp) { + $Target = "192.168.1.11" +} + +# Validate the code coverage switch. if ($CodeCoverage) { if (!$IsWindows) { Write-Error "-CodeCoverage switch only supported on Windows"; diff --git a/src/platform/platform_worker.c b/src/platform/platform_worker.c index f9318fc06..585fe128a 100644 --- a/src/platform/platform_worker.c +++ b/src/platform/platform_worker.c @@ -62,6 +62,13 @@ typedef struct QUIC_CACHEALIGN CXPLAT_WORKER { // CXPLAT_SLIST_ENTRY* ExecutionContexts; +#if DEBUG // Debug statistics + uint64_t LoopCount; + uint64_t EcPollCount; + uint64_t EcRunCount; + uint64_t CqeCount; +#endif + // // The ideal processor for the worker thread. // @@ -78,6 +85,8 @@ typedef struct QUIC_CACHEALIGN CXPLAT_WORKER { #endif BOOLEAN InitializedThread : 1; BOOLEAN InitializedECLock : 1; + BOOLEAN StoppingThread : 1; + BOOLEAN DestroyedThread : 1; // // Must not be bitfield. @@ -208,8 +217,14 @@ Error: if (CxPlatWorkers) { for (uint32_t i = 0; i < CxPlatWorkerCount; ++i) { if (CxPlatWorkers[i].InitializedThread) { + CxPlatWorkers[i].StoppingThread = TRUE; + CxPlatEventQEnqueue( + &CxPlatWorkers[i].EventQ, + &CxPlatWorkers[i].ShutdownSqe, + NULL); CxPlatThreadWait(&CxPlatWorkers[i].Thread); CxPlatThreadDelete(&CxPlatWorkers[i].Thread); + CxPlatWorkers[i].DestroyedThread = TRUE; } #ifdef CXPLAT_SQE_INIT if (CxPlatWorkers[i].InitializedUpdatePollSqe) { @@ -248,12 +263,14 @@ CxPlatWorkersUninit( CxPlatRundownReleaseAndWait(&CxPlatWorkerRundown); for (uint32_t i = 0; i < CxPlatWorkerCount; ++i) { + CxPlatWorkers[i].StoppingThread = TRUE; CxPlatEventQEnqueue( &CxPlatWorkers[i].EventQ, &CxPlatWorkers[i].ShutdownSqe, NULL); CxPlatThreadWait(&CxPlatWorkers[i].Thread); CxPlatThreadDelete(&CxPlatWorkers[i].Thread); + CxPlatWorkers[i].DestroyedThread = TRUE; #ifdef CXPLAT_SQE_INIT CxPlatSqeCleanup(&CxPlatWorkers[i].EventQ, &CxPlatWorkers[i].UpdatePollSqe); CxPlatSqeCleanup(&CxPlatWorkers[i].EventQ, &CxPlatWorkers[i].WakeSqe); @@ -356,6 +373,9 @@ CxPlatRunExecutionContexts( return; } +#if DEBUG // Debug statistics + ++Worker->EcPollCount; +#endif State->TimeNow = CxPlatTimeUs64(); uint64_t NextTime = UINT64_MAX; @@ -365,6 +385,9 @@ CxPlatRunExecutionContexts( CXPLAT_CONTAINING_RECORD(*EC, CXPLAT_EXECUTION_CONTEXT, Entry); BOOLEAN Ready = InterlockedFetchAndClearBoolean(&Context->Ready); if (Ready || Context->NextTimeUs <= State->TimeNow) { +#if DEBUG // Debug statistics + ++Worker->EcRunCount; +#endif CXPLAT_SLIST_ENTRY* Next = Context->Entry.Next; if (!Context->Callback(Context->Context, State)) { *EC = Next; // Remove Context from the list. @@ -407,6 +430,9 @@ CxPlatProcessEvents( uint32_t CqeCount = CxPlatEventQDequeue(&Worker->EventQ, Cqes, ARRAYSIZE(Cqes), State->WaitTime); InterlockedFetchAndSetBoolean(&Worker->Running); if (CqeCount != 0) { +#if DEBUG // Debug statistics + Worker->CqeCount += CqeCount; +#endif State->NoWorkCount = 0; for (uint32_t i = 0; i < CqeCount; ++i) { if (CxPlatCqeUserData(&Cqes[i]) == NULL) { @@ -450,6 +476,9 @@ CXPLAT_THREAD_CALLBACK(CxPlatWorkerThread, Context) while (TRUE) { ++State.NoWorkCount; +#if DEBUG // Debug statistics + ++Worker->LoopCount; +#endif CxPlatRunExecutionContexts(Worker, &State); if (State.WaitTime && InterlockedFetchAndClearBoolean(&Worker->Running)) {