Skip to content

Instantly share code, notes, and snippets.

@menski
Created May 30, 2013 07:02
Show Gist options
  • Select an option

  • Save menski/5676161 to your computer and use it in GitHub Desktop.

Select an option

Save menski/5676161 to your computer and use it in GitHub Desktop.
monitor unhalted cycles
#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