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