File: | pr/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/pr/tests/../../../pr/tests/sel_spd.c |
Warning: | line 468, column 5 Null pointer passed to 1st parameter expecting 'nonnull' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | |||
2 | /* This Source Code Form is subject to the terms of the Mozilla Public | |||
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |||
5 | ||||
6 | /* | |||
7 | * Test the speed of select within NSPR | |||
8 | * | |||
9 | */ | |||
10 | ||||
11 | #include "nspr.h" | |||
12 | #include "prpriv.h" | |||
13 | ||||
14 | #include <stdlib.h> | |||
15 | #include <stdio.h> | |||
16 | #include <errno(*__errno_location ()).h> | |||
17 | #include <string.h> | |||
18 | ||||
19 | #if defined(XP_UNIX1) | |||
20 | #include <unistd.h> | |||
21 | #endif | |||
22 | ||||
23 | #ifdef DEBUG1 | |||
24 | #define PORT_INC_DO+100 +100 | |||
25 | #else | |||
26 | #define PORT_INC_DO+100 | |||
27 | #endif | |||
28 | #ifdef IS_64 | |||
29 | #define PORT_INC_3264+200 +200 | |||
30 | #else | |||
31 | #define PORT_INC_3264+200 | |||
32 | #endif | |||
33 | ||||
34 | #define PORT_BASE19000 +100 +200 19000 PORT_INC_DO+100 PORT_INC_3264+200 | |||
35 | ||||
36 | typedef struct timer_slot_t { | |||
37 | unsigned long d_connect; | |||
38 | unsigned long d_cl_data; | |||
39 | unsigned long d_sv_data; | |||
40 | unsigned long d_close; | |||
41 | unsigned long d_total; | |||
42 | unsigned long requests; | |||
43 | } timer_slot_t; | |||
44 | ||||
45 | static long _iterations = 5; | |||
46 | static long _client_data = 8192; | |||
47 | ||||
48 | static long _server_data = (128*1024); | |||
49 | static long _threads_max = 10, _threads = 10; | |||
50 | ||||
51 | static int verbose=0; | |||
52 | static PRMonitor *exit_cv; | |||
53 | static long _thread_exit_count; | |||
54 | static timer_slot_t *timer_data; | |||
55 | static PRThreadScope scope1, scope2; | |||
56 | ||||
57 | void tally_results(int); | |||
58 | ||||
59 | /* return the diff in microseconds */ | |||
60 | unsigned long _delta(PRIntervalTime *start, PRIntervalTime *stop) | |||
61 | { | |||
62 | /* | |||
63 | * Will C do the right thing with unsigned arithemtic? | |||
64 | */ | |||
65 | return PR_IntervalToMicroseconds(*stop - *start); | |||
66 | } | |||
67 | ||||
68 | int _readn(PRFileDesc *sock, char *buf, int len) | |||
69 | { | |||
70 | int rem; | |||
71 | int bytes; | |||
72 | ||||
73 | for (rem=len; rem; rem -= bytes) { | |||
74 | bytes = PR_Recv(sock, buf+len-rem, rem, 0, PR_INTERVAL_NO_TIMEOUT0xffffffffUL); | |||
75 | if (bytes <= 0) { | |||
76 | return -1; | |||
77 | } | |||
78 | } | |||
79 | return len; | |||
80 | } | |||
81 | ||||
82 | void | |||
83 | _thread_exit(int id) | |||
84 | { | |||
85 | PR_EnterMonitor(exit_cv); | |||
86 | #ifdef DEBUG1 | |||
87 | fprintf(stdoutstdout, "Thread %d EXIT\n", id); | |||
88 | #endif | |||
89 | ||||
90 | _thread_exit_count--; | |||
91 | if (_thread_exit_count == 0) { | |||
92 | #ifdef DEBUG1 | |||
93 | fprintf(stdoutstdout, "Thread %d EXIT triggered notify\n", id); | |||
94 | #endif | |||
95 | PR_Notify(exit_cv); | |||
96 | } | |||
97 | PR_ExitMonitor(exit_cv); | |||
98 | } | |||
99 | ||||
100 | void | |||
101 | _server_thread(void *arg_id) | |||
102 | { | |||
103 | void _client_thread(void *); | |||
104 | int *id = (int *)arg_id; | |||
105 | PRFileDesc *sock; | |||
106 | PRSocketOptionData sockopt; | |||
107 | PRNetAddr sa; | |||
108 | PRFileDesc * newsock; | |||
109 | char *data_buffer = NULL((void*)0); | |||
110 | int data_buffer_size; | |||
111 | int index; | |||
112 | PRIntervalTime start, | |||
113 | connect_done, | |||
114 | read_done, | |||
115 | write_done, | |||
116 | close_done; | |||
117 | ||||
118 | ||||
119 | #ifdef DEBUG1 | |||
120 | fprintf(stdoutstdout, "server thread %d alive\n", *id); | |||
121 | #endif | |||
122 | ||||
123 | data_buffer_size = (_client_data>_server_data?_client_data:_server_data); | |||
124 | ||||
125 | if ( (data_buffer = (char *)PR_Malloc(data_buffer_size * sizeof(char))) == NULL((void*)0) ) { | |||
126 | fprintf(stderrstderr, "Error creating buffer in server thread %d\n", *id); | |||
127 | goto done; | |||
128 | } | |||
129 | ||||
130 | ||||
131 | if ( (sock = PR_NewTCPSocket()) == NULL((void*)0)) { | |||
132 | fprintf(stderrstderr, "Error creating socket in server thread %d\n", *id); | |||
133 | goto done; | |||
134 | } | |||
135 | ||||
136 | sockopt.option = PR_SockOpt_Reuseaddr; | |||
137 | sockopt.value.reuse_addr = PR_TRUE1; | |||
138 | if ( PR_SetSocketOption(sock, &sockopt) == PR_FAILURE) { | |||
139 | fprintf(stderrstderr, "Error setting socket option in server thread %d\n", *id); | |||
140 | goto done; | |||
141 | } | |||
142 | ||||
143 | memset(&sa, 0, sizeof(sa)); | |||
144 | sa.inet.family = PR_AF_INET2; | |||
145 | sa.inet.port = PR_htons(PORT_BASE19000 +100 +200 + *id); | |||
146 | sa.inet.ip = PR_htonl(PR_INADDR_ANY((in_addr_t) 0x00000000)); | |||
147 | ||||
148 | if ( PR_Bind(sock, &sa) < 0) { | |||
149 | fprintf(stderrstderr, "Error binding socket in server thread %d errno = %d\n", *id, errno(*__errno_location ())); | |||
150 | goto done; | |||
151 | } | |||
152 | ||||
153 | if ( PR_Listen(sock, 32) < 0 ) { | |||
154 | fprintf(stderrstderr, "Error listening to socket in server thread %d\n", *id); | |||
155 | goto done; | |||
156 | } | |||
157 | ||||
158 | /* Tell the client to start */ | |||
159 | if ( PR_CreateThread(PR_USER_THREAD, | |||
160 | _client_thread, | |||
161 | id, | |||
162 | PR_PRIORITY_NORMAL, | |||
163 | scope2, | |||
164 | PR_UNJOINABLE_THREAD, | |||
165 | 0) == NULL((void*)0)) { | |||
166 | fprintf(stderrstderr, "Error creating client thread %d\n", *id); | |||
167 | } | |||
168 | ||||
169 | for (index = 0; index< _iterations; index++) { | |||
170 | ||||
171 | #ifdef DEBUG1 | |||
172 | fprintf(stdoutstdout, "server thread %d loop %d\n", *id, index); | |||
173 | #endif | |||
174 | ||||
175 | start = PR_IntervalNow(); | |||
176 | ||||
177 | if ( (newsock = PR_Accept(sock, &sa, | |||
178 | PR_INTERVAL_NO_TIMEOUT0xffffffffUL)) == NULL((void*)0)) { | |||
179 | fprintf(stderrstderr, "Error accepting connection %d in server thread %d\n", | |||
180 | index, *id); | |||
181 | goto done; | |||
182 | } | |||
183 | #ifdef DEBUG1 | |||
184 | fprintf(stdoutstdout, "server thread %d got connection %d\n", *id, newsock); | |||
185 | #endif | |||
186 | ||||
187 | ||||
188 | connect_done = PR_IntervalNow(); | |||
189 | ||||
190 | if ( _readn(newsock, data_buffer, _client_data) < _client_data) { | |||
191 | fprintf(stderrstderr, "Error reading client data for iteration %d in server thread %d\n", index, *id ); | |||
192 | goto done; | |||
193 | } | |||
194 | ||||
195 | #ifdef DEBUG1 | |||
196 | fprintf(stdoutstdout, "server thread %d read %d bytes\n", *id, _client_data); | |||
197 | #endif | |||
198 | read_done = PR_IntervalNow(); | |||
199 | ||||
200 | if ( PR_Send(newsock, data_buffer, _server_data, 0, | |||
201 | PR_INTERVAL_NO_TIMEOUT0xffffffffUL) < _server_data) { | |||
202 | fprintf(stderrstderr, "Error sending client data for iteration %d in server thread %d\n", index, *id ); | |||
203 | goto done; | |||
204 | } | |||
205 | ||||
206 | #ifdef DEBUG1 | |||
207 | fprintf(stdoutstdout, "server thread %d write %d bytes\n", *id, _server_data); | |||
208 | #endif | |||
209 | ||||
210 | write_done = PR_IntervalNow(); | |||
211 | ||||
212 | PR_Close(newsock); | |||
213 | ||||
214 | close_done = PR_IntervalNow(); | |||
215 | ||||
216 | timer_data[2*(*id)].d_connect += _delta(&start, &connect_done); | |||
217 | timer_data[2*(*id)].d_cl_data += _delta(&connect_done, &read_done); | |||
218 | timer_data[2*(*id)].d_sv_data += _delta(&read_done, &write_done); | |||
219 | timer_data[2*(*id)].d_close += _delta(&write_done, &close_done); | |||
220 | timer_data[2*(*id)].d_total += _delta(&start, &close_done); | |||
221 | timer_data[2*(*id)].requests++; | |||
222 | ||||
223 | ||||
224 | #ifdef DEBUG1 | |||
225 | fprintf(stdoutstdout, "server: %d %d %d %d %d\n", | |||
226 | _delta(&start, &connect_done), _delta(&connect_done, &read_done), | |||
227 | _delta(&read_done, &write_done), _delta(&write_done, &close_done), | |||
228 | _delta(&start, &close_done)); | |||
229 | #endif | |||
230 | } | |||
231 | ||||
232 | done: | |||
233 | if (data_buffer != NULL((void*)0)) { | |||
234 | PR_Free (data_buffer); | |||
235 | } | |||
236 | if (sock) { | |||
237 | PR_Close(sock); | |||
238 | } | |||
239 | _thread_exit(*id); | |||
240 | return; | |||
241 | } | |||
242 | ||||
243 | void | |||
244 | _client_thread(void *arg_id) | |||
245 | { | |||
246 | int *id = (int *)arg_id; | |||
247 | int index; | |||
248 | PRNetAddr sa; | |||
249 | PRFileDesc *sock_h; | |||
250 | char *data_buffer = NULL((void*)0); | |||
251 | int data_buffer_size; | |||
252 | int bytes; | |||
253 | PRIntervalTime start, | |||
254 | connect_done, | |||
255 | read_done, | |||
256 | write_done, | |||
257 | close_done; | |||
258 | PRStatus rv; | |||
259 | ||||
260 | #ifdef DEBUG1 | |||
261 | fprintf(stdoutstdout, "client thread %d alive\n", *id); | |||
262 | #endif | |||
263 | ||||
264 | data_buffer_size = (_client_data>_server_data?_client_data:_server_data); | |||
265 | ||||
266 | if ( (data_buffer = (char *)PR_Malloc(data_buffer_size * sizeof(char))) == NULL((void*)0)) { | |||
267 | fprintf(stderrstderr, "Error creating buffer in server thread %d\n", *id); | |||
268 | goto done; | |||
269 | } | |||
270 | ||||
271 | memset(&sa, 0, sizeof(sa)); | |||
272 | rv = PR_InitializeNetAddr(PR_IpAddrLoopback, PORT_BASE19000 +100 +200 + *id, &sa); | |||
273 | PR_ASSERT(PR_SUCCESS == rv)((PR_SUCCESS == rv)?((void)0):PR_Assert("PR_SUCCESS == rv","../../../pr/tests/sel_spd.c" ,273)); | |||
274 | ||||
275 | for (index = 0; index< _iterations; index++) { | |||
276 | ||||
277 | #ifdef DEBUG1 | |||
278 | fprintf(stdoutstdout, "client thread %d loop %d\n", *id, index); | |||
279 | #endif | |||
280 | ||||
281 | start = PR_IntervalNow(); | |||
282 | if ( (sock_h = PR_NewTCPSocket()) == NULL((void*)0)) { | |||
283 | fprintf(stderrstderr, "Error creating socket %d in client thread %d\n", | |||
284 | index, *id); | |||
285 | goto done; | |||
286 | } | |||
287 | ||||
288 | #ifdef DEBUG1 | |||
289 | fprintf(stdoutstdout, "client thread %d socket created %d\n", *id, sock_h); | |||
290 | #endif | |||
291 | ||||
292 | if ( PR_Connect(sock_h, &sa, | |||
293 | PR_INTERVAL_NO_TIMEOUT0xffffffffUL) < 0) { | |||
294 | fprintf(stderrstderr, "Error accepting connection %d in client thread %d\n", | |||
295 | index, *id); | |||
296 | goto done; | |||
297 | } | |||
298 | ||||
299 | #ifdef DEBUG1 | |||
300 | fprintf(stdoutstdout, "client thread %d socket connected %d\n", *id, sock_h); | |||
301 | #endif | |||
302 | ||||
303 | connect_done = PR_IntervalNow(); | |||
304 | if ( PR_Send(sock_h, data_buffer, _client_data, 0, | |||
305 | PR_INTERVAL_NO_TIMEOUT0xffffffffUL) < _client_data) { | |||
306 | fprintf(stderrstderr, "Error sending client data for iteration %d in client thread %d\n", index, *id ); | |||
307 | goto done; | |||
308 | } | |||
309 | ||||
310 | #ifdef DEBUG1 | |||
311 | fprintf(stdoutstdout, "client thread %d socket wrote %d\n", *id, _client_data); | |||
312 | #endif | |||
313 | ||||
314 | write_done = PR_IntervalNow(); | |||
315 | if ( (bytes = _readn(sock_h, data_buffer, _server_data)) < _server_data) { | |||
316 | fprintf(stderrstderr, "Error reading server data for iteration %d in client thread %d (read %d bytes)\n", index, *id, bytes ); | |||
317 | goto done; | |||
318 | } | |||
319 | ||||
320 | #ifdef DEBUG1 | |||
321 | fprintf(stdoutstdout, "client thread %d socket read %d\n", *id, _server_data); | |||
322 | #endif | |||
323 | ||||
324 | read_done = PR_IntervalNow(); | |||
325 | PR_Close(sock_h); | |||
326 | close_done = PR_IntervalNow(); | |||
327 | ||||
328 | timer_data[2*(*id)+1].d_connect += _delta(&start, &connect_done); | |||
329 | timer_data[2*(*id)+1].d_cl_data += _delta(&connect_done, &write_done); | |||
330 | timer_data[2*(*id)+1].d_sv_data += _delta(&write_done, &read_done); | |||
331 | timer_data[2*(*id)+1].d_close += _delta(&read_done, &close_done); | |||
332 | timer_data[2*(*id)+1].d_total += _delta(&start, &close_done); | |||
333 | timer_data[2*(*id)+1].requests++; | |||
334 | } | |||
335 | done: | |||
336 | if (data_buffer != NULL((void*)0)) { | |||
337 | PR_Free (data_buffer); | |||
338 | } | |||
339 | _thread_exit(*id); | |||
340 | ||||
341 | return; | |||
342 | } | |||
343 | ||||
344 | static | |||
345 | void do_work(void) | |||
346 | { | |||
347 | int index; | |||
348 | ||||
349 | _thread_exit_count = _threads * 2; | |||
350 | for (index=0; index<_threads; index++) { | |||
351 | int *id = (int *)PR_Malloc(sizeof(int)); | |||
352 | ||||
353 | *id = index; | |||
354 | ||||
355 | if ( PR_CreateThread(PR_USER_THREAD, | |||
356 | _server_thread, | |||
357 | id, | |||
358 | PR_PRIORITY_NORMAL, | |||
359 | scope1, | |||
360 | PR_UNJOINABLE_THREAD, | |||
361 | 0) == NULL((void*)0)) { | |||
362 | fprintf(stderrstderr, "Error creating server thread %d\n", index); | |||
363 | } | |||
364 | } | |||
365 | ||||
366 | PR_EnterMonitor(exit_cv); | |||
367 | while (_thread_exit_count > 0) { | |||
368 | PR_Wait(exit_cv, PR_INTERVAL_NO_TIMEOUT0xffffffffUL); | |||
369 | } | |||
370 | PR_ExitMonitor(exit_cv); | |||
371 | ||||
372 | fprintf(stdoutstdout, "TEST COMPLETE!\n"); | |||
373 | ||||
374 | tally_results(verbose); | |||
375 | ||||
376 | } | |||
377 | ||||
378 | static void do_workUU(void) | |||
379 | { | |||
380 | scope1 = PR_LOCAL_THREAD; | |||
381 | scope2 = PR_LOCAL_THREAD; | |||
382 | do_work(); | |||
383 | } | |||
384 | ||||
385 | static void do_workUK(void) | |||
386 | { | |||
387 | scope1 = PR_LOCAL_THREAD; | |||
388 | scope2 = PR_GLOBAL_THREAD; | |||
389 | do_work(); | |||
390 | } | |||
391 | ||||
392 | static void do_workKU(void) | |||
393 | { | |||
394 | scope1 = PR_GLOBAL_THREAD; | |||
395 | scope2 = PR_LOCAL_THREAD; | |||
396 | do_work(); | |||
397 | } | |||
398 | ||||
399 | static void do_workKK(void) | |||
400 | { | |||
401 | scope1 = PR_GLOBAL_THREAD; | |||
402 | scope2 = PR_GLOBAL_THREAD; | |||
403 | do_work(); | |||
404 | } | |||
405 | ||||
406 | ||||
407 | ||||
408 | static void Measure(void (*func)(void), const char *msg) | |||
409 | { | |||
410 | PRIntervalTime start, stop; | |||
411 | double d; | |||
412 | ||||
413 | start = PR_IntervalNow(); | |||
414 | (*func)(); | |||
415 | stop = PR_IntervalNow(); | |||
416 | ||||
417 | d = (double)PR_IntervalToMicroseconds(stop - start); | |||
418 | ||||
419 | printf("%40s: %6.2f usec\n", msg, d / _iterations); | |||
420 | } | |||
421 | ||||
422 | ||||
423 | int main(int argc, char **argv) | |||
424 | { | |||
425 | #if defined(XP_UNIX1) || defined(XP_OS2) | |||
426 | int opt; | |||
427 | PR_IMPORT_DATA(char *)extern __attribute__((visibility("default"))) char * optarg; | |||
428 | #endif | |||
429 | ||||
430 | #if defined(XP_UNIX1) || defined(XP_OS2) | |||
431 | while ( (opt = getopt(argc, argv, "c:s:i:t:v")) != EOF(-1)) { | |||
| ||||
432 | switch(opt) { | |||
433 | case 'i': | |||
434 | _iterations = atoi(optarg); | |||
435 | break; | |||
436 | case 't': | |||
437 | _threads_max = _threads = atoi(optarg); | |||
438 | break; | |||
439 | case 'c': | |||
440 | _client_data = atoi(optarg); | |||
441 | break; | |||
442 | case 's': | |||
443 | _server_data = atoi(optarg); | |||
444 | break; | |||
445 | case 'v': | |||
446 | verbose = 1; | |||
447 | break; | |||
448 | default: | |||
449 | break; | |||
450 | } | |||
451 | } | |||
452 | #endif | |||
453 | ||||
454 | PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); | |||
455 | PR_STDIO_INIT(); | |||
456 | ||||
457 | fprintf(stdoutstdout, "Running test for %d iterations with %d simultaneous threads.\n", | |||
458 | _iterations, _threads); | |||
459 | fprintf(stdoutstdout, "\tWill send %d bytes of client data and %d bytes of server data\n", | |||
460 | _client_data, _server_data); | |||
461 | ||||
462 | if ( (exit_cv = PR_NewMonitor()) == NULL((void*)0)) { | |||
463 | fprintf(stderrstderr, "Error creating monitor for exit cv\n"); | |||
464 | } | |||
465 | if ( (timer_data = (timer_slot_t *)PR_Malloc(2*_threads * sizeof(timer_slot_t))) == NULL((void*)0)) { | |||
466 | fprintf(stderrstderr, "error allocating thread time results array\n"); | |||
467 | } | |||
468 | memset(timer_data, 0, 2*_threads*sizeof(timer_slot_t)); | |||
| ||||
469 | ||||
470 | Measure(do_workUU, "select loop user/user"); | |||
471 | Measure(do_workUK, "select loop user/kernel"); | |||
472 | Measure(do_workKU, "select loop kernel/user"); | |||
473 | Measure(do_workKK, "select loop kernel/kernel"); | |||
474 | ||||
475 | ||||
476 | return 0; | |||
477 | } | |||
478 | ||||
479 | void | |||
480 | tally_results(int verbose) | |||
481 | { | |||
482 | int index; | |||
483 | unsigned long tot_connect = 0; | |||
484 | unsigned long tot_cl_data = 0; | |||
485 | unsigned long tot_sv_data = 0; | |||
486 | unsigned long tot_close = 0; | |||
487 | unsigned long tot_all = 0; | |||
488 | unsigned long tot_requests = 0; | |||
489 | ||||
490 | fprintf(stdoutstdout, "Server results:\n\n"); | |||
491 | for (index=0; index<_threads_max*2; index+=2) { | |||
492 | ||||
493 | if (verbose) | |||
494 | fprintf(stdoutstdout, "server thread %u\t%u\t%u\t%u\t%u\t%u\t%u\n", | |||
495 | index, timer_data[index].requests, timer_data[index].d_connect, | |||
496 | timer_data[index].d_cl_data, timer_data[index].d_sv_data, | |||
497 | timer_data[index].d_close, timer_data[index].d_total); | |||
498 | ||||
499 | tot_connect += timer_data[index].d_connect / _threads; | |||
500 | tot_cl_data += timer_data[index].d_cl_data / _threads; | |||
501 | tot_sv_data += timer_data[index].d_sv_data / _threads; | |||
502 | tot_close += timer_data[index].d_close / _threads; | |||
503 | tot_all += timer_data[index].d_total / _threads; | |||
504 | tot_requests += timer_data[index].requests / _threads; | |||
505 | } | |||
506 | fprintf(stdoutstdout, "----------\n"); | |||
507 | fprintf(stdoutstdout, "server per thread totals %u\t%u\t%u\t%u\t%u\n", | |||
508 | tot_requests, tot_connect, tot_cl_data, tot_sv_data, tot_close); | |||
509 | fprintf(stdoutstdout, "server per thread elapsed time %u\n", tot_all); | |||
510 | fprintf(stdoutstdout, "----------\n"); | |||
511 | ||||
512 | tot_connect = tot_cl_data = tot_sv_data = tot_close = tot_all = tot_requests = 0; | |||
513 | fprintf(stdoutstdout, "Client results:\n\n"); | |||
514 | for (index=1; index<_threads_max*2; index+=2) { | |||
515 | ||||
516 | if (verbose) | |||
517 | fprintf(stdoutstdout, "client thread %u\t%u\t%u\t%u\t%u\t%u\t%u\n", | |||
518 | index, timer_data[index].requests, timer_data[index].d_connect, | |||
519 | timer_data[index].d_cl_data, timer_data[index].d_sv_data, | |||
520 | timer_data[index].d_close, timer_data[index].d_total); | |||
521 | ||||
522 | tot_connect += timer_data[index].d_connect / _threads; | |||
523 | tot_cl_data += timer_data[index].d_cl_data / _threads; | |||
524 | tot_sv_data += timer_data[index].d_sv_data / _threads; | |||
525 | tot_close += timer_data[index].d_close / _threads; | |||
526 | tot_all += timer_data[index].d_total / _threads; | |||
527 | tot_requests += timer_data[index].requests / _threads; | |||
528 | } | |||
529 | fprintf(stdoutstdout, "----------\n"); | |||
530 | fprintf(stdoutstdout, "client per thread totals %u\t%u\t%u\t%u\t%u\n", | |||
531 | tot_requests, tot_connect, tot_cl_data, tot_sv_data, tot_close); | |||
532 | fprintf(stdoutstdout, "client per thread elapsed time %u\n", tot_all); | |||
533 | } | |||
534 |