VirtualBox

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

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

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 14.6 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** Contact: AOF<[email protected]>
41**
42** Name: ranfile.c
43**
44** Description: Test to hammer on various components of NSPR
45** Modification History:
46** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
47** The debug mode will print all of the printfs associated with this test.
48** The regress mode will be the default mode. Since the regress tool limits
49** the output to a one line status:PASS or FAIL,all of the printf statements
50** have been handled with an if (debug_mode) statement.
51** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
52** recognize the return code from tha main program.
53***********************************************************************/
54
55
56/***********************************************************************
57** Includes
58***********************************************************************/
59/* Used to get the command line option */
60#include "plgetopt.h"
61
62#include "prinit.h"
63#include "prthread.h"
64#include "prlock.h"
65#include "prcvar.h"
66#include "prmem.h"
67#include "prinrval.h"
68#include "prio.h"
69
70#include <string.h>
71#include <stdio.h>
72
73static PRIntn debug_mode = 0;
74static PRIntn failed_already=0;
75static PRThreadScope thread_scope = PR_LOCAL_THREAD;
76
77typedef enum {sg_go, sg_stop, sg_done} Action;
78typedef enum {sg_okay, sg_open, sg_close, sg_delete, sg_write, sg_seek} Problem;
79
80typedef struct Hammer_s {
81 PRLock *ml;
82 PRCondVar *cv;
83 PRUint32 id;
84 PRUint32 limit;
85 PRUint32 writes;
86 PRThread *thread;
87 PRIntervalTime timein;
88 Action action;
89 Problem problem;
90} Hammer_t;
91
92#define DEFAULT_LIMIT 10
93#define DEFAULT_THREADS 2
94#define DEFAULT_LOOPS 1
95
96static PRInt32 pageSize = 1024;
97static const char* baseName = "./";
98static const char *programName = "Random File";
99
100#ifdef XP_MAC
101#include "prlog.h"
102#define printf PR_LogPrint
103extern void SetupMacPrintfLog(char *logFile);
104#endif
105
106/***********************************************************************
107** PRIVATE FUNCTION: Random
108** DESCRIPTION:
109** Generate a pseudo-random number
110** INPUTS: None
111** OUTPUTS: None
112** RETURN: A pseudo-random unsigned number, 32-bits wide
113** SIDE EFFECTS:
114** Updates random seed (a static)
115** RESTRICTIONS:
116** None
117** MEMORY: NA
118** ALGORITHM:
119** Uses the current interval timer value, promoted to a 64 bit
120** float as a multiplier for a static residue (which begins
121** as an uninitialized variable). The result is bits [16..48)
122** of the product. Seed is then updated with the return value
123** promoted to a float-64.
124***********************************************************************/
125static PRUint32 Random(void)
126{
127 PRUint32 rv;
128 PRUint64 shift;
129 static PRFloat64 seed = 0x58a9382; /* Just make sure it isn't 0! */
130 PRFloat64 random = seed * (PRFloat64)PR_IntervalNow();
131 LL_USHR(shift, *((PRUint64*)&random), 16);
132 LL_L2UI(rv, shift);
133 seed = (PRFloat64)rv;
134 return rv;
135} /* Random */
136
137/***********************************************************************
138** PRIVATE FUNCTION: Thread
139** DESCRIPTION:
140** Hammer on the file I/O system
141** INPUTS: A pointer to the thread's private data
142** OUTPUTS: None
143** RETURN: None
144** SIDE EFFECTS:
145** Creates, accesses and deletes a file
146** RESTRICTIONS:
147** (Currently) must have file create permission in "/usr/tmp".
148** MEMORY: NA
149** ALGORITHM:
150** This function is a root of a thread
151** 1) Creates a (hopefully) unique file in /usr/tmp/
152** 2) Writes a zero to a random number of sequential pages
153** 3) Closes the file
154** 4) Reopens the file
155** 5) Seeks to a random page within the file
156** 6) Writes a one byte on that page
157** 7) Repeat steps [5..6] for each page in the file
158** 8) Close and delete the file
159** 9) Repeat steps [1..8] until told to stop
160** 10) Notify complete and return
161***********************************************************************/
162static void PR_CALLBACK Thread(void *arg)
163{
164 PRUint32 index;
165 char filename[30];
166 const char zero = 0;
167 PRFileDesc *file = NULL;
168 PRStatus rv = PR_SUCCESS;
169 Hammer_t *cd = (Hammer_t*)arg;
170
171 (void)sprintf(filename, "%ssg%04ld.dat", baseName, cd->id);
172
173 if (debug_mode) printf("Starting work on %s\n", filename);
174
175 while (PR_TRUE)
176 {
177 PRUint32 bytes;
178 PRUint32 minor = (Random() % cd->limit) + 1;
179 PRUint32 random = (Random() % cd->limit) + 1;
180 PRUint32 pages = (Random() % cd->limit) + 10;
181 while (minor-- > 0)
182 {
183 cd->problem = sg_okay;
184 if (cd->action != sg_go) goto finished;
185 cd->problem = sg_open;
186 file = PR_Open(filename, PR_RDWR|PR_CREATE_FILE, 0666);
187 if (file == NULL) goto finished;
188 for (index = 0; index < pages; index++)
189 {
190 cd->problem = sg_okay;
191 if (cd->action != sg_go) goto close;
192 cd->problem = sg_seek;
193 bytes = PR_Seek(file, pageSize * index, PR_SEEK_SET);
194 if (bytes != pageSize * index) goto close;
195 cd->problem = sg_write;
196 bytes = PR_Write(file, &zero, sizeof(zero));
197 if (bytes <= 0) goto close;
198 cd->writes += 1;
199 }
200 cd->problem = sg_close;
201 rv = PR_Close(file);
202 if (rv != PR_SUCCESS) goto purge;
203
204 cd->problem = sg_okay;
205 if (cd->action != sg_go) goto purge;
206
207 cd->problem = sg_open;
208 file = PR_Open(filename, PR_RDWR, 0666);
209 for (index = 0; index < pages; index++)
210 {
211 cd->problem = sg_okay;
212 if (cd->action != sg_go) goto close;
213 cd->problem = sg_seek;
214 bytes = PR_Seek(file, pageSize * index, PR_SEEK_SET);
215 if (bytes != pageSize * index) goto close;
216 cd->problem = sg_write;
217 bytes = PR_Write(file, &zero, sizeof(zero));
218 if (bytes <= 0) goto close;
219 cd->writes += 1;
220 random = (random + 511) % pages;
221 }
222 cd->problem = sg_close;
223 rv = PR_Close(file);
224 if (rv != PR_SUCCESS) goto purge;
225 cd->problem = sg_delete;
226 rv = PR_Delete(filename);
227 if (rv != PR_SUCCESS) goto finished;
228 }
229 }
230
231close:
232 (void)PR_Close(file);
233purge:
234 (void)PR_Delete(filename);
235finished:
236 PR_Lock(cd->ml);
237 cd->action = sg_done;
238 PR_NotifyCondVar(cd->cv);
239 PR_Unlock(cd->ml);
240
241 if (debug_mode) printf("Ending work on %s\n", filename);
242
243 return;
244} /* Thread */
245
246static Hammer_t hammer[100];
247static PRCondVar *cv;
248/***********************************************************************
249** PRIVATE FUNCTION: main
250** DESCRIPTION:
251** Hammer on the file I/O system
252** INPUTS: The usual argc and argv
253** argv[0] - program name (not used)
254** argv[1] - the number of times to execute the major loop
255** argv[2] - the number of threads to toss into the batch
256** argv[3] - the clipping number applied to randoms
257** default values: loops = 2, threads = 10, limit = 57
258** OUTPUTS: None
259** RETURN: None
260** SIDE EFFECTS:
261** Creates, accesses and deletes lots of files
262** RESTRICTIONS:
263** (Currently) must have file create permission in "/usr/tmp".
264** MEMORY: NA
265** ALGORITHM:
266** 1) Fork a "Thread()"
267** 2) Wait for 'interleave' seconds
268** 3) For [0..'threads') repeat [1..2]
269** 4) Mark all objects to stop
270** 5) Collect the threads, accumulating the results
271** 6) For [0..'loops') repeat [1..5]
272** 7) Print accumulated results and exit
273**
274** Characteristic output (from IRIX)
275** Random File: Using loops = 2, threads = 10, limit = 57
276** Random File: [min [avg] max] writes/sec average
277***********************************************************************/
278int main (int argc, char *argv[])
279{
280 PRLock *ml;
281 PRUint32 id = 0;
282 int active, poll;
283 PRIntervalTime interleave;
284 PRIntervalTime duration = 0;
285 int limit = 0, loops = 0, threads = 0, times;
286 PRUint32 writes, writesMin = 0x7fffffff, writesTot = 0, durationTot = 0, writesMax = 0;
287
288 const char *where[] = {"okay", "open", "close", "delete", "write", "seek"};
289
290 /* The command line argument: -d is used to determine if the test is being run
291 in debug mode. The regress tool requires only one line output:PASS or FAIL.
292 All of the printfs associated with this test has been handled with a if (debug_mode)
293 test.
294 Usage: test_name -d
295 */
296 PLOptStatus os;
297 PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:t:i:");
298 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
299 {
300 if (PL_OPT_BAD == os) continue;
301 switch (opt->option)
302 {
303 case 'G': /* global threads */
304 thread_scope = PR_GLOBAL_THREAD;
305 break;
306 case 'd': /* debug mode */
307 debug_mode = 1;
308 break;
309 case 'l': /* limiting number */
310 limit = atoi(opt->value);
311 break;
312 case 't': /* number of threads */
313 threads = atoi(opt->value);
314 break;
315 case 'i': /* iteration counter */
316 loops = atoi(opt->value);
317 break;
318 default:
319 break;
320 }
321 }
322 PL_DestroyOptState(opt);
323
324 /* main test */
325
326 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
327 PR_STDIO_INIT();
328
329 interleave = PR_SecondsToInterval(10);
330
331#ifdef XP_MAC
332 SetupMacPrintfLog("ranfile.log");
333 debug_mode = 1;
334#endif
335
336 ml = PR_NewLock();
337 cv = PR_NewCondVar(ml);
338
339 if (loops == 0) loops = DEFAULT_LOOPS;
340 if (limit == 0) limit = DEFAULT_LIMIT;
341 if (threads == 0) threads = DEFAULT_THREADS;
342
343 if (debug_mode) printf(
344 "%s: Using loops = %d, threads = %d, limit = %d and %s threads\n",
345 programName, loops, threads, limit,
346 (thread_scope == PR_LOCAL_THREAD) ? "LOCAL" : "GLOBAL");
347
348 for (times = 0; times < loops; ++times)
349 {
350 if (debug_mode) printf("%s: Setting concurrency level to %d\n", programName, times + 1);
351 PR_SetConcurrency(times + 1);
352 for (active = 0; active < threads; active++)
353 {
354 hammer[active].ml = ml;
355 hammer[active].cv = cv;
356 hammer[active].id = id++;
357 hammer[active].writes = 0;
358 hammer[active].action = sg_go;
359 hammer[active].problem = sg_okay;
360 hammer[active].limit = (Random() % limit) + 1;
361 hammer[active].timein = PR_IntervalNow();
362 hammer[active].thread = PR_CreateThread(
363 PR_USER_THREAD, Thread, &hammer[active],
364 PR_GetThreadPriority(PR_GetCurrentThread()),
365 thread_scope, PR_JOINABLE_THREAD, 0);
366
367 PR_Lock(ml);
368 PR_WaitCondVar(cv, interleave); /* start new ones slowly */
369 PR_Unlock(ml);
370 }
371
372 /*
373 * The last thread started has had the opportunity to run for
374 * 'interleave' seconds. Now gather them all back in.
375 */
376 PR_Lock(ml);
377 for (poll = 0; poll < threads; poll++)
378 {
379 if (hammer[poll].action == sg_go) /* don't overwrite done */
380 hammer[poll].action = sg_stop; /* ask him to stop */
381 }
382 PR_Unlock(ml);
383
384 while (active > 0)
385 {
386 for (poll = 0; poll < threads; poll++)
387 {
388 PR_Lock(ml);
389 while (hammer[poll].action < sg_done)
390 PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
391 PR_Unlock(ml);
392
393 active -= 1; /* this is another one down */
394 (void)PR_JoinThread(hammer[poll].thread);
395 hammer[poll].thread = NULL;
396 if (hammer[poll].problem == sg_okay)
397 {
398 duration = PR_IntervalToMilliseconds(
399 PR_IntervalNow() - hammer[poll].timein);
400 writes = hammer[poll].writes * 1000 / duration;
401 if (writes < writesMin)
402 writesMin = writes;
403 if (writes > writesMax)
404 writesMax = writes;
405 writesTot += hammer[poll].writes;
406 durationTot += duration;
407 }
408 else
409 if (debug_mode) printf(
410 "%s: test failed %s after %ld seconds\n",
411 programName, where[hammer[poll].problem], duration);
412 else failed_already=1;
413 }
414 }
415 }
416 if (debug_mode) printf(
417 "%s: [%ld [%ld] %ld] writes/sec average\n",
418 programName, writesMin, writesTot * 1000 / durationTot, writesMax);
419
420 PR_DestroyCondVar(cv);
421 PR_DestroyLock(ml);
422
423 if (failed_already)
424 {
425 printf("FAIL\n");
426 return 1;
427 }
428 else
429 {
430 printf("PASS\n");
431 return 0;
432 }
433} /* main */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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