tools/testing/selftests/mm/folio_split_race_test.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/mm/folio_split_race_test.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/mm/folio_split_race_test.c
Extension
.c
Size
7826 bytes
Lines
298
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct shared_ctl {
	atomic_uint_fast32_t stop;
	atomic_uint_fast64_t reader_failures;
	atomic_uint_fast64_t reader_verified;
	pthread_barrier_t barrier;
};

static void fill_page(unsigned char *base, size_t page_idx)
{
	unsigned char *page_ptr = base + page_idx * page_size;
	uint64_t idx = (uint64_t)page_idx;

	memset(page_ptr, FILL_BYTE, page_size);
	memcpy(page_ptr, &idx, sizeof(idx));
}

/* Returns true if valid, false if corrupted. */
static bool check_page(unsigned char *base, uint64_t page_idx)
{
	unsigned char *page_ptr = base + page_idx * page_size;
	uint64_t expected_idx = (uint64_t)page_idx;
	uint64_t got_idx;

	memcpy(&got_idx, page_ptr, 8);

	if (got_idx != expected_idx) {
		uint64_t off;
		int all_zero = 1;

		for (off = 0; off < page_size; off++) {
			if (page_ptr[off] != 0) {
				all_zero = 0;
				break;
			}
		}
		if (all_zero) {
			ksft_print_msg("CORRUPTED: page %" PRIu64
				       " (huge page %" PRIu64
				       ") is ALL ZEROS\n",
				       page_idx,
				       (page_idx * page_size) / pmd_pagesize);
		} else {
			ksft_print_msg("CORRUPTED: page %" PRIu64
				       " (huge page %" PRIu64
				       "): expected idx %" PRIu64
				       ", got %" PRIu64 "\n",
				       page_idx,
				       (page_idx * page_size) / pmd_pagesize,
				       page_idx, got_idx);
		}
		return false;
	}
	return true;
}

struct reader_arg {
	unsigned char *base;
	struct shared_ctl *ctl;
	int tid;
	atomic_uint_fast64_t *failures;
	atomic_uint_fast64_t *verified;
};

static void *reader_thread(void *arg)
{
	struct reader_arg *ra = (struct reader_arg *)arg;
	unsigned char *base = ra->base;
	struct shared_ctl *ctl = ra->ctl;
	int tid = ra->tid;
	atomic_uint_fast64_t *failures = ra->failures;
	atomic_uint_fast64_t *verified = ra->verified;
	uint64_t page_idx;

	pthread_barrier_wait(&ctl->barrier);

	while (atomic_load_explicit(&ctl->stop, memory_order_acquire) == 0) {
		for (page_idx = (size_t)tid; page_idx < TOTAL_PAGES;
		     page_idx += NUM_READER_THREADS) {
			/*
			 * page_idx % PUNCH_INTERVAL is in [0, PUNCH_INTERVAL),
			 * skip [0, PUNCH_SIZE_FACTOR)
			 */
			if (page_idx % PUNCH_INTERVAL < PUNCH_SIZE_FACTOR)
				continue;
			if (check_page(base, page_idx))
				atomic_fetch_add_explicit(verified, 1,
							  memory_order_relaxed);
			else
				atomic_fetch_add_explicit(failures, 1,
							  memory_order_relaxed);

Annotation

Implementation Notes