5 // Created by Mark Hamilton on 8/21/13.
13 @implementation PITest
15 + (id)testWithOptions:(NSDictionary *)options
17 PITest *instance = nil;
19 instance = [[PITest alloc] init];
20 [instance setTestName:[options objectForKey:@"name"]];
24 - (BOOL)loadPITestAtPath:(NSString*) path
29 handle = dlopen([path UTF8String], RTLD_NOW | RTLD_LOCAL);
35 f = dlsym(handle, "setup");
36 self->setup_func = (int (*)(int, long long, int, void **))f;
38 f = dlsym(handle, "execute");
39 self->execute_func = (int (*)(int, int, long long, int, void **))f;
40 if(!self->execute_func)
43 f = dlsym(handle, "cleanup");
44 self->cleanup_func = (void (*)(int, long long))f;
48 - (long long)lengthForTest:(NSString*) testName
52 NSDictionary* lengths = [NSDictionary dictionaryWithObjectsAndKeys:
53 @"cpu", [NSNumber numberWithLongLong:2000],
54 @"syscall", [NSNumber numberWithLongLong:2500],
55 @"memory", [NSNumber numberWithLongLong:1000000],
56 @"fault", [NSNumber numberWithLongLong:500],
57 @"zfod", [NSNumber numberWithLongLong:500],
58 @"file_create", [NSNumber numberWithLongLong:10],
59 @"file_read", [NSNumber numberWithLongLong:1000000],
60 @"file_write", [NSNumber numberWithLongLong:1000000],
63 number = (NSNumber*)[lengths objectForKey:testName];
67 myLength = [number longLongValue];
78 NSString* testPath = [NSString stringWithFormat:@"/AppleInternal/CoreOS/perf_index/%@.dylib", [self testName]];
79 success = [self loadPITestAtPath:testPath];
81 NSLog(@"Failed to load test %@", [self testName]);
85 self->length = [self lengthForTest:[self testName]];
88 self->testArgv = NULL;
90 pthread_cond_init(&self->threadsReadyCvar, NULL);
91 pthread_cond_init(&self->startCvar, NULL);
92 pthread_mutex_init(&self->readyThreadCountLock, NULL);
93 self->readyThreadCount = 0;
95 if(self->setup_func) {
96 retval = self->setup_func(1, self->length, 0, NULL);
98 NSLog(@"setup_func failed");
103 self->threads = (pthread_t*)malloc(sizeof(pthread_t)*self->numThreads);
105 for(int thread_index = 0; thread_index < self->numThreads; thread_index++) {
106 NSNumber* my_thread_index = [NSNumber numberWithInt:thread_index];
107 NSArray *arg = [NSArray arrayWithObjects:my_thread_index, self, nil];
108 retval = pthread_create(&threads[thread_index], NULL, thread_setup, (__bridge void*)arg);
110 NSLog(@"pthread_create failed");
116 pthread_mutex_lock(&self->readyThreadCountLock);
117 if(self->readyThreadCount != self->numThreads) {
118 pthread_cond_wait(&self->threadsReadyCvar, &self->readyThreadCountLock);
120 pthread_mutex_unlock(&self->readyThreadCountLock);
126 pthread_cond_broadcast(&self->startCvar);
127 for(int thread_index = 0; thread_index < self->numThreads; thread_index++) {
128 pthread_join(self->threads[thread_index], NULL);
136 if(self->cleanup_func)
137 self->cleanup_func(0, self->length);
140 void* thread_setup(void* arg)
142 int my_index = (int)[(NSNumber*)[(__bridge NSArray*)arg objectAtIndex:0] integerValue];
143 PITest* test = (PITest*)[(__bridge NSArray*)arg objectAtIndex:1];
145 long long work_size = test->length / test->numThreads;
146 int work_remainder = test->length % test->numThreads;
148 if(work_remainder > my_index) {
152 pthread_mutex_lock(&test->readyThreadCountLock);
153 test->readyThreadCount++;
155 if(test->readyThreadCount == test->numThreads)
156 pthread_cond_signal(&test->threadsReadyCvar);
157 pthread_cond_wait(&test->startCvar, &test->readyThreadCountLock);
158 pthread_mutex_unlock(&test->readyThreadCountLock);
159 test->execute_func(my_index, test->numThreads, work_size, test->testArgc, test->testArgv);