#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #define gettid() syscall(__NR_gettid) #define KPROBE_FILE "/debug/tracing/kprobe_events" #define KPROBE_ENABLE "/debug/tracing/events/kprobes/sigprocmask/enable" #define PROBE "p:sigprocmask sigprocmask" #define INTERVALS 1000 #define INTERVAL_START 60000 #define INTERVAL_STOP 92000 #define INTERVAL_STEP (((INTERVAL_STOP - INTERVAL_START) * 7) / (INTERVALS * 5)) #define nano2sec(nan) (nan / 1000000000ULL) #define ms2nano(ms) (ms * 1000000ULL) #define sec2nano(sec) (sec * 1000000000ULL) static int pause_main = 1; static unsigned long long interval = INTERVAL_START; static pthread_barrier_t initiate; static pthread_barrier_t finish; static pthread_barrier_t restart; static int done; static void *write_it(void *ignore) { struct timespec intv; cpu_set_t cpumask; int ret; int fd; CPU_ZERO(&cpumask); CPU_SET(1, &cpumask); sched_setaffinity(gettid(), sizeof(long), &cpumask); while (!done) { intv.tv_sec = nano2sec(interval); intv.tv_nsec = interval % sec2nano(1); fd = open(KPROBE_ENABLE, O_WRONLY); if (fd < 0) { fprintf(stderr, "Can't open '%s'\n", KPROBE_ENABLE); exit(-1); } pthread_barrier_wait(&initiate); if (!pause_main) nanosleep(&intv, NULL); ret = write(fd, "1", 1); if (ret >= 0) printf("Enabled event! (%lld)\n", interval); write(fd, "0", 1); pthread_barrier_wait(&finish); write(fd, "0", 1); close(fd); pthread_barrier_wait(&restart); } return NULL; } static int open_kprobe(int trunc) { int fd; int flags = O_WRONLY; if (trunc) flags |= O_TRUNC; fd = open(KPROBE_FILE, flags); return fd; } static void create_probe(int fd) { if (write(fd, PROBE, strlen(PROBE)) < 0) { fprintf(stderr, "Failed to write to '%s'\n", KPROBE_FILE); exit(-1); } } int main (int argc, char **argv) { struct timespec intv; unsigned int intervals = INTERVALS; int start = INTERVAL_START; unsigned int stop = INTERVAL_STOP; unsigned int step = INTERVAL_STEP; cpu_set_t cpumask; pthread_t writer; int ret; int fd; int i; if (argc > 1) start = atoi(argv[1]); if (argc > 2) stop = atoi(argv[2]); if (argc > 3) intervals = atoi(argv[3]); if (start < 0) { pause_main = 0; start = start * -1; printf("PAUSING WRITE\n"); } /* Check for bad input (also 0 skips parameters) */ if (!start) start = INTERVAL_START; if (!stop) stop = INTERVAL_STOP; if (stop < start) stop = start + INTERVALS; if (!intervals) intervals = INTERVALS; if (argc > 1) { step = (((stop - start) * 7) / (intervals * 5)); interval = start; if (!step) step = 1; } printf("interval:\t%d\n", intervals); printf("start:\t%d\n", start); printf("stop:\t%d\n", stop); printf("step:\t%d\n", step); CPU_ZERO(&cpumask); CPU_SET(0, &cpumask); pthread_barrier_init(&initiate, NULL, 2); pthread_barrier_init(&finish, NULL, 2); pthread_barrier_init(&restart, NULL, 2); fd = open_kprobe(1); if (fd < 0) { fprintf(stderr, "Can't open '%s'\n", KPROBE_FILE); exit(-1); } create_probe(fd); close(fd); ret = pthread_create(&writer, NULL, write_it, NULL); if (ret < 0) exit(-1); sched_setaffinity(gettid(), sizeof(long), &cpumask); for (i = 0; i < intervals; i++) { if (pause_main) { intv.tv_sec = nano2sec(interval); intv.tv_nsec = interval % sec2nano(1); } else { intv.tv_sec = 0; intv.tv_nsec = 1; } pthread_barrier_wait(&initiate); nanosleep(&intv, NULL); while ((fd = open_kprobe(1)) < 0) ; pthread_barrier_wait(&finish); create_probe(fd); close(fd); pthread_barrier_wait(&restart); interval += step; if (interval > stop) interval = start + interval - stop; } done = 1; pthread_join(writer, NULL); fd = open_kprobe(1); close(fd); return 0; }