// SPDX-License-Identifier: GPL-2.0 /* * Author: SeongJae Park <sj@kernel.org> */ #define _GNU_SOURCE #include <fcntl.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #include <unistd.h> #define DBGFS_MONITOR_ON "/sys/kernel/debug/damon/monitor_on_DEPRECATED" #define DBGFS_TARGET_IDS "/sys/kernel/debug/damon/target_ids" static void turn_damon_on_exit(void) { int target_ids_fd = open(DBGFS_TARGET_IDS, O_RDWR); int monitor_on_fd = open(DBGFS_MONITOR_ON, O_RDWR); char pid_str[128]; snprintf(pid_str, sizeof(pid_str), "%d", getpid()); write(target_ids_fd, pid_str, sizeof(pid_str)); write(monitor_on_fd, "on\n", 3); close(target_ids_fd); close(monitor_on_fd); usleep(1000); exit(0); } static void try_race(void) { int target_ids_fd = open(DBGFS_TARGET_IDS, O_RDWR); int pid = fork(); int buf[256]; if (pid < 0) { fprintf(stderr, "fork() failed\n"); exit(1); } if (pid == 0) turn_damon_on_exit(); while (true) { int status; read(target_ids_fd, buf, sizeof(buf)); if (waitpid(-1, &status, WNOHANG) == pid) break; } close(target_ids_fd); } static inline uint64_t ts_to_ms(struct timespec *ts) { return (uint64_t)ts->tv_sec * 1000 + (uint64_t)ts->tv_nsec / 1000000; } int main(int argc, char *argv[]) { struct timespec start_time, now; int runtime_ms; if (argc != 2) { fprintf(stderr, "Usage: %s <runtime in ms>\n", argv[0]); exit(1); } runtime_ms = atoi(argv[1]); clock_gettime(CLOCK_MONOTONIC, &start_time); while (true) { try_race(); clock_gettime(CLOCK_MONOTONIC, &now); if (ts_to_ms(&now) - ts_to_ms(&start_time) > runtime_ms) break; } return 0; }