]> git.saurik.com Git - apple/xnu.git/blame - tools/tests/perf_index/main.c
xnu-2422.115.4.tar.gz
[apple/xnu.git] / tools / tests / perf_index / main.c
CommitLineData
39236c6e
A
1#include <stdio.h>
2#include <string.h>
3#include <inttypes.h>
4#include <pthread.h>
5#include "perf_index.h"
6#include <sys/time.h>
7#include <sys/socket.h>
8#include <netdb.h>
9
10#define CONTROL_PORT 17694
11
12static const stress_test_t *stress_tests[] =
13{&cpu_test, &memory_test, &syscall_test, &fault_test, &zfod_test,
14 &file_local_create_test, &file_local_write_test, &file_local_read_test,
15 &file_ram_create_test, &file_ram_read_test, &file_ram_write_test, &iperf_test,
16 &compile_test
17};
18
19static int num_threads;
20static long long all_len;
21static int test_type;
22static const char *control_host = NULL;
23static const char **test_argv;
24static int test_argc;
25struct in_addr control_host_addr;
26int control_sock;
27const char remote_str[] = "remote";
28const char ready_msg[] = "Ready";
29const char done_msg[] = "Done";
30
31static pthread_cond_t threads_running_cvar;
32static pthread_cond_t start_cvar;
33static int thread_count;
34static pthread_mutex_t count_lock;
35
36static void usage() {
37 int i;
38 fprintf(stderr, "usage: perf_index remote server\n"
39 "or\n"
40 "usage: pref_index type threads size [args]\n\n"
41 "where type is one of:\n");
42 for(i=0; i<sizeof(stress_tests)/sizeof(stress_test_t*); i++) {
43 fprintf(stderr, "%s ", stress_tests[i]->name);
44 }
45 fprintf(stderr, "\n");
46 exit(1);
47}
48
49static int validate_args(int argc, const char **argv) {
50 int i;
51 int ret;
52 int found = 0;
53
54 if(argc < 3) {
55 return -1;
56 }
57 if(argc==3 && strcmp(argv[1], remote_str) == 0)
58 return 0;
59
60
61 if(argc < 4)
62 return -1;
63
64 ret = -1;
65 for(i=0; i<sizeof(stress_tests)/sizeof(stress_test_t*); i++) {
66 if(strcmp(argv[1], stress_tests[i]->name) == 0) {
67 ret = i;
68 found = 1;
69 break;
70 }
71 }
72
73 if(!found)
74 return -1;
75
76 if(stress_tests[i]->validate(argc-4, argv+4))
77 return ret;
78 else
79 return -1;
80}
81
82int host_to_addr(const char *hostname, struct in_addr *addr) {
83 struct addrinfo *info;
84 int err;
85 if((err = getaddrinfo(hostname, NULL, NULL, &info)) != 0) {
86 return -1;
87 }
88 *addr = ((struct sockaddr_in*)info->ai_addr)->sin_addr;
89 freeaddrinfo(info);
90 return 0;
91}
92
93static void parse_args(int argc, const char **argv);
94
95static void read_params_from_server(void) {
96 struct sockaddr_in addr;
97 char readbuff[1024];
98 int zerocount = 0;
99 ssize_t offset = 0;
100 ssize_t recv_count;
101 ssize_t i;
102 const char **newargv = malloc(sizeof(char*) * 4);
103 assert(newargv != NULL);
104
105 if(host_to_addr(control_host, &control_host_addr)<0) {
106 fprintf(stderr, "Could not resolve: %s\n", control_host);
107 exit(2);
108 }
109
110 control_sock = socket(PF_INET, SOCK_STREAM, 0);
111 assert(control_sock != -1);
112 addr.sin_family = AF_INET;
113 addr.sin_port = htons(CONTROL_PORT);
114 addr.sin_addr = control_host_addr;
115 bzero(addr.sin_zero, sizeof addr.sin_zero);
116 if(connect(control_sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
117 fprintf(stderr, "Failed to connect to host: %s\n", control_host);
118 exit(3);
119 }
120
121 while(offset<sizeof(readbuff)) {
122 recv_count = recv(control_sock, readbuff+offset, sizeof(readbuff) - offset, 0);
123 if(recv_count<0) {
124 fprintf(stderr, "Failed to receive parameters\n");
125 exit(3);
126 }
127
128 /* Guard against bad input */
129 readbuff[sizeof(readbuff)-1] = '\0';
130 newargv[1] = strdup(readbuff);
131 for(i=offset; i<offset+recv_count; i++) {
132 if(readbuff[i] == '\0') {
133 zerocount++;
134 newargv[zerocount+1] = strdup(&readbuff[i+1]);
135 }
136 }
137 offset += recv_count;
138 if(offset>=2 && readbuff[offset-1] == '\0' && readbuff[offset-2] == '\0')
139 break;
140 }
141 if(zerocount < 3) {
142 fprintf(stderr, "Received invalid parameters");
143 exit(4);
144 }
145
146 parse_args(zerocount+1, newargv);
147}
148
149static void parse_args(int argc, const char **argv) {
150 test_type = validate_args(argc, argv);
151 if(test_type < 0)
152 usage();
153 if(strcmp(argv[1], remote_str) == 0) {
154 control_host = argv[2];
155 read_params_from_server();
156 }
157 else {
158 num_threads = strtoimax(argv[2], NULL, 10);
159 all_len = strtoll(argv[3], NULL, 10);
160 test_argc = argc - 4;
161 test_argv = argv + 4;
162 }
163}
164
165static void *stress_loop(void *data) {
166 int my_index = (int)data;
167 long long work_size = all_len / num_threads;
168 int work_remainder = all_len % num_threads;
169
170 if(work_remainder > my_index) {
171 work_size++;
172 }
173
174 pthread_mutex_lock(&count_lock);
175 thread_count++;
176 if(thread_count == num_threads)
177 pthread_cond_signal(&threads_running_cvar);
178 pthread_cond_wait(&start_cvar, &count_lock);
179 pthread_mutex_unlock(&count_lock);
180 stress_tests[test_type]->stress(my_index, num_threads, work_size, test_argc, test_argv);
181 return NULL;
182}
183
184void start_timer(struct timeval *tp) {
185 gettimeofday(tp, NULL);
186}
187
188void end_timer(struct timeval *tp) {
189 struct timeval tend;
190 gettimeofday(&tend, NULL);
191 if(tend.tv_usec >= tp->tv_usec) {
192 tp->tv_sec = tend.tv_sec - tp->tv_sec;
193 tp->tv_usec = tend.tv_usec - tp->tv_usec;
194 }
195 else {
196 tp->tv_sec = tend.tv_sec - tp->tv_sec - 1;
197 tp->tv_usec = tend.tv_usec - tp->tv_usec + 1000000;
198 }
199}
200
201void print_timer(struct timeval *tp) {
202 printf("%ld.%06d", tp->tv_sec, tp->tv_usec);
203}
204
205void wait_start(void) {
206 char readbuff[1024];
207 if(control_host != NULL) {
208 send(control_sock, ready_msg, strlen(ready_msg), 0);
209 while(recv(control_sock, readbuff, sizeof(readbuff), 0)>0);
210 }
211}
212
213void done(void) {
214 send(control_sock, done_msg, strlen(done_msg), 0);
215}
216
217int main(int argc, const char **argv) {
218 int thread_index;
219 pthread_t *threads;
220 parse_args(argc, argv);
221 struct timeval timer;
222
223 stress_tests[test_type]->init(num_threads, all_len, test_argc, test_argv);
224 pthread_cond_init(&threads_running_cvar, NULL);
225 pthread_cond_init(&start_cvar, NULL);
226 pthread_mutex_init(&count_lock, NULL);
227 thread_count = 0;
228
229 threads = (pthread_t*)malloc(sizeof(pthread_t)*num_threads);
230 for(thread_index = 0; thread_index < num_threads; thread_index++) {
231 assert(pthread_create(&threads[thread_index], NULL, stress_loop, (void*)thread_index) == 0);
232 }
233
234 pthread_mutex_lock(&count_lock);
235 if(thread_count != num_threads)
236 pthread_cond_wait(&threads_running_cvar, &count_lock);
237 pthread_mutex_unlock(&count_lock);
238
239 wait_start();
240
241 start_timer(&timer);
242 pthread_cond_broadcast(&start_cvar);
243 for(thread_index = 0; thread_index < num_threads; thread_index++) {
244 pthread_join(threads[thread_index], NULL);
245 }
246 end_timer(&timer);
247 done();
248
249 pthread_mutex_destroy(&count_lock);
250 pthread_cond_destroy(&start_cvar);
251 pthread_cond_destroy(&threads_running_cvar);
252
253 stress_tests[test_type]->cleanup(num_threads, all_len);
254
255 print_timer(&timer);
256 printf("\n");
257
258 return 0;
259}