VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/servr_kk.c@ 99775

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

import

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

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