VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/servr_ku.c@ 81786

Last change on this file since 81786 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.4 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Netscape Portable Runtime (NSPR).
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/***********************************************************************
39**
40** This server simulates a server running in loopback mode.
41**
42** The idea is that a single server is created. The server initially creates
43** a number of worker threads. Then, with the server running, a number of
44** clients are created which start requesting service from the server.
45**
46**
47** Modification History:
48** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
49** The debug mode will print all of the printfs associated with this test.
50** The regress mode will be the default mode. Since the regress tool limits
51** the output to a one line status:PASS or FAIL,all of the printf statements
52** have been handled with an if (debug_mode) statement.
53** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
54** recognize the return code from tha main program.
55***********************************************************************/
56
57/***********************************************************************
58** Includes
59***********************************************************************/
60/* Used to get the command line option */
61#include "plgetopt.h"
62
63#include "nspr.h"
64#include "pprthred.h"
65
66#include <string.h>
67
68#define PORT 15004
69#define THREAD_STACKSIZE 0
70
71static int _iterations = 1000;
72static int _clients = 1;
73static int _client_data = 250;
74static int _server_data = (8*1024);
75
76static PRThreadScope ServerScope, ClientScope;
77
78#define SERVER "Server"
79#define MAIN "Main"
80
81#define SERVER_STATE_STARTUP 0
82#define SERVER_STATE_READY 1
83#define SERVER_STATE_DYING 2
84#define SERVER_STATE_DEAD 4
85int ServerState;
86PRLock *ServerStateCVLock;
87PRCondVar *ServerStateCV;
88
89#ifdef DEBUGPRINTS
90#define DPRINTF printf
91#else
92#define DPRINTF
93#endif
94
95PRIntn failed_already=0;
96PRIntn debug_mode;
97
98static void do_work(void);
99
100/* --- Server state functions --------------------------------------------- */
101void
102SetServerState(char *waiter, PRInt32 state)
103{
104 PR_Lock(ServerStateCVLock);
105 ServerState = state;
106 PR_NotifyCondVar(ServerStateCV);
107
108 if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state);
109
110 PR_Unlock(ServerStateCVLock);
111}
112
113int
114WaitServerState(char *waiter, PRInt32 state)
115{
116 PRInt32 rv;
117
118 PR_Lock(ServerStateCVLock);
119
120 if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state);
121
122 while(!(ServerState & state))
123 PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT);
124 rv = ServerState;
125
126 if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n",
127 waiter, state, ServerState);
128 PR_Unlock(ServerStateCVLock);
129
130 return rv;
131}
132
133/* --- Server Functions ------------------------------------------- */
134
135PRLock *workerThreadsLock;
136PRInt32 workerThreads;
137PRInt32 workerThreadsBusy;
138
139void
140WorkerThreadFunc(void *_listenSock)
141{
142 PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
143 PRInt32 bytesRead;
144 PRInt32 bytesWritten;
145 char *dataBuf;
146 char *sendBuf;
147
148 if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
149 _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
150 dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
151 if (!dataBuf)
152 if (debug_mode) printf("\tServer could not malloc space!?\n");
153 sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
154 if (!sendBuf)
155 if (debug_mode) printf("\tServer could not malloc space!?\n");
156
157 if (debug_mode) DPRINTF("\tServer worker thread running\n");
158
159 while(1) {
160 PRInt32 bytesToRead = _client_data;
161 PRInt32 bytesToWrite = _server_data;
162 PRFileDesc *newSock;
163 PRNetAddr *rAddr;
164 PRInt32 loops = 0;
165
166 loops++;
167
168 if (debug_mode) DPRINTF("\tServer thread going into accept\n");
169
170 bytesRead = PR_AcceptRead(listenSock,
171 &newSock,
172 &rAddr,
173 dataBuf,
174 bytesToRead,
175 PR_INTERVAL_NO_TIMEOUT);
176
177 if (bytesRead < 0) {
178 if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
179 continue;
180 }
181
182 if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
183
184 PR_AtomicIncrement(&workerThreadsBusy);
185 if (workerThreadsBusy == workerThreads) {
186
187 PR_Lock(workerThreadsLock);
188 if (workerThreadsBusy == workerThreads) {
189 PRThread *WorkerThread;
190
191 WorkerThread = PR_CreateThread(
192 PR_SYSTEM_THREAD,
193 WorkerThreadFunc,
194 listenSock,
195 PR_PRIORITY_NORMAL,
196 ServerScope,
197 PR_UNJOINABLE_THREAD,
198 THREAD_STACKSIZE);
199
200 if (!WorkerThread)
201 if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
202 else {
203 PR_AtomicIncrement(&workerThreads);
204 if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
205 }
206 }
207 PR_Unlock(workerThreadsLock);
208 }
209
210 bytesToRead -= bytesRead;
211 while (bytesToRead) {
212 bytesRead = PR_Recv(newSock,
213 dataBuf,
214 bytesToRead,
215 0,
216 PR_INTERVAL_NO_TIMEOUT);
217 if (bytesRead < 0) {
218 if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
219 continue;
220 }
221 if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
222 }
223
224 bytesWritten = PR_Send(newSock,
225 sendBuf,
226 bytesToWrite,
227 0,
228 PR_INTERVAL_NO_TIMEOUT);
229 if (bytesWritten != _server_data)
230 if (debug_mode) printf("\tError sending data to client (%d, %d)\n",
231 bytesWritten, PR_GetOSError());
232 else
233 if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
234
235 PR_Close(newSock);
236 PR_AtomicDecrement(&workerThreadsBusy);
237 }
238}
239
240PRFileDesc *
241ServerSetup(void)
242{
243 PRFileDesc *listenSocket;
244 PRSocketOptionData sockOpt;
245 PRNetAddr serverAddr;
246 PRThread *WorkerThread;
247
248 if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
249 if (debug_mode) printf("\tServer error creating listen socket\n");
250 else failed_already=1;
251 return NULL;
252 }
253
254 sockOpt.option = PR_SockOpt_Reuseaddr;
255 sockOpt.value.reuse_addr = PR_TRUE;
256 if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) {
257 if (debug_mode) printf("\tServer error setting socket option: OS error %d\n",
258 PR_GetOSError());
259 else failed_already=1;
260 PR_Close(listenSocket);
261 return NULL;
262 }
263
264 memset(&serverAddr, 0, sizeof(PRNetAddr));
265 serverAddr.inet.family = PR_AF_INET;
266 serverAddr.inet.port = PR_htons(PORT);
267 serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
268
269 if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
270 if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
271 PR_GetOSError());
272 else failed_already=1;
273 PR_Close(listenSocket);
274 return NULL;
275 }
276
277 if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
278 if (debug_mode) printf("\tServer error listening to server socket\n");
279 else failed_already=1;
280 PR_Close(listenSocket);
281
282 return NULL;
283 }
284
285 /* Create Clients */
286 workerThreads = 0;
287 workerThreadsBusy = 0;
288
289 workerThreadsLock = PR_NewLock();
290
291 WorkerThread = PR_CreateThread(
292 PR_SYSTEM_THREAD,
293 WorkerThreadFunc,
294 listenSocket,
295 PR_PRIORITY_NORMAL,
296 ServerScope,
297 PR_UNJOINABLE_THREAD,
298 THREAD_STACKSIZE);
299
300 if (!WorkerThread) {
301 if (debug_mode) printf("error creating working thread\n");
302 PR_Close(listenSocket);
303 return NULL;
304 }
305 PR_AtomicIncrement(&workerThreads);
306 if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");
307
308 return listenSocket;
309}
310
311/* The main server loop */
312void
313ServerThreadFunc(void *unused)
314{
315 PRFileDesc *listenSocket;
316
317 /* Do setup */
318 listenSocket = ServerSetup();
319
320 if (!listenSocket) {
321 SetServerState(SERVER, SERVER_STATE_DEAD);
322 } else {
323
324 if (debug_mode) DPRINTF("\tServer up\n");
325
326 /* Tell clients they can start now. */
327 SetServerState(SERVER, SERVER_STATE_READY);
328
329 /* Now wait for server death signal */
330 WaitServerState(SERVER, SERVER_STATE_DYING);
331
332 /* Cleanup */
333 SetServerState(SERVER, SERVER_STATE_DEAD);
334 }
335}
336
337/* --- Client Functions ------------------------------------------- */
338
339PRInt32 numRequests;
340PRInt32 numClients;
341PRMonitor *clientMonitor;
342
343void
344ClientThreadFunc(void *unused)
345{
346 PRNetAddr serverAddr;
347 PRFileDesc *clientSocket;
348 char *sendBuf;
349 char *recvBuf;
350 PRInt32 rv;
351 PRInt32 bytesNeeded;
352
353 sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
354 if (!sendBuf)
355 if (debug_mode) printf("\tClient could not malloc space!?\n");
356 recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
357 if (!recvBuf)
358 if (debug_mode) printf("\tClient could not malloc space!?\n");
359
360 memset(&serverAddr, 0, sizeof(PRNetAddr));
361 serverAddr.inet.family = PR_AF_INET;
362 serverAddr.inet.port = PR_htons(PORT);
363 serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
364
365 while(numRequests > 0) {
366
367 if ( (numRequests % 10) == 0 )
368 if (debug_mode) printf(".");
369 if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);
370
371 clientSocket = PR_NewTCPSocket();
372 if (!clientSocket) {
373 if (debug_mode) printf("Client error creating socket: OS error %d\n",
374 PR_GetOSError());
375 continue;
376 }
377
378 if (debug_mode) DPRINTF("\tClient connecting\n");
379
380 rv = PR_Connect(clientSocket,
381 &serverAddr,
382 PR_INTERVAL_NO_TIMEOUT);
383 if (!clientSocket) {
384 if (debug_mode) printf("\tClient error connecting\n");
385 continue;
386 }
387
388 if (debug_mode) DPRINTF("\tClient connected\n");
389
390 rv = PR_Send(clientSocket,
391 sendBuf,
392 _client_data,
393 0,
394 PR_INTERVAL_NO_TIMEOUT);
395 if (rv != _client_data) {
396 if (debug_mode) printf("Client error sending data (%d)\n", rv);
397 PR_Close(clientSocket);
398 continue;
399 }
400
401 if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);
402
403 bytesNeeded = _server_data;
404 while(bytesNeeded) {
405 rv = PR_Recv(clientSocket,
406 recvBuf,
407 bytesNeeded,
408 0,
409 PR_INTERVAL_NO_TIMEOUT);
410 if (rv <= 0) {
411 if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n",
412 rv, (_server_data - bytesNeeded), _server_data);
413 break;
414 }
415 if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
416 bytesNeeded -= rv;
417 }
418
419 PR_Close(clientSocket);
420
421 PR_AtomicDecrement(&numRequests);
422 }
423
424 PR_EnterMonitor(clientMonitor);
425 --numClients;
426 PR_Notify(clientMonitor);
427 PR_ExitMonitor(clientMonitor);
428
429 PR_DELETE(sendBuf);
430 PR_DELETE(recvBuf);
431}
432
433void
434RunClients(void)
435{
436 PRInt32 index;
437
438 numRequests = _iterations;
439 numClients = _clients;
440 clientMonitor = PR_NewMonitor();
441
442 for (index=0; index<_clients; index++) {
443 PRThread *clientThread;
444
445
446 clientThread = PR_CreateThread(
447 PR_USER_THREAD,
448 ClientThreadFunc,
449 NULL,
450 PR_PRIORITY_NORMAL,
451 ClientScope,
452 PR_UNJOINABLE_THREAD,
453 THREAD_STACKSIZE);
454
455 if (!clientThread) {
456 if (debug_mode) printf("\terror creating client thread %d\n", index);
457 } else
458 if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients);
459
460 }
461
462 PR_EnterMonitor(clientMonitor);
463 while(numClients)
464 PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT);
465 PR_ExitMonitor(clientMonitor);
466}
467
468/* --- Main Function ---------------------------------------------- */
469
470static
471void do_work()
472{
473 PRThread *ServerThread;
474 PRInt32 state;
475
476 SetServerState(MAIN, SERVER_STATE_STARTUP);
477 ServerThread = PR_CreateThread(
478 PR_USER_THREAD,
479 ServerThreadFunc,
480 NULL,
481 PR_PRIORITY_NORMAL,
482 ServerScope,
483 PR_JOINABLE_THREAD,
484 THREAD_STACKSIZE);
485 if (!ServerThread) {
486 if (debug_mode) printf("error creating main server thread\n");
487 return;
488 }
489
490 /* Wait for server to be ready */
491 state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD);
492
493 if (!(state & SERVER_STATE_DEAD)) {
494 /* Run Test Clients */
495 RunClients();
496
497 /* Send death signal to server */
498 SetServerState(MAIN, SERVER_STATE_DYING);
499 }
500
501 PR_JoinThread(ServerThread);
502}
503
504
505static void do_workKU(void)
506{
507 ServerScope = PR_GLOBAL_THREAD;
508 ClientScope = PR_LOCAL_THREAD;
509 do_work();
510}
511
512
513
514static void Measure(void (*func)(void), const char *msg)
515{
516 PRIntervalTime start, stop;
517 double d;
518
519 start = PR_IntervalNow();
520 (*func)();
521 stop = PR_IntervalNow();
522
523 d = (double)PR_IntervalToMicroseconds(stop - start);
524
525 if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations);
526}
527
528
529main(int argc, char **argv)
530{
531 /* The command line argument: -d is used to determine if the test is being run
532 in debug mode. The regress tool requires only one line output:PASS or FAIL.
533 All of the printfs associated with this test has been handled with a if (debug_mode)
534 test.
535 Usage: test_name -d
536 */
537 PLOptStatus os;
538 PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
539 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
540 {
541 if (PL_OPT_BAD == os) continue;
542 switch (opt->option)
543 {
544 case 'd': /* debug mode */
545 debug_mode = 1;
546 break;
547 default:
548 break;
549 }
550 }
551 PL_DestroyOptState(opt);
552
553 /* main test */
554 if (debug_mode) {
555 printf("Enter number of iterations: \n");
556 scanf("%d", &_iterations);
557 printf("Enter number of clients : \n");
558 scanf("%d", &_clients);
559 printf("Enter size of client data : \n");
560 scanf("%d", &_client_data);
561 printf("Enter size of server data : \n");
562 scanf("%d", &_server_data);
563 }
564 else {
565 _iterations = 7;
566 _clients = 7;
567 _client_data = 100;
568 _server_data = 100;
569 }
570
571 if (debug_mode) {
572 printf("\n\n%d iterations with %d client threads.\n",
573 _iterations, _clients);
574 printf("Sending %d bytes of client data and %d bytes of server data\n",
575 _client_data, _server_data);
576 }
577 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
578 PR_STDIO_INIT();
579
580 PR_SetThreadRecycleMode(64);
581
582 ServerStateCVLock = PR_NewLock();
583 ServerStateCV = PR_NewCondVar(ServerStateCVLock);
584
585 Measure(do_workKU, "server loop kernel/user");
586
587 PR_Cleanup();
588 if(failed_already)
589 return 1;
590 else
591 return 0;
592
593}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette