tools/testing/selftests/mm/migration.c
Source file repositories/reference/linux-study-clean/tools/testing/selftests/mm/migration.c
File Facts
- System
- Linux kernel
- Corpus path
tools/testing/selftests/mm/migration.c- Extension
.c- Size
- 7406 bytes
- Lines
- 315
- Domain
- Support Tooling And Documentation
- Bucket
- tools
- Inferred role
- Support Tooling And Documentation: implementation source
- Status
- source implementation candidate
Why This File Exists
Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
kselftest_harness.hthp_settings.hstrings.hpthread.hnuma.hnumaif.hsys/mman.hsys/prctl.hsys/types.hsignal.htime.hvm_util.h
Detected Declarations
function migrate
Annotated Snippet
if (numa_bitmask_isbitset(numa_all_nodes_ptr, n)) {
if (self->n1 == -1) {
self->n1 = n;
} else {
self->n2 = n;
break;
}
}
self->threads = malloc(self->nthreads * sizeof(*self->threads));
ASSERT_NE(self->threads, NULL);
self->pids = malloc(self->nthreads * sizeof(*self->pids));
ASSERT_NE(self->pids, NULL);
};
FIXTURE_TEARDOWN(migration)
{
free(self->threads);
free(self->pids);
}
int migrate(uint64_t *ptr, int n1, int n2)
{
int ret, tmp;
int status = 0;
struct timespec ts1, ts2;
int failures = 0;
if (clock_gettime(CLOCK_MONOTONIC, &ts1))
return -1;
while (1) {
if (clock_gettime(CLOCK_MONOTONIC, &ts2))
return -1;
if (ts2.tv_sec - ts1.tv_sec >= RUNTIME)
return 0;
ret = move_pages(0, 1, (void **) &ptr, &n2, &status,
MPOL_MF_MOVE_ALL);
if (ret) {
if (ret > 0) {
/* Migration is best effort; try again */
if (++failures < MAX_RETRIES)
continue;
printf("Didn't migrate %d pages\n", ret);
}
else
perror("Couldn't migrate pages");
return -2;
}
failures = 0;
tmp = n2;
n2 = n1;
n1 = tmp;
}
return 0;
}
void *access_mem(void *ptr)
{
while (1) {
pthread_testcancel();
/* Force a read from the memory pointed to by ptr. This ensures
* the memory access actually happens and prevents the compiler
* from optimizing away this entire loop.
*/
FORCE_READ(*(uint64_t *)ptr);
}
return NULL;
}
/*
* Basic migration entry testing. One thread will move pages back and forth
* between nodes whilst other threads try and access them triggering the
* migration entry wait paths in the kernel.
*/
TEST_F_TIMEOUT(migration, private_anon, 2*RUNTIME)
{
uint64_t *ptr;
int i;
if (self->nthreads < 2 || self->n1 < 0 || self->n2 < 0)
SKIP(return, "Not enough threads or NUMA nodes available");
ptr = mmap(NULL, TWOMEG, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_NE(ptr, MAP_FAILED);
Annotation
- Immediate include surface: `kselftest_harness.h`, `thp_settings.h`, `strings.h`, `pthread.h`, `numa.h`, `numaif.h`, `sys/mman.h`, `sys/prctl.h`.
- Detected declarations: `function migrate`.
- Atlas domain: Support Tooling And Documentation / tools.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.