Created
May 30, 2013 07:02
-
-
Save menski/5676161 to your computer and use it in GitHub Desktop.
monitor unhalted cycles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #define _GNU_SOURCE 1 | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <signal.h> | |
| #include <sched.h> | |
| #include <unistd.h> | |
| #include <err.h> | |
| #include <sysexits.h> | |
| #include <time.h> | |
| #include <stdbool.h> | |
| #include <string.h> | |
| #include "cycles.h" | |
| #define FILENAME_SIZE 16 | |
| volatile sig_atomic_t sig_usr1_recvd = 0; | |
| volatile sig_atomic_t sig_int_recvd = 0; | |
| void sig_handler(int signal) | |
| { | |
| sig_usr1_recvd = signal == SIGUSR1; | |
| sig_int_recvd = signal == SIGINT; | |
| } | |
| static void log_unhalted_cycles(char* filename, bool session_end) { | |
| counter_t cycles; | |
| static counter_t last_cycles = 0; | |
| time_t t; | |
| char t_str[25]; | |
| FILE* fp; | |
| sync_core(); | |
| cycles = unhalted_core(); | |
| t = time(NULL); | |
| strftime(t_str, 25, "%Y-%m-%dT%H:%M:%S", localtime(&t)); | |
| /* no error logging here as we have closed all our outputs after forking */ | |
| fp = fopen(filename, "a"); | |
| if (fp != NULL) { | |
| fprintf(fp, "%s %llu (+%llu)%s\n", t_str, cycles, last_cycles ? cycles - last_cycles : 0, session_end ? " (end)\n" : ""); | |
| last_cycles = cycles; | |
| fclose(fp); | |
| } | |
| } | |
| int pin_process(int cpu) { | |
| cpu_set_t cpus; | |
| CPU_ZERO(&cpus); | |
| CPU_SET(cpu, &cpus); | |
| return sched_setaffinity(0, sizeof(cpu_set_t), &cpus); | |
| } | |
| int main(int argc, char **argv) { | |
| int i, max_cpu, cpu_count = 0; | |
| pid_t pid = -1; | |
| cpu_set_t cpus; | |
| char log_filename[FILENAME_SIZE]; | |
| struct sigaction sa; | |
| if (perfmon_available() <= 0) { | |
| errx(EX_OSERR, "No fixed perfmon available\n"); | |
| } | |
| CPU_ZERO(&cpus); | |
| if (sched_getaffinity(0, sizeof(cpu_set_t), &cpus) != 0) { | |
| err(EX_OSERR, "Unable to get affinity to determine online CPUs"); | |
| } | |
| max_cpu = sysconf(_SC_NPROCESSORS_CONF); | |
| for (i = 0; i < max_cpu; i++) { | |
| if (CPU_ISSET(i, &cpus)) { | |
| cpu_count++; | |
| pid = fork(); | |
| if (pid < 0) { | |
| err(EX_OSERR, "Unable to fork"); | |
| } else if (pid == 0) { | |
| fflush(stdout); | |
| if (pin_process(i) != 0) { | |
| err(EX_OSERR, "Unable to pin process to CPU %d\n", i); | |
| } | |
| snprintf(log_filename, FILENAME_SIZE, "cpu_%02d.log", i); | |
| break; | |
| } else { | |
| printf("Created child process %d for CPU %d\n", pid, i); | |
| fflush(stdout); | |
| } | |
| } | |
| } | |
| if (pid == 0) { | |
| memset(&sa, 0, sizeof(sa)); | |
| sa.sa_handler = &sig_handler; | |
| sa.sa_flags = 0; | |
| sigemptyset(&sa.sa_mask); | |
| sigaddset(&sa.sa_mask, SIGUSR1); | |
| sigaddset(&sa.sa_mask, SIGINT); | |
| if (sigaction(SIGUSR1, &sa, NULL) != 0) { | |
| err(EX_OSERR, "Unable to register SIGUSR1 signal action handler"); | |
| } | |
| if (sigaction(SIGINT, &sa, NULL) != 0) { | |
| err(EX_OSERR, "Unable to register SIGINT signal action handler"); | |
| } | |
| fclose(stdin); | |
| fclose(stdout); | |
| fclose(stderr); | |
| while (!sig_int_recvd) { | |
| pause(); | |
| if (sig_usr1_recvd) { | |
| sig_usr1_recvd = 0; | |
| log_unhalted_cycles(log_filename, false); | |
| } | |
| } | |
| /* mark end of "session" */ | |
| log_unhalted_cycles(log_filename, true); | |
| } else { | |
| /* | |
| printf("CPU count: %d\n", cpu_count); | |
| printf("Use 'killall -USR1 %s' to print unhalted cycles\n", argv[0]); | |
| printf("Use 'killall %s' to stop childs\n", argv[0]); | |
| */ | |
| } | |
| return EXIT_SUCCESS; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment