#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

#include <mach/mach_init.h>
#include <mach/thread_act.h>

#include <sys/sysctl.h>


void usage(const char *self) {
    printf("Usage: %s <executable> [<arguments>]\n", self);
}


int boost_priority() {
    // try to get ourselves realtime priority
    int mib[2] = {CTL_HW, HW_BUS_FREQ};
    int bus_speed;
    struct thread_time_constraint_policy ttcpolicy;
    size_t len = sizeof(bus_speed);
    if (sysctl(mib, 2, &bus_speed, &len, NULL, 0)) {
        return errno;
    }
    ttcpolicy.period = bus_speed/160;
    ttcpolicy.computation = bus_speed/3300;
    ttcpolicy.constraint = bus_speed/2200;
    ttcpolicy.preemptible = 1;
    return thread_policy_set(mach_thread_self(),
                             THREAD_TIME_CONSTRAINT_POLICY,
                             (int *)&ttcpolicy,
                             THREAD_TIME_CONSTRAINT_POLICY_COUNT);
}


int main (int argc, const char * argv[]) {
    int i;
    int retVal;
    
    // check the number of arguments
    if (argc < 2) {
        usage(argv[0]);
        exit(1);
    }
    
    // strip the first cmd line argument
    for (i = 1; i < argc; ++i) {
        argv[i-1] = argv[i];
    }
    argv[argc-1] = NULL;
    
    // try to exec
    if (retVal = boost_priority()) {
        printf("Failed to boost the priority\n");
        return retVal;
    }
    execv(argv[0], (char **const) argv);
    printf("Failed to call execv\n");
    return errno;
}
