tools/testing/selftests/perf_events/mmap.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/perf_events/mmap.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/perf_events/mmap.c
Extension
.c
Size
5682 bytes
Lines
237
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

if (fd < 0) {
			if (errno == EACCES)
				eacces++;
			continue;
		}

		// Check whether the event supports mmap()
		rb = mmap(region, RB_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0);
		if (rb == MAP_FAILED) {
			close(fd);
			continue;
		}

		if (!map) {
			// Save the event in case that no AUX capable event is found
			attr_ok = attr;
			map = MAP_BASE;
		}

		if (!variant->aux)
			continue;

		rb->aux_offset = AUX_OFFS;
		rb->aux_size = AUX_SIZE;

		// Check whether it supports a AUX buffer
		aux = mmap(region + REGION_AUX_OFFS, AUX_SIZE, PROT_READ | PROT_WRITE,
			   MAP_SHARED | MAP_FIXED, fd, AUX_OFFS);
		if (aux == MAP_FAILED) {
			munmap(rb, RB_SIZE);
			close(fd);
			continue;
		}

		attr_ok = attr;
		map = MAP_AUX;
		munmap(aux, AUX_SIZE);
		munmap(rb, RB_SIZE);
		close(fd);
		break;
	}
	closedir(dir);

	if (!map) {
		if (!eacces)
			SKIP(return, "No mappable perf event found.");
		else
			SKIP(return, "No permissions for perf_event_open()");
	}

	self->fd = syscall(SYS_perf_event_open, &attr_ok, 0, -1, -1, 0);
	ASSERT_NE(self->fd, -1);

	rb = mmap(region, RB_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, self->fd, 0);
	ASSERT_NE(rb, MAP_FAILED);

	if (!variant->aux) {
		self->ptr = rb;
		return;
	}

	if (map != MAP_AUX)
		SKIP(return, "No AUX event found.");

	rb->aux_offset = AUX_OFFS;
	rb->aux_size = AUX_SIZE;
	aux = mmap(region + REGION_AUX_OFFS, AUX_SIZE, PROT_READ | PROT_WRITE,
		   MAP_SHARED | MAP_FIXED, self->fd, AUX_OFFS);
	ASSERT_NE(aux, MAP_FAILED);
	self->ptr = aux;
}

FIXTURE_TEARDOWN(perf_mmap)
{
	ASSERT_EQ(munmap(self->region, REGION_SIZE), 0);
	if (self->fd != -1)
		ASSERT_EQ(close(self->fd), 0);
}

TEST_F(perf_mmap, remap)
{
	void *tmp, *ptr = self->ptr;
	unsigned long size = variant->ptr_size;

	// Test the invalid remaps
	ASSERT_EQ(mremap(ptr, size, HOLE_SIZE, MREMAP_MAYMOVE), MAP_FAILED);
	ASSERT_EQ(mremap(ptr + HOLE_SIZE, size, HOLE_SIZE, MREMAP_MAYMOVE), MAP_FAILED);
	ASSERT_EQ(mremap(ptr + size - HOLE_SIZE, HOLE_SIZE, size, MREMAP_MAYMOVE), MAP_FAILED);
	// Shrink the end of the mapping such that we only unmap past end of the VMA,
	// which should succeed and poke a hole into the PROT_NONE region

Annotation

Implementation Notes