tools/testing/selftests/mm/rmap.c

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/mm/rmap.c
Extension
.c
Size
9270 bytes
Lines
434
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 global_data {
	int worker_level;

	int semid;
	int pipefd[2];

	unsigned int mapsize;
	unsigned int rand_seed;
	char *region;

	prepare_fn do_prepare;
	work_fn do_work;
	check_fn do_check;

	enum backend_type backend;
	char filename[MAX_FILENAME_LEN];

	unsigned long *expected_pfn;
};

/*
 * Create a process tree with TOTAL_LEVEL height and at most MAX_CHILDREN
 * children for each.
 *
 * It will randomly select one process as 'worker' process which will
 * 'do_work' until all processes are created. And all other processes will
 * wait until 'worker' finish its work.
 */
void propagate_children(struct __test_metadata *_metadata, struct global_data *data)
{
	pid_t root_pid, pid;
	unsigned int num_child;
	int status;
	int ret = 0;
	int curr_child, worker_child;
	int curr_level = 1;
	bool is_worker = true;

	root_pid = getpid();
repeat:
	num_child = rand_r(&data->rand_seed) % MAX_CHILDREN + 1;
	worker_child = is_worker ? rand_r(&data->rand_seed) % num_child : -1;

	for (curr_child = 0; curr_child < num_child; curr_child++) {
		pid = fork();

		if (pid < 0) {
			perror("Error: fork\n");
		} else if (pid == 0) {
			curr_level++;

			if (curr_child != worker_child)
				is_worker = false;

			if (curr_level == TOTAL_LEVEL)
				break;

			data->rand_seed += curr_child;
			goto repeat;
		}
	}

	if (data->do_prepare)
		data->do_prepare(data);

	close(data->pipefd[1]);

	if (is_worker && curr_level == data->worker_level) {
		/* This is the worker process, first wait last process created */
		char buf;

		while (read(data->pipefd[0], &buf, 1) > 0)
			;

		if (data->do_work)
			ret = data->do_work(data);

		/* Kick others */
		semctl(data->semid, 0, IPC_RMID);
	} else {
		/* Wait worker finish */
		semop(data->semid, &sem_wait, 1);
		if (data->do_check)
			ret = data->do_check(data);
	}

	/* Wait all child to quit */
	while (wait(&status) > 0) {
		if (WIFEXITED(status))
			ret |= WEXITSTATUS(status);

Annotation

Implementation Notes