nsprpub/pr/tests/thrpool_server.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /***********************************************************************
michael@0 7 **
michael@0 8 ** Name: thrpool.c
michael@0 9 **
michael@0 10 ** Description: Test threadpool functionality.
michael@0 11 **
michael@0 12 ** Modification History:
michael@0 13 */
michael@0 14 #include "primpl.h"
michael@0 15
michael@0 16 #include "plgetopt.h"
michael@0 17
michael@0 18 #include <stdio.h>
michael@0 19 #include <string.h>
michael@0 20 #include <errno.h>
michael@0 21 #ifdef XP_UNIX
michael@0 22 #include <sys/mman.h>
michael@0 23 #endif
michael@0 24 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
michael@0 25 #include <pthread.h>
michael@0 26 #endif
michael@0 27
michael@0 28 /* for getcwd */
michael@0 29 #if defined(XP_UNIX) || defined (XP_OS2) || defined(XP_BEOS)
michael@0 30 #include <unistd.h>
michael@0 31 #elif defined(XP_PC)
michael@0 32 #include <direct.h>
michael@0 33 #endif
michael@0 34
michael@0 35 #ifdef WIN32
michael@0 36 #include <process.h>
michael@0 37 #endif
michael@0 38
michael@0 39 static int _debug_on = 0;
michael@0 40 static char *program_name = NULL;
michael@0 41 static void serve_client_write(void *arg);
michael@0 42
michael@0 43 #include "obsolete/prsem.h"
michael@0 44
michael@0 45 #ifdef XP_PC
michael@0 46 #define mode_t int
michael@0 47 #endif
michael@0 48
michael@0 49 #define DPRINTF(arg) if (_debug_on) printf arg
michael@0 50
michael@0 51
michael@0 52 #define BUF_DATA_SIZE (2 * 1024)
michael@0 53 #define TCP_MESG_SIZE 1024
michael@0 54 #define NUM_TCP_CLIENTS 10 /* for a listen queue depth of 5 */
michael@0 55
michael@0 56
michael@0 57 #define NUM_TCP_CONNECTIONS_PER_CLIENT 10
michael@0 58 #define NUM_TCP_MESGS_PER_CONNECTION 10
michael@0 59 #define TCP_SERVER_PORT 10000
michael@0 60 #define SERVER_MAX_BIND_COUNT 100
michael@0 61
michael@0 62 #ifdef WINCE
michael@0 63 char *getcwd(char *buf, size_t size)
michael@0 64 {
michael@0 65 wchar_t wpath[MAX_PATH];
michael@0 66 _wgetcwd(wpath, MAX_PATH);
michael@0 67 WideCharToMultiByte(CP_ACP, 0, wpath, -1, buf, size, 0, 0);
michael@0 68 }
michael@0 69
michael@0 70 #define perror(s)
michael@0 71 #endif
michael@0 72
michael@0 73 static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS;
michael@0 74 static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT;
michael@0 75 static PRInt32 tcp_mesg_size = TCP_MESG_SIZE;
michael@0 76 static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION;
michael@0 77 static void TCP_Server_Accept(void *arg);
michael@0 78
michael@0 79
michael@0 80 int failed_already=0;
michael@0 81 typedef struct buffer {
michael@0 82 char data[BUF_DATA_SIZE];
michael@0 83 } buffer;
michael@0 84
michael@0 85
michael@0 86 typedef struct Server_Param {
michael@0 87 PRJobIoDesc iod; /* socket to read from/write to */
michael@0 88 PRInt32 datalen; /* bytes of data transfered in each read/write */
michael@0 89 PRNetAddr netaddr;
michael@0 90 PRMonitor *exit_mon; /* monitor to signal on exit */
michael@0 91 PRInt32 *job_counterp; /* counter to decrement, before exit */
michael@0 92 PRInt32 conn_counter; /* counter to decrement, before exit */
michael@0 93 PRThreadPool *tp;
michael@0 94 } Server_Param;
michael@0 95
michael@0 96 typedef struct Serve_Client_Param {
michael@0 97 PRJobIoDesc iod; /* socket to read from/write to */
michael@0 98 PRInt32 datalen; /* bytes of data transfered in each read/write */
michael@0 99 PRMonitor *exit_mon; /* monitor to signal on exit */
michael@0 100 PRInt32 *job_counterp; /* counter to decrement, before exit */
michael@0 101 PRThreadPool *tp;
michael@0 102 } Serve_Client_Param;
michael@0 103
michael@0 104 typedef struct Session {
michael@0 105 PRJobIoDesc iod; /* socket to read from/write to */
michael@0 106 buffer *in_buf;
michael@0 107 PRInt32 bytes;
michael@0 108 PRInt32 msg_num;
michael@0 109 PRInt32 bytes_read;
michael@0 110 PRMonitor *exit_mon; /* monitor to signal on exit */
michael@0 111 PRInt32 *job_counterp; /* counter to decrement, before exit */
michael@0 112 PRThreadPool *tp;
michael@0 113 } Session;
michael@0 114
michael@0 115 static void
michael@0 116 serve_client_read(void *arg)
michael@0 117 {
michael@0 118 Session *sp = (Session *) arg;
michael@0 119 int rem;
michael@0 120 int bytes;
michael@0 121 int offset;
michael@0 122 PRFileDesc *sockfd;
michael@0 123 char *buf;
michael@0 124 PRJob *jobp;
michael@0 125
michael@0 126 PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;
michael@0 127
michael@0 128 sockfd = sp->iod.socket;
michael@0 129 buf = sp->in_buf->data;
michael@0 130
michael@0 131 PR_ASSERT(sp->msg_num < num_tcp_mesgs_per_connection);
michael@0 132 PR_ASSERT(sp->bytes_read < sp->bytes);
michael@0 133
michael@0 134 offset = sp->bytes_read;
michael@0 135 rem = sp->bytes - offset;
michael@0 136 bytes = PR_Recv(sockfd, buf + offset, rem, 0, timeout);
michael@0 137 if (bytes < 0) {
michael@0 138 return;
michael@0 139 }
michael@0 140 sp->bytes_read += bytes;
michael@0 141 sp->iod.timeout = PR_SecondsToInterval(60);
michael@0 142 if (sp->bytes_read < sp->bytes) {
michael@0 143 jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp,
michael@0 144 PR_FALSE);
michael@0 145 PR_ASSERT(NULL != jobp);
michael@0 146 return;
michael@0 147 }
michael@0 148 PR_ASSERT(sp->bytes_read == sp->bytes);
michael@0 149 DPRINTF(("serve_client: read complete, msg(%d) \n", sp->msg_num));
michael@0 150
michael@0 151 sp->iod.timeout = PR_SecondsToInterval(60);
michael@0 152 jobp = PR_QueueJob_Write(sp->tp, &sp->iod, serve_client_write, sp,
michael@0 153 PR_FALSE);
michael@0 154 PR_ASSERT(NULL != jobp);
michael@0 155
michael@0 156 return;
michael@0 157 }
michael@0 158
michael@0 159 static void
michael@0 160 serve_client_write(void *arg)
michael@0 161 {
michael@0 162 Session *sp = (Session *) arg;
michael@0 163 int bytes;
michael@0 164 PRFileDesc *sockfd;
michael@0 165 char *buf;
michael@0 166 PRJob *jobp;
michael@0 167
michael@0 168 sockfd = sp->iod.socket;
michael@0 169 buf = sp->in_buf->data;
michael@0 170
michael@0 171 PR_ASSERT(sp->msg_num < num_tcp_mesgs_per_connection);
michael@0 172
michael@0 173 bytes = PR_Send(sockfd, buf, sp->bytes, 0, PR_INTERVAL_NO_TIMEOUT);
michael@0 174 PR_ASSERT(bytes == sp->bytes);
michael@0 175
michael@0 176 if (bytes < 0) {
michael@0 177 return;
michael@0 178 }
michael@0 179 DPRINTF(("serve_client: write complete, msg(%d) \n", sp->msg_num));
michael@0 180 sp->msg_num++;
michael@0 181 if (sp->msg_num < num_tcp_mesgs_per_connection) {
michael@0 182 sp->bytes_read = 0;
michael@0 183 sp->iod.timeout = PR_SecondsToInterval(60);
michael@0 184 jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp,
michael@0 185 PR_FALSE);
michael@0 186 PR_ASSERT(NULL != jobp);
michael@0 187 return;
michael@0 188 }
michael@0 189
michael@0 190 DPRINTF(("serve_client: read/write complete, msg(%d) \n", sp->msg_num));
michael@0 191 if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
michael@0 192 fprintf(stderr,"%s: ERROR - PR_Shutdown\n", program_name);
michael@0 193 }
michael@0 194
michael@0 195 PR_Close(sockfd);
michael@0 196 PR_EnterMonitor(sp->exit_mon);
michael@0 197 --(*sp->job_counterp);
michael@0 198 PR_Notify(sp->exit_mon);
michael@0 199 PR_ExitMonitor(sp->exit_mon);
michael@0 200
michael@0 201 PR_DELETE(sp->in_buf);
michael@0 202 PR_DELETE(sp);
michael@0 203
michael@0 204 return;
michael@0 205 }
michael@0 206
michael@0 207 /*
michael@0 208 * Serve_Client
michael@0 209 * Thread, started by the server, for serving a client connection.
michael@0 210 * Reads data from socket and writes it back, unmodified, and
michael@0 211 * closes the socket
michael@0 212 */
michael@0 213 static void PR_CALLBACK
michael@0 214 Serve_Client(void *arg)
michael@0 215 {
michael@0 216 Serve_Client_Param *scp = (Serve_Client_Param *) arg;
michael@0 217 buffer *in_buf;
michael@0 218 Session *sp;
michael@0 219 PRJob *jobp;
michael@0 220
michael@0 221 sp = PR_NEW(Session);
michael@0 222 sp->iod = scp->iod;
michael@0 223
michael@0 224 in_buf = PR_NEW(buffer);
michael@0 225 if (in_buf == NULL) {
michael@0 226 fprintf(stderr,"%s: failed to alloc buffer struct\n",program_name);
michael@0 227 failed_already=1;
michael@0 228 return;
michael@0 229 }
michael@0 230
michael@0 231 sp->in_buf = in_buf;
michael@0 232 sp->bytes = scp->datalen;
michael@0 233 sp->msg_num = 0;
michael@0 234 sp->bytes_read = 0;
michael@0 235 sp->tp = scp->tp;
michael@0 236 sp->exit_mon = scp->exit_mon;
michael@0 237 sp->job_counterp = scp->job_counterp;
michael@0 238
michael@0 239 sp->iod.timeout = PR_SecondsToInterval(60);
michael@0 240 jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp,
michael@0 241 PR_FALSE);
michael@0 242 PR_ASSERT(NULL != jobp);
michael@0 243 PR_DELETE(scp);
michael@0 244 }
michael@0 245
michael@0 246 static void
michael@0 247 print_stats(void *arg)
michael@0 248 {
michael@0 249 Server_Param *sp = (Server_Param *) arg;
michael@0 250 PRThreadPool *tp = sp->tp;
michael@0 251 PRInt32 counter;
michael@0 252 PRJob *jobp;
michael@0 253
michael@0 254 PR_EnterMonitor(sp->exit_mon);
michael@0 255 counter = (*sp->job_counterp);
michael@0 256 PR_ExitMonitor(sp->exit_mon);
michael@0 257
michael@0 258 printf("PRINT_STATS: #client connections = %d\n",counter);
michael@0 259
michael@0 260
michael@0 261 jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500),
michael@0 262 print_stats, sp, PR_FALSE);
michael@0 263
michael@0 264 PR_ASSERT(NULL != jobp);
michael@0 265 }
michael@0 266
michael@0 267 static int job_counter = 0;
michael@0 268 /*
michael@0 269 * TCP Server
michael@0 270 * Server binds an address to a socket, starts a client process and
michael@0 271 * listens for incoming connections.
michael@0 272 * Each client connects to the server and sends a chunk of data
michael@0 273 * Starts a Serve_Client job for each incoming connection, to read
michael@0 274 * the data from the client and send it back to the client, unmodified.
michael@0 275 * Each client checks that data received from server is same as the
michael@0 276 * data it sent to the server.
michael@0 277 * Finally, the threadpool is shutdown
michael@0 278 */
michael@0 279 static void PR_CALLBACK
michael@0 280 TCP_Server(void *arg)
michael@0 281 {
michael@0 282 PRThreadPool *tp = (PRThreadPool *) arg;
michael@0 283 Server_Param *sp;
michael@0 284 PRFileDesc *sockfd;
michael@0 285 PRNetAddr netaddr;
michael@0 286 PRMonitor *sc_mon;
michael@0 287 PRJob *jobp;
michael@0 288 int i;
michael@0 289 PRStatus rval;
michael@0 290
michael@0 291 /*
michael@0 292 * Create a tcp socket
michael@0 293 */
michael@0 294 if ((sockfd = PR_NewTCPSocket()) == NULL) {
michael@0 295 fprintf(stderr,"%s: PR_NewTCPSocket failed\n", program_name);
michael@0 296 return;
michael@0 297 }
michael@0 298 memset(&netaddr, 0 , sizeof(netaddr));
michael@0 299 netaddr.inet.family = PR_AF_INET;
michael@0 300 netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
michael@0 301 netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
michael@0 302 /*
michael@0 303 * try a few times to bind server's address, if addresses are in
michael@0 304 * use
michael@0 305 */
michael@0 306 i = 0;
michael@0 307 while (PR_Bind(sockfd, &netaddr) < 0) {
michael@0 308 if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
michael@0 309 netaddr.inet.port += 2;
michael@0 310 if (i++ < SERVER_MAX_BIND_COUNT)
michael@0 311 continue;
michael@0 312 }
michael@0 313 fprintf(stderr,"%s: ERROR - PR_Bind failed\n", program_name);
michael@0 314 perror("PR_Bind");
michael@0 315 failed_already=1;
michael@0 316 return;
michael@0 317 }
michael@0 318
michael@0 319 if (PR_Listen(sockfd, 32) < 0) {
michael@0 320 fprintf(stderr,"%s: ERROR - PR_Listen failed\n", program_name);
michael@0 321 failed_already=1;
michael@0 322 return;
michael@0 323 }
michael@0 324
michael@0 325 if (PR_GetSockName(sockfd, &netaddr) < 0) {
michael@0 326 fprintf(stderr,"%s: ERROR - PR_GetSockName failed\n", program_name);
michael@0 327 failed_already=1;
michael@0 328 return;
michael@0 329 }
michael@0 330
michael@0 331 DPRINTF((
michael@0 332 "TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
michael@0 333 netaddr.inet.ip, netaddr.inet.port));
michael@0 334
michael@0 335 sp = PR_NEW(Server_Param);
michael@0 336 if (sp == NULL) {
michael@0 337 fprintf(stderr,"%s: PR_NEW failed\n", program_name);
michael@0 338 failed_already=1;
michael@0 339 return;
michael@0 340 }
michael@0 341 sp->iod.socket = sockfd;
michael@0 342 sp->iod.timeout = PR_SecondsToInterval(60);
michael@0 343 sp->datalen = tcp_mesg_size;
michael@0 344 sp->exit_mon = sc_mon;
michael@0 345 sp->job_counterp = &job_counter;
michael@0 346 sp->conn_counter = 0;
michael@0 347 sp->tp = tp;
michael@0 348 sp->netaddr = netaddr;
michael@0 349
michael@0 350 /* create and cancel an io job */
michael@0 351 jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp,
michael@0 352 PR_FALSE);
michael@0 353 PR_ASSERT(NULL != jobp);
michael@0 354 rval = PR_CancelJob(jobp);
michael@0 355 PR_ASSERT(PR_SUCCESS == rval);
michael@0 356
michael@0 357 /*
michael@0 358 * create the client process
michael@0 359 */
michael@0 360 {
michael@0 361 #define MAX_ARGS 4
michael@0 362 char *argv[MAX_ARGS + 1];
michael@0 363 int index = 0;
michael@0 364 char port[32];
michael@0 365 char path[1024 + sizeof("/thrpool_client")];
michael@0 366
michael@0 367 getcwd(path, sizeof(path));
michael@0 368
michael@0 369 (void)strcat(path, "/thrpool_client");
michael@0 370 #ifdef XP_PC
michael@0 371 (void)strcat(path, ".exe");
michael@0 372 #endif
michael@0 373 argv[index++] = path;
michael@0 374 sprintf(port,"%d",PR_ntohs(netaddr.inet.port));
michael@0 375 if (_debug_on)
michael@0 376 {
michael@0 377 argv[index++] = "-d";
michael@0 378 argv[index++] = "-p";
michael@0 379 argv[index++] = port;
michael@0 380 argv[index++] = NULL;
michael@0 381 } else {
michael@0 382 argv[index++] = "-p";
michael@0 383 argv[index++] = port;
michael@0 384 argv[index++] = NULL;
michael@0 385 }
michael@0 386 PR_ASSERT(MAX_ARGS >= (index - 1));
michael@0 387
michael@0 388 DPRINTF(("creating client process %s ...\n", path));
michael@0 389 if (PR_FAILURE == PR_CreateProcessDetached(path, argv, NULL, NULL)) {
michael@0 390 fprintf(stderr,
michael@0 391 "thrpool_server: ERROR - PR_CreateProcessDetached failed\n");
michael@0 392 failed_already=1;
michael@0 393 return;
michael@0 394 }
michael@0 395 }
michael@0 396
michael@0 397 sc_mon = PR_NewMonitor();
michael@0 398 if (sc_mon == NULL) {
michael@0 399 fprintf(stderr,"%s: PR_NewMonitor failed\n", program_name);
michael@0 400 failed_already=1;
michael@0 401 return;
michael@0 402 }
michael@0 403
michael@0 404 sp->iod.socket = sockfd;
michael@0 405 sp->iod.timeout = PR_SecondsToInterval(60);
michael@0 406 sp->datalen = tcp_mesg_size;
michael@0 407 sp->exit_mon = sc_mon;
michael@0 408 sp->job_counterp = &job_counter;
michael@0 409 sp->conn_counter = 0;
michael@0 410 sp->tp = tp;
michael@0 411 sp->netaddr = netaddr;
michael@0 412
michael@0 413 /* create and cancel a timer job */
michael@0 414 jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(5000),
michael@0 415 print_stats, sp, PR_FALSE);
michael@0 416 PR_ASSERT(NULL != jobp);
michael@0 417 rval = PR_CancelJob(jobp);
michael@0 418 PR_ASSERT(PR_SUCCESS == rval);
michael@0 419
michael@0 420 DPRINTF(("TCP_Server: Accepting connections \n"));
michael@0 421
michael@0 422 jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp,
michael@0 423 PR_FALSE);
michael@0 424 PR_ASSERT(NULL != jobp);
michael@0 425 return;
michael@0 426 }
michael@0 427
michael@0 428 static void
michael@0 429 TCP_Server_Accept(void *arg)
michael@0 430 {
michael@0 431 Server_Param *sp = (Server_Param *) arg;
michael@0 432 PRThreadPool *tp = sp->tp;
michael@0 433 Serve_Client_Param *scp;
michael@0 434 PRFileDesc *newsockfd;
michael@0 435 PRJob *jobp;
michael@0 436
michael@0 437 if ((newsockfd = PR_Accept(sp->iod.socket, &sp->netaddr,
michael@0 438 PR_INTERVAL_NO_TIMEOUT)) == NULL) {
michael@0 439 fprintf(stderr,"%s: ERROR - PR_Accept failed\n", program_name);
michael@0 440 failed_already=1;
michael@0 441 goto exit;
michael@0 442 }
michael@0 443 scp = PR_NEW(Serve_Client_Param);
michael@0 444 if (scp == NULL) {
michael@0 445 fprintf(stderr,"%s: PR_NEW failed\n", program_name);
michael@0 446 failed_already=1;
michael@0 447 goto exit;
michael@0 448 }
michael@0 449
michael@0 450 /*
michael@0 451 * Start a Serve_Client job for each incoming connection
michael@0 452 */
michael@0 453 scp->iod.socket = newsockfd;
michael@0 454 scp->iod.timeout = PR_SecondsToInterval(60);
michael@0 455 scp->datalen = tcp_mesg_size;
michael@0 456 scp->exit_mon = sp->exit_mon;
michael@0 457 scp->job_counterp = sp->job_counterp;
michael@0 458 scp->tp = sp->tp;
michael@0 459
michael@0 460 PR_EnterMonitor(sp->exit_mon);
michael@0 461 (*sp->job_counterp)++;
michael@0 462 PR_ExitMonitor(sp->exit_mon);
michael@0 463 jobp = PR_QueueJob(tp, Serve_Client, scp,
michael@0 464 PR_FALSE);
michael@0 465
michael@0 466 PR_ASSERT(NULL != jobp);
michael@0 467 DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", jobp));
michael@0 468
michael@0 469 /*
michael@0 470 * single-threaded update; no lock needed
michael@0 471 */
michael@0 472 sp->conn_counter++;
michael@0 473 if (sp->conn_counter <
michael@0 474 (num_tcp_clients * num_tcp_connections_per_client)) {
michael@0 475 jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp,
michael@0 476 PR_FALSE);
michael@0 477 PR_ASSERT(NULL != jobp);
michael@0 478 return;
michael@0 479 }
michael@0 480 jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500),
michael@0 481 print_stats, sp, PR_FALSE);
michael@0 482
michael@0 483 PR_ASSERT(NULL != jobp);
michael@0 484 DPRINTF(("TCP_Server: Created print_stats timer job = 0x%lx\n", jobp));
michael@0 485
michael@0 486 exit:
michael@0 487 PR_EnterMonitor(sp->exit_mon);
michael@0 488 /* Wait for server jobs to finish */
michael@0 489 while (0 != *sp->job_counterp) {
michael@0 490 PR_Wait(sp->exit_mon, PR_INTERVAL_NO_TIMEOUT);
michael@0 491 DPRINTF(("TCP_Server: conn_counter = %d\n",
michael@0 492 *sp->job_counterp));
michael@0 493 }
michael@0 494
michael@0 495 PR_ExitMonitor(sp->exit_mon);
michael@0 496 if (sp->iod.socket) {
michael@0 497 PR_Close(sp->iod.socket);
michael@0 498 }
michael@0 499 PR_DestroyMonitor(sp->exit_mon);
michael@0 500 printf("%30s","TCP_Socket_Client_Server_Test:");
michael@0 501 printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l,
michael@0 502 num_tcp_clients, num_tcp_connections_per_client);
michael@0 503 printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":",
michael@0 504 num_tcp_mesgs_per_connection, tcp_mesg_size);
michael@0 505
michael@0 506 DPRINTF(("%s: calling PR_ShutdownThreadPool\n", program_name));
michael@0 507 PR_ShutdownThreadPool(sp->tp);
michael@0 508 PR_DELETE(sp);
michael@0 509 }
michael@0 510
michael@0 511 /************************************************************************/
michael@0 512
michael@0 513 #define DEFAULT_INITIAL_THREADS 4
michael@0 514 #define DEFAULT_MAX_THREADS 100
michael@0 515 #define DEFAULT_STACKSIZE (512 * 1024)
michael@0 516
michael@0 517 int main(int argc, char **argv)
michael@0 518 {
michael@0 519 PRInt32 initial_threads = DEFAULT_INITIAL_THREADS;
michael@0 520 PRInt32 max_threads = DEFAULT_MAX_THREADS;
michael@0 521 PRInt32 stacksize = DEFAULT_STACKSIZE;
michael@0 522 PRThreadPool *tp = NULL;
michael@0 523 PRStatus rv;
michael@0 524 PRJob *jobp;
michael@0 525
michael@0 526 /*
michael@0 527 * -d debug mode
michael@0 528 */
michael@0 529 PLOptStatus os;
michael@0 530 PLOptState *opt;
michael@0 531
michael@0 532 program_name = argv[0];
michael@0 533 opt = PL_CreateOptState(argc, argv, "d");
michael@0 534 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 535 {
michael@0 536 if (PL_OPT_BAD == os) continue;
michael@0 537 switch (opt->option)
michael@0 538 {
michael@0 539 case 'd': /* debug mode */
michael@0 540 _debug_on = 1;
michael@0 541 break;
michael@0 542 default:
michael@0 543 break;
michael@0 544 }
michael@0 545 }
michael@0 546 PL_DestroyOptState(opt);
michael@0 547
michael@0 548 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
michael@0 549 PR_STDIO_INIT();
michael@0 550
michael@0 551 PR_SetConcurrency(4);
michael@0 552
michael@0 553 tp = PR_CreateThreadPool(initial_threads, max_threads, stacksize);
michael@0 554 if (NULL == tp) {
michael@0 555 printf("PR_CreateThreadPool failed\n");
michael@0 556 failed_already=1;
michael@0 557 goto done;
michael@0 558 }
michael@0 559 jobp = PR_QueueJob(tp, TCP_Server, tp, PR_TRUE);
michael@0 560 rv = PR_JoinJob(jobp);
michael@0 561 PR_ASSERT(PR_SUCCESS == rv);
michael@0 562
michael@0 563 DPRINTF(("%s: calling PR_JoinThreadPool\n", program_name));
michael@0 564 rv = PR_JoinThreadPool(tp);
michael@0 565 PR_ASSERT(PR_SUCCESS == rv);
michael@0 566 DPRINTF(("%s: returning from PR_JoinThreadPool\n", program_name));
michael@0 567
michael@0 568 done:
michael@0 569 PR_Cleanup();
michael@0 570 if (failed_already) return 1;
michael@0 571 else return 0;
michael@0 572 }

mercurial