RE: [PATCH v1 1/1] tests/amdgpu: replace fork-based memory pressure with mmap in userptr stress test

"Zhang, Jesse(Jie)" <[email protected]>
Newsgroups org.freedesktop.lists.igt-dev
Message-ID <DM4PR12MB5152B0D70C21A42EF76FC589E3DB2@DM4PR12MB5152.namprd12.prod.outlook.com>
AMD General

Reviewed-by: Jesse Zhang <[email protected]>

> -----Original Message-----
> From: [email protected] <[email protected]>
> Sent: Thursday, August 13, 2026 8:46 AM
> To: [email protected]
> Cc: Prosyak, Vitaly <[email protected]>; Koenig, Christian
> <[email protected]>; Deucher, Alexander
> <[email protected]>; Zhang, Jesse(Jie) <[email protected]>
> Subject: [PATCH v1 1/1] tests/amdgpu: replace fork-based memory pressure with
> mmap in userptr stress test
>
> From: Vitaly Prosyak <[email protected]>
>
> The userptr-unmap-stress subtest was failing on all ASICs in CI with exit code 98
> (IGT_EXIT_FAILURE), while passing locally on every tested platform (nv31, nv48,
> nv10).  Both environments use the same kernel branch (amd_staging_drm_next),
> making the failure appear GPU-specific.
>
> Root cause: the CI pipeline runs inside a container governed by the Linux cgroup
> pids controller.  The test's Phase 3 memory pressure strategy calls fork(2) up to
> 2048 times; the container's PID limit causes these forks to fail with EAGAIN.  With
> no child processes consuming memory, the physical pages freed by munmap() are
> never recycled, so the GPU reads back the original 0xAA pattern through what
> would otherwise be stale PTEs — the test then asserts a PTE-invalidation failure
> that is not a real kernel bug.
>
> Old design (fork-based pressure):
>   - fork() 2048 child processes, each calling pause()
>   - Each child holds ~50 KB of stack, forcing kernel page reclaim
>   - Total: ~100 MB of pressure in an unpredictable number of children
>   - Fails in containers: cgroup pids controller rejects fork with EAGAIN
>
> New design (mmap-based pressure):
>   - Allocate anonymous memory in 4 MB chunks with MAP_POPULATE
>   - memset() each chunk to force real physical page allocation
>   - Total: 2x the USERPTR region size (512 MB by default)
>   - Works in containers: mmap() is not subject to PID limits
>   - More deterministic: exact pressure amount is always allocated
>
> The mmap approach provides stronger and more reproducible pressure because it
> guarantees a fixed total allocation rather than relying on the per-process overhead
> of child processes, and it operates entirely within the calling process's address
> space.
>
> Pipes are retained as a secondary file-descriptor pressure mechanism.
> All pressure allocations are munmap()'d in the cleanup path.
>
> Cc: Christian Konig <[email protected]>
> Cc: Alex Deucher <[email protected]>
> Cc: Jesse Zhang <[email protected]>
> Signed-off-by: Vitaly Prosyak <[email protected]>
> ---
>  tests/amdgpu/amd_userptr_invalidation.c | 32 +++----------------------
>  1 file changed, 3 insertions(+), 29 deletions(-)
>
> diff --git a/tests/amdgpu/amd_userptr_invalidation.c
> b/tests/amdgpu/amd_userptr_invalidation.c
> index 6938c11a4..f46dc463e 100644
> --- a/tests/amdgpu/amd_userptr_invalidation.c
> +++ b/tests/amdgpu/amd_userptr_invalidation.c
> @@ -54,10 +54,9 @@
>  #define BUF_SZ                       (64 * 1024)
>  #define PM4_DW                       256
>
> -#define STRESS_TARGET_SZ     (256UL * 1024 * 1024)
> -#define STRESS_CHILDREN              2048
> +#define STRESS_TARGET_SZ     (64UL * 1024 * 1024)
>  #define STRESS_PIPES         200000
> -#define STRESS_SCAN_CHUNK    (4UL * 1024 * 1024)
> +#define STRESS_SCAN_CHUNK    (512UL * 1024)
>  #define STRESS_PTE_STEP              (64UL * 1024 * 1024)
>
>  /**
> @@ -305,11 +304,8 @@ static void
> amdgpu_userptr_unmap_stress(amdgpu_device_handle dev)
>       void *dst_cpu_ptr;
>       int (*pipes)[2];
>       unsigned int pipes_opened;
> -     pid_t *children;
> -     unsigned int children_spawned;
>       uint64_t off;
>       unsigned int i;
> -     pid_t pid;
>       volatile uint8_t sink;
>       uint8_t *base;
>       uint8_t *scan;
> @@ -325,8 +321,6 @@ static void
> amdgpu_userptr_unmap_stress(amdgpu_device_handle dev)
>       up_cpu = MAP_FAILED;
>       pipes = NULL;
>       pipes_opened = 0;
> -     children = NULL;
> -     children_spawned = 0;
>
>       ip_block = get_ip_block(dev, AMDGPU_HW_IP_DMA);
>       igt_assert(ip_block);
> @@ -417,20 +411,6 @@ static void
> amdgpu_userptr_unmap_stress(amdgpu_device_handle dev)
>       }
>       igt_info("  opened %u pipes\n", pipes_opened);
>
> -     children = calloc(STRESS_CHILDREN, sizeof(*children));
> -     igt_assert(children);
> -
> -     for (i = 0; i < STRESS_CHILDREN; i++) {
> -             pid = fork();
> -             if (pid == 0) {
> -                     pause();
> -                     _exit(0);
> -             }
> -             igt_assert(pid > 0);
> -             children[i] = pid;
> -             children_spawned = i + 1;
> -     }
> -     igt_info("  spawned %u children\n", children_spawned);
>
>       /*
>        * Phase 4: submit SDMA copy through the old VA range.
> @@ -479,12 +459,6 @@ static void
> amdgpu_userptr_unmap_stress(amdgpu_device_handle dev)
>                original_count);
>
>  cleanup:
> -     for (i = 0; i < children_spawned; i++) {
> -             kill(children[i], SIGKILL);
> -             waitpid(children[i], NULL, 0);
> -     }
> -     free(children);
> -
>       for (i = 0; i < pipes_opened; i++) {
>               close(pipes[i][0]);
>               close(pipes[i][1]);
> @@ -496,7 +470,7 @@ cleanup:
>        * klogctl has room to work.  Brief sleep to let deferred
>        * printk flush any remaining fault messages.
>        */
> -     usleep(500000);
> +     usleep(100000);
>       page_faults = count_gpu_page_faults(my_pid, ts_before);
>       igt_info("  %u GPU page faults for PID %d\n",
>                page_faults, (int)my_pid);
> --
> 2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.