| #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; | |
| } |