1*19c3b8c2SApple OSS Distributions// 2*19c3b8c2SApple OSS Distributions// PITest.m 3*19c3b8c2SApple OSS Distributions// PerfIndex 4*19c3b8c2SApple OSS Distributions// 5*19c3b8c2SApple OSS Distributions// Created by Mark Hamilton on 8/21/13. 6*19c3b8c2SApple OSS Distributions// 7*19c3b8c2SApple OSS Distributions// 8*19c3b8c2SApple OSS Distributions 9*19c3b8c2SApple OSS Distributions#import "PITest.h" 10*19c3b8c2SApple OSS Distributions#include <dlfcn.h> 11*19c3b8c2SApple OSS Distributions#include <pthread.h> 12*19c3b8c2SApple OSS Distributions 13*19c3b8c2SApple OSS Distributions@implementation PITest 14*19c3b8c2SApple OSS Distributions 15*19c3b8c2SApple OSS Distributions+ (id)testWithOptions:(NSDictionary *)options 16*19c3b8c2SApple OSS Distributions{ 17*19c3b8c2SApple OSS Distributions PITest *instance = nil; 18*19c3b8c2SApple OSS Distributions if(instance == nil) 19*19c3b8c2SApple OSS Distributions instance = [[PITest alloc] init]; 20*19c3b8c2SApple OSS Distributions [instance setTestName:[options objectForKey:@"name"]]; 21*19c3b8c2SApple OSS Distributions return instance; 22*19c3b8c2SApple OSS Distributions} 23*19c3b8c2SApple OSS Distributions 24*19c3b8c2SApple OSS Distributions- (BOOL)loadPITestAtPath:(NSString*) path 25*19c3b8c2SApple OSS Distributions{ 26*19c3b8c2SApple OSS Distributions void* handle; 27*19c3b8c2SApple OSS Distributions void* f; 28*19c3b8c2SApple OSS Distributions 29*19c3b8c2SApple OSS Distributions handle = dlopen([path UTF8String], RTLD_NOW | RTLD_LOCAL); 30*19c3b8c2SApple OSS Distributions if(!handle) { 31*19c3b8c2SApple OSS Distributions return NO; 32*19c3b8c2SApple OSS Distributions } 33*19c3b8c2SApple OSS Distributions 34*19c3b8c2SApple OSS Distributions 35*19c3b8c2SApple OSS Distributions f = dlsym(handle, "setup"); 36*19c3b8c2SApple OSS Distributions self->setup_func = (int (*)(int, long long, int, void **))f; 37*19c3b8c2SApple OSS Distributions 38*19c3b8c2SApple OSS Distributions f = dlsym(handle, "execute"); 39*19c3b8c2SApple OSS Distributions self->execute_func = (int (*)(int, int, long long, int, void **))f; 40*19c3b8c2SApple OSS Distributions if(!self->execute_func) 41*19c3b8c2SApple OSS Distributions return NO; 42*19c3b8c2SApple OSS Distributions 43*19c3b8c2SApple OSS Distributions f = dlsym(handle, "cleanup"); 44*19c3b8c2SApple OSS Distributions self->cleanup_func = (void (*)(int, long long))f; 45*19c3b8c2SApple OSS Distributions return YES; 46*19c3b8c2SApple OSS Distributions} 47*19c3b8c2SApple OSS Distributions 48*19c3b8c2SApple OSS Distributions- (long long)lengthForTest:(NSString*) testName 49*19c3b8c2SApple OSS Distributions{ 50*19c3b8c2SApple OSS Distributions NSNumber* number; 51*19c3b8c2SApple OSS Distributions long long myLength; 52*19c3b8c2SApple OSS Distributions NSDictionary* lengths = [NSDictionary dictionaryWithObjectsAndKeys: 53*19c3b8c2SApple OSS Distributions @"cpu", [NSNumber numberWithLongLong:2000], 54*19c3b8c2SApple OSS Distributions @"syscall", [NSNumber numberWithLongLong:2500], 55*19c3b8c2SApple OSS Distributions @"memory", [NSNumber numberWithLongLong:1000000], 56*19c3b8c2SApple OSS Distributions @"fault", [NSNumber numberWithLongLong:500], 57*19c3b8c2SApple OSS Distributions @"zfod", [NSNumber numberWithLongLong:500], 58*19c3b8c2SApple OSS Distributions @"file_create", [NSNumber numberWithLongLong:10], 59*19c3b8c2SApple OSS Distributions @"file_read", [NSNumber numberWithLongLong:1000000], 60*19c3b8c2SApple OSS Distributions @"file_write", [NSNumber numberWithLongLong:1000000], 61*19c3b8c2SApple OSS Distributions nil]; 62*19c3b8c2SApple OSS Distributions 63*19c3b8c2SApple OSS Distributions number = (NSNumber*)[lengths objectForKey:testName]; 64*19c3b8c2SApple OSS Distributions if(!number) { 65*19c3b8c2SApple OSS Distributions myLength = 10; 66*19c3b8c2SApple OSS Distributions } else { 67*19c3b8c2SApple OSS Distributions myLength = [number longLongValue]; 68*19c3b8c2SApple OSS Distributions } 69*19c3b8c2SApple OSS Distributions 70*19c3b8c2SApple OSS Distributions return myLength; 71*19c3b8c2SApple OSS Distributions} 72*19c3b8c2SApple OSS Distributions 73*19c3b8c2SApple OSS Distributions- (BOOL)setup 74*19c3b8c2SApple OSS Distributions{ 75*19c3b8c2SApple OSS Distributions BOOL success = NO; 76*19c3b8c2SApple OSS Distributions int retval; 77*19c3b8c2SApple OSS Distributions 78*19c3b8c2SApple OSS Distributions NSString* testPath = [NSString stringWithFormat:@"/AppleInternal/CoreOS/perf_index/%@.dylib", [self testName]]; 79*19c3b8c2SApple OSS Distributions success = [self loadPITestAtPath:testPath]; 80*19c3b8c2SApple OSS Distributions if(!success) { 81*19c3b8c2SApple OSS Distributions NSLog(@"Failed to load test %@", [self testName]); 82*19c3b8c2SApple OSS Distributions return NO; 83*19c3b8c2SApple OSS Distributions } 84*19c3b8c2SApple OSS Distributions 85*19c3b8c2SApple OSS Distributions self->length = [self lengthForTest:[self testName]]; 86*19c3b8c2SApple OSS Distributions self->numThreads = 1; 87*19c3b8c2SApple OSS Distributions self->testArgc = 0; 88*19c3b8c2SApple OSS Distributions self->testArgv = NULL; 89*19c3b8c2SApple OSS Distributions 90*19c3b8c2SApple OSS Distributions pthread_cond_init(&self->threadsReadyCvar, NULL); 91*19c3b8c2SApple OSS Distributions pthread_cond_init(&self->startCvar, NULL); 92*19c3b8c2SApple OSS Distributions pthread_mutex_init(&self->readyThreadCountLock, NULL); 93*19c3b8c2SApple OSS Distributions self->readyThreadCount = 0; 94*19c3b8c2SApple OSS Distributions 95*19c3b8c2SApple OSS Distributions if(self->setup_func) { 96*19c3b8c2SApple OSS Distributions retval = self->setup_func(1, self->length, 0, NULL); 97*19c3b8c2SApple OSS Distributions if(retval != 0) { 98*19c3b8c2SApple OSS Distributions NSLog(@"setup_func failed"); 99*19c3b8c2SApple OSS Distributions return NO; 100*19c3b8c2SApple OSS Distributions } 101*19c3b8c2SApple OSS Distributions } 102*19c3b8c2SApple OSS Distributions 103*19c3b8c2SApple OSS Distributions self->threads = (pthread_t*)malloc(sizeof(pthread_t)*self->numThreads); 104*19c3b8c2SApple OSS Distributions 105*19c3b8c2SApple OSS Distributions for(int thread_index = 0; thread_index < self->numThreads; thread_index++) { 106*19c3b8c2SApple OSS Distributions NSNumber* my_thread_index = [NSNumber numberWithInt:thread_index]; 107*19c3b8c2SApple OSS Distributions NSArray *arg = [NSArray arrayWithObjects:my_thread_index, self, nil]; 108*19c3b8c2SApple OSS Distributions retval = pthread_create(&threads[thread_index], NULL, thread_setup, (__bridge void*)arg); 109*19c3b8c2SApple OSS Distributions if(retval != 0) { 110*19c3b8c2SApple OSS Distributions NSLog(@"pthread_create failed"); 111*19c3b8c2SApple OSS Distributions free(self->threads); 112*19c3b8c2SApple OSS Distributions return NO; 113*19c3b8c2SApple OSS Distributions } 114*19c3b8c2SApple OSS Distributions } 115*19c3b8c2SApple OSS Distributions 116*19c3b8c2SApple OSS Distributions pthread_mutex_lock(&self->readyThreadCountLock); 117*19c3b8c2SApple OSS Distributions if(self->readyThreadCount != self->numThreads) { 118*19c3b8c2SApple OSS Distributions pthread_cond_wait(&self->threadsReadyCvar, &self->readyThreadCountLock); 119*19c3b8c2SApple OSS Distributions } 120*19c3b8c2SApple OSS Distributions pthread_mutex_unlock(&self->readyThreadCountLock); 121*19c3b8c2SApple OSS Distributions return YES; 122*19c3b8c2SApple OSS Distributions} 123*19c3b8c2SApple OSS Distributions 124*19c3b8c2SApple OSS Distributions- (BOOL)execute 125*19c3b8c2SApple OSS Distributions{ 126*19c3b8c2SApple OSS Distributions pthread_cond_broadcast(&self->startCvar); 127*19c3b8c2SApple OSS Distributions for(int thread_index = 0; thread_index < self->numThreads; thread_index++) { 128*19c3b8c2SApple OSS Distributions pthread_join(self->threads[thread_index], NULL); 129*19c3b8c2SApple OSS Distributions } 130*19c3b8c2SApple OSS Distributions return YES; 131*19c3b8c2SApple OSS Distributions} 132*19c3b8c2SApple OSS Distributions 133*19c3b8c2SApple OSS Distributions- (void)cleanup 134*19c3b8c2SApple OSS Distributions{ 135*19c3b8c2SApple OSS Distributions free(self->threads); 136*19c3b8c2SApple OSS Distributions if(self->cleanup_func) 137*19c3b8c2SApple OSS Distributions self->cleanup_func(0, self->length); 138*19c3b8c2SApple OSS Distributions} 139*19c3b8c2SApple OSS Distributions 140*19c3b8c2SApple OSS Distributionsvoid* thread_setup(void* arg) 141*19c3b8c2SApple OSS Distributions{ 142*19c3b8c2SApple OSS Distributions int my_index = (int)[(NSNumber*)[(__bridge NSArray*)arg objectAtIndex:0] integerValue]; 143*19c3b8c2SApple OSS Distributions PITest* test = (PITest*)[(__bridge NSArray*)arg objectAtIndex:1]; 144*19c3b8c2SApple OSS Distributions 145*19c3b8c2SApple OSS Distributions long long work_size = test->length / test->numThreads; 146*19c3b8c2SApple OSS Distributions int work_remainder = test->length % test->numThreads; 147*19c3b8c2SApple OSS Distributions 148*19c3b8c2SApple OSS Distributions if(work_remainder > my_index) { 149*19c3b8c2SApple OSS Distributions work_size++; 150*19c3b8c2SApple OSS Distributions } 151*19c3b8c2SApple OSS Distributions 152*19c3b8c2SApple OSS Distributions pthread_mutex_lock(&test->readyThreadCountLock); 153*19c3b8c2SApple OSS Distributions test->readyThreadCount++; 154*19c3b8c2SApple OSS Distributions 155*19c3b8c2SApple OSS Distributions if(test->readyThreadCount == test->numThreads) 156*19c3b8c2SApple OSS Distributions pthread_cond_signal(&test->threadsReadyCvar); 157*19c3b8c2SApple OSS Distributions pthread_cond_wait(&test->startCvar, &test->readyThreadCountLock); 158*19c3b8c2SApple OSS Distributions pthread_mutex_unlock(&test->readyThreadCountLock); 159*19c3b8c2SApple OSS Distributions test->execute_func(my_index, test->numThreads, work_size, test->testArgc, test->testArgv); 160*19c3b8c2SApple OSS Distributions 161*19c3b8c2SApple OSS Distributions return NULL; 162*19c3b8c2SApple OSS Distributions} 163*19c3b8c2SApple OSS Distributions 164*19c3b8c2SApple OSS Distributions@end 165