]> git.saurik.com Git - apple/xnu.git/blob - tools/tests/perf_index/PerfIndex_COPS_Module/PITest.m
xnu-3248.60.10.tar.gz
[apple/xnu.git] / tools / tests / perf_index / PerfIndex_COPS_Module / PITest.m
1 //
2 // PITest.m
3 // PerfIndex
4 //
5 // Created by Mark Hamilton on 8/21/13.
6 //
7 //
8
9 #import "PITest.h"
10 #include <dlfcn.h>
11 #include <pthread.h>
12
13 @implementation PITest
14
15 + (id)testWithOptions:(NSDictionary *)options
16 {
17 PITest *instance = nil;
18 if(instance == nil)
19 instance = [[PITest alloc] init];
20 [instance setTestName:[options objectForKey:@"name"]];
21 return instance;
22 }
23
24 - (BOOL)loadPITestAtPath:(NSString*) path
25 {
26 void* handle;
27 void* f;
28
29 handle = dlopen([path UTF8String], RTLD_NOW | RTLD_LOCAL);
30 if(!handle) {
31 return NO;
32 }
33
34
35 f = dlsym(handle, "setup");
36 self->setup_func = (int (*)(int, long long, int, void **))f;
37
38 f = dlsym(handle, "execute");
39 self->execute_func = (int (*)(int, int, long long, int, void **))f;
40 if(!self->execute_func)
41 return NO;
42
43 f = dlsym(handle, "cleanup");
44 self->cleanup_func = (void (*)(int, long long))f;
45 return YES;
46 }
47
48 - (long long)lengthForTest:(NSString*) testName
49 {
50 NSNumber* number;
51 long long myLength;
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],
61 nil];
62
63 number = (NSNumber*)[lengths objectForKey:testName];
64 if(!number) {
65 myLength = 10;
66 } else {
67 myLength = [number longLongValue];
68 }
69
70 return myLength;
71 }
72
73 - (BOOL)setup
74 {
75 BOOL success = NO;
76 int retval;
77
78 NSString* testPath = [NSString stringWithFormat:@"/AppleInternal/CoreOS/perf_index/%@.dylib", [self testName]];
79 success = [self loadPITestAtPath:testPath];
80 if(!success) {
81 NSLog(@"Failed to load test %@", [self testName]);
82 return NO;
83 }
84
85 self->length = [self lengthForTest:[self testName]];
86 self->numThreads = 1;
87 self->testArgc = 0;
88 self->testArgv = NULL;
89
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;
94
95 if(self->setup_func) {
96 retval = self->setup_func(1, self->length, 0, NULL);
97 if(retval != 0) {
98 NSLog(@"setup_func failed");
99 return NO;
100 }
101 }
102
103 self->threads = (pthread_t*)malloc(sizeof(pthread_t)*self->numThreads);
104
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);
109 if(retval != 0) {
110 NSLog(@"pthread_create failed");
111 free(self->threads);
112 return NO;
113 }
114 }
115
116 pthread_mutex_lock(&self->readyThreadCountLock);
117 if(self->readyThreadCount != self->numThreads) {
118 pthread_cond_wait(&self->threadsReadyCvar, &self->readyThreadCountLock);
119 }
120 pthread_mutex_unlock(&self->readyThreadCountLock);
121 return YES;
122 }
123
124 - (BOOL)execute
125 {
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);
129 }
130 return YES;
131 }
132
133 - (void)cleanup
134 {
135 free(self->threads);
136 if(self->cleanup_func)
137 self->cleanup_func(0, self->length);
138 }
139
140 void* thread_setup(void* arg)
141 {
142 int my_index = (int)[(NSNumber*)[(__bridge NSArray*)arg objectAtIndex:0] integerValue];
143 PITest* test = (PITest*)[(__bridge NSArray*)arg objectAtIndex:1];
144
145 long long work_size = test->length / test->numThreads;
146 int work_remainder = test->length % test->numThreads;
147
148 if(work_remainder > my_index) {
149 work_size++;
150 }
151
152 pthread_mutex_lock(&test->readyThreadCountLock);
153 test->readyThreadCount++;
154
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);
160
161 return NULL;
162 }
163
164 @end