VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/servr_uk.c@ 89890

最後變更 在這個檔案從89890是 1,由 vboxsync 提交於 55 年 前

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 17.4 KB
 
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
98
99
100static void do_work(void);
101
102/* --- Server state functions --------------------------------------------- */
103void
104SetServerState(char *waiter, PRInt32 state)
105{
106 PR_Lock(ServerStateCVLock);
107 ServerState = state;
108 PR_NotifyCondVar(ServerStateCV);
109
110 if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state);
111
112 PR_Unlock(ServerStateCVLock);
113}
114
115int
116WaitServerState(char *waiter, PRInt32 state)
117{
118 PRInt32 rv;
119
120 PR_Lock(ServerStateCVLock);
121
122 if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state);
123
124 while(!(ServerState & state))
125 PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT);
126 rv = ServerState;
127
128 if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n",
129 waiter, state, ServerState);
130 PR_Unlock(ServerStateCVLock);
131
132 return rv;
133}
134
135/* --- Server Functions ------------------------------------------- */
136
137PRLock *workerThreadsLock;
138PRInt32 workerThreads;
139PRInt32 workerThreadsBusy;
140
141void
142WorkerThreadFunc(void *_listenSock)
143{
144 PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
145 PRInt32 bytesRead;
146 PRInt32 bytesWritten;
147 char *dataBuf;
148 char *sendBuf;
149
150 if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
151 _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
152 dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
153 if (!dataBuf)
154 if (debug_mode) printf("\tServer could not malloc space!?\n");
155 sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
156 if (!sendBuf)
157 if (debug_mode) printf("\tServer could not malloc space!?\n");
158
159 if (debug_mode) DPRINTF("\tServer worker thread running\n");
160
161 while(1) {
162 PRInt32 bytesToRead = _client_data;
163 PRInt32 bytesToWrite = _server_data;
164 PRFileDesc *newSock;
165 PRNetAddr *rAddr;
166 PRInt32 loops = 0;
167
168 loops++;
169
170 if (debug_mode) DPRINTF("\tServer thread going into accept\n");
171
172 bytesRead = PR_AcceptRead(listenSock,
173 &newSock,
174 &rAddr,
175 dataBuf,
176 bytesToRead,
177 PR_INTERVAL_NO_TIMEOUT);
178
179 if (bytesRead < 0) {
180 if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
181 continue;
182 }
183
184 if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
185
186 PR_AtomicIncrement(&workerThreadsBusy);
187 if (workerThreadsBusy == workerThreads) {
188
189 PR_Lock(workerThreadsLock);
190 if (workerThreadsBusy == workerThreads) {
191 PRThread *WorkerThread;
192
193 WorkerThread = PR_CreateThread(
194 PR_SYSTEM_THREAD,
195 WorkerThreadFunc,
196 listenSock,
197 PR_PRIORITY_NORMAL,
198 ServerScope,
199 PR_UNJOINABLE_THREAD,
200 THREAD_STACKSIZE);
201
202 if (!WorkerThread)
203 if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
204 else {
205 PR_AtomicIncrement(&workerThreads);
206 if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
207 }
208 }
209 PR_Unlock(workerThreadsLock);
210 }
211
212 bytesToRead -= bytesRead;
213 while (bytesToRead) {
214 bytesRead = PR_Recv(newSock,
215 dataBuf,
216 bytesToRead,
217 0,
218 PR_INTERVAL_NO_TIMEOUT);
219 if (bytesRead < 0) {
220 if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
221 continue;
222 }
223 if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
224 }
225
226 bytesWritten = PR_Send(newSock,
227 sendBuf,
228 bytesToWrite,
229 0,
230 PR_INTERVAL_NO_TIMEOUT);
231 if (bytesWritten != _server_data)
232 if (debug_mode) printf("\tError sending data to client (%d, %d)\n",
233 bytesWritten, PR_GetOSError());
234 else
235 if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
236
237 PR_Close(newSock);
238 PR_AtomicDecrement(&workerThreadsBusy);
239 }
240}
241
242PRFileDesc *
243ServerSetup(void)
244{
245 PRFileDesc *listenSocket;
246 PRSocketOptionData sockOpt;
247 PRNetAddr serverAddr;
248 PRThread *WorkerThread;
249
250 if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
251 if (debug_mode) printf("\tServer error creating listen socket\n");
252 else
253 return NULL;
254 }
255
256 sockOpt.option = PR_SockOpt_Reuseaddr;
257 sockOpt.value.reuse_addr = PR_TRUE;
258 if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) {
259 if (debug_mode) printf("\tServer error setting socket option: OS error %d\n",
260 PR_GetOSError());
261 else failed_already=1;
262 PR_Close(listenSocket);
263 return NULL;
264 }
265
266 memset(&serverAddr, 0, sizeof(PRNetAddr));
267 serverAddr.inet.family = PR_AF_INET;
268 serverAddr.inet.port = PR_htons(PORT);
269 serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
270
271 if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
272 if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
273 PR_GetOSError());
274 else failed_already=1;
275 PR_Close(listenSocket);
276 return NULL;
277 }
278
279 if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
280 if (debug_mode) printf("\tServer error listening to server socket\n");
281 else failed_already=1;
282 PR_Close(listenSocket);
283
284 return NULL;
285 }
286
287 /* Create Clients */
288 workerThreads = 0;
289 workerThreadsBusy = 0;
290
291 workerThreadsLock = PR_NewLock();
292
293 WorkerThread = PR_CreateThread(
294 PR_SYSTEM_THREAD,
295 WorkerThreadFunc,
296 listenSocket,
297 PR_PRIORITY_NORMAL,
298 ServerScope,
299 PR_UNJOINABLE_THREAD,
300 THREAD_STACKSIZE);
301
302 if (!WorkerThread) {
303 if (debug_mode) printf("error creating working thread\n");
304 PR_Close(listenSocket);
305 return NULL;
306 }
307 PR_AtomicIncrement(&workerThreads);
308 if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");
309
310 return listenSocket;
311}
312
313/* The main server loop */
314void
315ServerThreadFunc(void *unused)
316{
317 PRFileDesc *listenSocket;
318
319 /* Do setup */
320 listenSocket = ServerSetup();
321
322 if (!listenSocket) {
323 SetServerState(SERVER, SERVER_STATE_DEAD);
324 } else {
325
326 if (debug_mode) DPRINTF("\tServer up\n");
327
328 /* Tell clients they can start now. */
329 SetServerState(SERVER, SERVER_STATE_READY);
330
331 /* Now wait for server death signal */
332 WaitServerState(SERVER, SERVER_STATE_DYING);
333
334 /* Cleanup */
335 SetServerState(SERVER, SERVER_STATE_DEAD);
336 }
337}
338
339/* --- Client Functions ------------------------------------------- */
340
341PRInt32 numRequests;
342PRInt32 numClients;
343PRMonitor *clientMonitor;
344
345void
346ClientThreadFunc(void *unused)
347{
348 PRNetAddr serverAddr;
349 PRFileDesc *clientSocket;
350 char *sendBuf;
351 char *recvBuf;
352 PRInt32 rv;
353 PRInt32 bytesNeeded;
354
355 sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
356 if (!sendBuf)
357 if (debug_mode) printf("\tClient could not malloc space!?\n");
358 recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
359 if (!recvBuf)
360 if (debug_mode) printf("\tClient could not malloc space!?\n");
361
362 memset(&serverAddr, 0, sizeof(PRNetAddr));
363 serverAddr.inet.family = PR_AF_INET;
364 serverAddr.inet.port = PR_htons(PORT);
365 serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
366
367 while(numRequests > 0) {
368
369 if ( (numRequests % 10) == 0 )
370 if (debug_mode) printf(".");
371 if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);
372
373 clientSocket = PR_NewTCPSocket();
374 if (!clientSocket) {
375 if (debug_mode) printf("Client error creating socket: OS error %d\n",
376 PR_GetOSError());
377 continue;
378 }
379
380 if (debug_mode) DPRINTF("\tClient connecting\n");
381
382 rv = PR_Connect(clientSocket,
383 &serverAddr,
384 PR_INTERVAL_NO_TIMEOUT);
385 if (!clientSocket) {
386 if (debug_mode) printf("\tClient error connecting\n");
387 continue;
388 }
389
390 if (debug_mode) DPRINTF("\tClient connected\n");
391
392 rv = PR_Send(clientSocket,
393 sendBuf,
394 _client_data,
395 0,
396 PR_INTERVAL_NO_TIMEOUT);
397 if (rv != _client_data) {
398 if (debug_mode) printf("Client error sending data (%d)\n", rv);
399 PR_Close(clientSocket);
400 continue;
401 }
402
403 if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);
404
405 bytesNeeded = _server_data;
406 while(bytesNeeded) {
407 rv = PR_Recv(clientSocket,
408 recvBuf,
409 bytesNeeded,
410 0,
411 PR_INTERVAL_NO_TIMEOUT);
412 if (rv <= 0) {
413 if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n",
414 rv, (_server_data - bytesNeeded), _server_data);
415 break;
416 }
417 if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
418 bytesNeeded -= rv;
419 }
420
421 PR_Close(clientSocket);
422
423 PR_AtomicDecrement(&numRequests);
424 }
425
426 PR_EnterMonitor(clientMonitor);
427 --numClients;
428 PR_Notify(clientMonitor);
429 PR_ExitMonitor(clientMonitor);
430
431 PR_DELETE(sendBuf);
432 PR_DELETE(recvBuf);
433}
434
435void
436RunClients(void)
437{
438 PRInt32 index;
439
440 numRequests = _iterations;
441 numClients = _clients;
442 clientMonitor = PR_NewMonitor();
443
444 for (index=0; index<_clients; index++) {
445 PRThread *clientThread;
446
447
448 clientThread = PR_CreateThread(
449 PR_USER_THREAD,
450 ClientThreadFunc,
451 NULL,
452 PR_PRIORITY_NORMAL,
453 ClientScope,
454 PR_UNJOINABLE_THREAD,
455 THREAD_STACKSIZE);
456
457 if (!clientThread) {
458 if (debug_mode) printf("\terror creating client thread %d\n", index);
459 } else
460 if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients);
461
462 }
463
464 PR_EnterMonitor(clientMonitor);
465 while(numClients)
466 PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT);
467 PR_ExitMonitor(clientMonitor);
468}
469
470/* --- Main Function ---------------------------------------------- */
471
472static
473void do_work()
474{
475 PRThread *ServerThread;
476 PRInt32 state;
477
478 SetServerState(MAIN, SERVER_STATE_STARTUP);
479 ServerThread = PR_CreateThread(
480 PR_USER_THREAD,
481 ServerThreadFunc,
482 NULL,
483 PR_PRIORITY_NORMAL,
484 ServerScope,
485 PR_JOINABLE_THREAD,
486 THREAD_STACKSIZE);
487 if (!ServerThread) {
488 if (debug_mode) printf("error creating main server thread\n");
489 return;
490 }
491
492 /* Wait for server to be ready */
493 state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD);
494
495 if (!(state & SERVER_STATE_DEAD)) {
496 /* Run Test Clients */
497 RunClients();
498
499 /* Send death signal to server */
500 SetServerState(MAIN, SERVER_STATE_DYING);
501 }
502
503 PR_JoinThread(ServerThread);
504}
505
506
507static void do_workUK(void)
508{
509 ServerScope = PR_LOCAL_THREAD;
510 ClientScope = PR_GLOBAL_THREAD;
511 do_work();
512}
513
514
515
516static void Measure(void (*func)(void), const char *msg)
517{
518 PRIntervalTime start, stop;
519 double d;
520
521 start = PR_IntervalNow();
522 (*func)();
523 stop = PR_IntervalNow();
524
525 d = (double)PR_IntervalToMicroseconds(stop - start);
526
527 if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations);
528}
529
530
531main(int argc, char **argv)
532{
533 /* The command line argument: -d is used to determine if the test is being run
534 in debug mode. The regress tool requires only one line output:PASS or FAIL.
535 All of the printfs associated with this test has been handled with a if (debug_mode)
536 test.
537 Usage: test_name -d
538 */
539 PLOptStatus os;
540 PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
541 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
542 {
543 if (PL_OPT_BAD == os) continue;
544 switch (opt->option)
545 {
546 case 'd': /* debug mode */
547 debug_mode = 1;
548 break;
549 default:
550 break;
551 }
552 }
553 PL_DestroyOptState(opt);
554
555 /* main test */
556 if (debug_mode) {
557 printf("Enter number of iterations: \n");
558 scanf("%d", &_iterations);
559 printf("Enter number of clients : \n");
560 scanf("%d", &_clients);
561 printf("Enter size of client data : \n");
562 scanf("%d", &_client_data);
563 printf("Enter size of server data : \n");
564 scanf("%d", &_server_data);
565 }
566 else {
567 _iterations = 7;
568 _clients = 7;
569 _client_data = 100;
570 _server_data = 100;
571 }
572
573 if (debug_mode) {
574 printf("\n\n%d iterations with %d client threads.\n",
575 _iterations, _clients);
576 printf("Sending %d bytes of client data and %d bytes of server data\n",
577 _client_data, _server_data);
578 }
579 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
580 PR_STDIO_INIT();
581
582 PR_SetThreadRecycleMode(64);
583
584 ServerStateCVLock = PR_NewLock();
585 ServerStateCV = PR_NewCondVar(ServerStateCVLock);
586
587 Measure(do_workUK, "server loop user/kernel");
588
589 PR_Cleanup();
590
591 if(failed_already)
592 return 1;
593 else
594 return 0;
595}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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