Skip to content

Instantly share code, notes, and snippets.

@nnethercote
Created August 21, 2015 05:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nnethercote/11ab3290006c095159bc to your computer and use it in GitHub Desktop.
Save nnethercote/11ab3290006c095159bc to your computer and use it in GitHub Desktop.
Program that triggers N wakeups per second
#include <mach/mach_init.h>
#include <mach/task.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
static void
Error(const char *aMsg)
{
fprintf(stderr, "error: %s\n", aMsg);
exit(1);
}
static bool
GetTaskPowerInfo(struct task_power_info* aInfo)
{
mach_msg_type_number_t count = TASK_POWER_INFO_COUNT;
kern_return_t kr =
task_info(mach_task_self(), TASK_POWER_INFO, (task_info_t)aInfo, &count);
return kr == KERN_SUCCESS;
}
// Set in main() from the command line.
static long gFreq = 0;
static void
SigprofHandler(int aSigNum, siginfo_t* aInfo, void *aContext)
{
static int n = 0;
if (n++ % gFreq == 0) {
task_power_info info;
if (!GetTaskPowerInfo(&info)) {
printf("tick: ???");
} else {
printf("tick: irpt=%llu, idle=%llu, bin1=%llu, bin2=%llu\n",
info.task_interrupt_wakeups, info.task_platform_idle_wakeups,
info.task_timer_wakeups_bin_1, info.task_timer_wakeups_bin_2);
}
fflush(stdout); // without this the script swallows the output, somehow
}
}
int
main(int argc, char* argv[])
{
if (argc != 2) {
Error("must provide a frequency argument");
}
char* endptr;
gFreq = strtol(argv[1], &endptr, /* base = */ 10);
if (*endptr) {
Error("frequency is not an integer");
}
if (gFreq < 2 || gFreq > 1000000) {
Error("frequency must be in the range 2..1000000");
}
// Install the signal handler.
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = SigprofHandler;
sa.sa_flags = SA_RESTART | SA_SIGINFO;
if (sigemptyset(&sa.sa_mask) < 0) {
Error("sigemptyset failed");
}
if (sigaction(SIGALRM, &sa, NULL) < 0) {
Error("sigaction failed");
}
// Set up the timer.
struct itimerval timer;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 1000000 / gFreq;
timer.it_value = timer.it_interval;
if (setitimer(ITIMER_REAL, &timer, NULL) < 0) {
Error("setitimer failed");
}
while (true) {
pause();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment