brintos

brintos / linux-shallow public Read only

0
0
Text · 3.1 KiB · 3213579 Raw
189 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright 2014, Michael Ellerman, IBM Corp.4 */5 6#define _GNU_SOURCE	/* For CPU_ZERO etc. */7 8#include <errno.h>9#include <sched.h>10#include <setjmp.h>11#include <stdlib.h>12#include <sys/wait.h>13 14#include "utils.h"15#include "lib.h"16 17#define PARENT_TOKEN	0xAA18#define CHILD_TOKEN	0x5519 20int sync_with_child(union pipe read_pipe, union pipe write_pipe)21{22	char c = PARENT_TOKEN;23 24	FAIL_IF(write(write_pipe.write_fd, &c, 1) != 1);25	FAIL_IF(read(read_pipe.read_fd, &c, 1) != 1);26	if (c != CHILD_TOKEN) /* sometimes expected */27		return 1;28 29	return 0;30}31 32int wait_for_parent(union pipe read_pipe)33{34	char c;35 36	FAIL_IF(read(read_pipe.read_fd, &c, 1) != 1);37	FAIL_IF(c != PARENT_TOKEN);38 39	return 0;40}41 42int notify_parent(union pipe write_pipe)43{44	char c = CHILD_TOKEN;45 46	FAIL_IF(write(write_pipe.write_fd, &c, 1) != 1);47 48	return 0;49}50 51int notify_parent_of_error(union pipe write_pipe)52{53	char c = ~CHILD_TOKEN;54 55	FAIL_IF(write(write_pipe.write_fd, &c, 1) != 1);56 57	return 0;58}59 60int wait_for_child(pid_t child_pid)61{62	int rc;63 64	if (waitpid(child_pid, &rc, 0) == -1) {65		perror("waitpid");66		return 1;67	}68 69	if (WIFEXITED(rc))70		rc = WEXITSTATUS(rc);71	else72		rc = 1; /* Signal or other */73 74	return rc;75}76 77int kill_child_and_wait(pid_t child_pid)78{79	kill(child_pid, SIGTERM);80 81	return wait_for_child(child_pid);82}83 84static int eat_cpu_child(union pipe read_pipe, union pipe write_pipe)85{86	volatile int i = 0;87 88	/*89	 * We are just here to eat cpu and die. So make sure we can be killed,90	 * and also don't do any custom SIGTERM handling.91	 */92	signal(SIGTERM, SIG_DFL);93 94	notify_parent(write_pipe);95	wait_for_parent(read_pipe);96 97	/* Soak up cpu forever */98	while (1) i++;99 100	return 0;101}102 103pid_t eat_cpu(int (test_function)(void))104{105	union pipe read_pipe, write_pipe;106	int rc;107	pid_t pid;108 109	FAIL_IF(bind_to_cpu(BIND_CPU_ANY) < 0);110 111	if (pipe(read_pipe.fds) == -1)112		return -1;113 114	if (pipe(write_pipe.fds) == -1)115		return -1;116 117	pid = fork();118	if (pid == 0)119		exit(eat_cpu_child(write_pipe, read_pipe));120 121	if (sync_with_child(read_pipe, write_pipe)) {122		rc = -1;123		goto out;124	}125 126	printf("main test running as pid %d\n", getpid());127 128	rc = test_function();129out:130	kill(pid, SIGKILL);131 132	return rc;133}134 135struct addr_range libc, vdso;136 137int parse_proc_maps(void)138{139	unsigned long start, end;140	char execute, name[128];141	FILE *f;142	int rc;143 144	f = fopen("/proc/self/maps", "r");145	if (!f) {146		perror("fopen");147		return -1;148	}149 150	do {151		/* This skips line with no executable which is what we want */152		rc = fscanf(f, "%lx-%lx %*c%*c%c%*c %*x %*d:%*d %*d %127s\n",153			    &start, &end, &execute, name);154		if (rc <= 0)155			break;156 157		if (execute != 'x')158			continue;159 160		if (strstr(name, "libc")) {161			libc.first = start;162			libc.last = end - 1;163		} else if (strstr(name, "[vdso]")) {164			vdso.first = start;165			vdso.last = end - 1;166		}167	} while(1);168 169	fclose(f);170 171	return 0;172}173 174#define PARANOID_PATH	"/proc/sys/kernel/perf_event_paranoid"175 176bool require_paranoia_below(int level)177{178	int err;179	long current;180 181	err = read_long(PARANOID_PATH, &current, 10);182	if (err) {183		printf("Couldn't parse " PARANOID_PATH "?\n");184		return false;185	}186 187	return current < level;188}189