VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/cvar.c@ 55761

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

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 8.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** 1996 - Netscape Communications Corporation
40**
41** Name: cvar.c
42**
43** Description: Tests Condition Variable Operations
44**
45** Modification History:
46** 13-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** 12-June-97 Revert to return code 0 and 1.
54***********************************************************************/
55
56/***********************************************************************
57** Includes
58***********************************************************************/
59
60#include "nspr.h"
61
62/* Used to get the command line option */
63#include "plgetopt.h"
64
65#include <stdio.h>
66#include <stdlib.h>
67#include <string.h>
68
69#ifdef XP_MAC
70#include "prlog.h"
71#define printf PR_LogPrint
72extern void SetupMacPrintfLog(char *logFile);
73#endif
74
75PRMonitor *mon;
76#define DEFAULT_COUNT 1000
77PRInt32 count = 0;
78PRIntn debug_mode;
79
80#define kQSIZE 1
81
82typedef struct {
83 PRLock *bufLock;
84 int startIdx;
85 int numFull;
86 PRCondVar *notFull;
87 PRCondVar *notEmpty;
88 void *data[kQSIZE];
89} CircBuf;
90
91static PRBool failed = PR_FALSE;
92
93/*
94** NewCB creates and initializes a new circular buffer.
95*/
96static CircBuf* NewCB(void)
97{
98 CircBuf *cbp;
99
100 cbp = PR_NEW(CircBuf);
101 if (cbp == NULL)
102 return (NULL);
103
104 cbp->bufLock = PR_NewLock();
105 cbp->startIdx = 0;
106 cbp->numFull = 0;
107 cbp->notFull = PR_NewCondVar(cbp->bufLock);
108 cbp->notEmpty = PR_NewCondVar(cbp->bufLock);
109
110 return (cbp);
111}
112
113/*
114** DeleteCB frees a circular buffer.
115*/
116static void DeleteCB(CircBuf *cbp)
117{
118 PR_DestroyLock(cbp->bufLock);
119 PR_DestroyCondVar(cbp->notFull);
120 PR_DestroyCondVar(cbp->notEmpty);
121 PR_DELETE(cbp);
122}
123
124
125/*
126** PutCBData puts new data on the queue. If the queue is full, it waits
127** until there is room.
128*/
129static void PutCBData(CircBuf *cbp, void *data)
130{
131 PR_Lock(cbp->bufLock);
132 /* wait while the buffer is full */
133 while (cbp->numFull == kQSIZE)
134 PR_WaitCondVar(cbp->notFull,PR_INTERVAL_NO_TIMEOUT);
135 cbp->data[(cbp->startIdx + cbp->numFull) % kQSIZE] = data;
136 cbp->numFull += 1;
137
138 /* let a waiting reader know that there is data */
139 PR_NotifyCondVar(cbp->notEmpty);
140 PR_Unlock(cbp->bufLock);
141
142}
143
144
145/*
146** GetCBData gets the oldest data on the queue. If the queue is empty, it waits
147** until new data appears.
148*/
149static void* GetCBData(CircBuf *cbp)
150{
151 void *data;
152
153 PR_Lock(cbp->bufLock);
154 /* wait while the buffer is empty */
155 while (cbp->numFull == 0)
156 PR_WaitCondVar(cbp->notEmpty,PR_INTERVAL_NO_TIMEOUT);
157 data = cbp->data[cbp->startIdx];
158 cbp->startIdx =(cbp->startIdx + 1) % kQSIZE;
159 cbp->numFull -= 1;
160
161 /* let a waiting writer know that there is room */
162 PR_NotifyCondVar(cbp->notFull);
163 PR_Unlock(cbp->bufLock);
164
165 return (data);
166}
167
168
169/************************************************************************/
170
171static int alive;
172
173static void PR_CALLBACK CXReader(void *arg)
174{
175 CircBuf *cbp = (CircBuf *)arg;
176 PRInt32 i, n;
177 void *data;
178
179 n = count / 2;
180 for (i = 0; i < n; i++) {
181 data = GetCBData(cbp);
182 if ((int)data != i)
183 if (debug_mode) printf("data mismatch at for i = %d usec\n", i);
184 }
185
186 PR_EnterMonitor(mon);
187 --alive;
188 PR_Notify(mon);
189 PR_ExitMonitor(mon);
190}
191
192static void PR_CALLBACK CXWriter(void *arg)
193{
194 CircBuf *cbp = (CircBuf *)arg;
195 PRInt32 i, n;
196
197 n = count / 2;
198 for (i = 0; i < n; i++)
199 PutCBData(cbp, (void *)i);
200
201 PR_EnterMonitor(mon);
202 --alive;
203 PR_Notify(mon);
204 PR_ExitMonitor(mon);
205}
206
207static void CondWaitContextSwitch(PRThreadScope scope1, PRThreadScope scope2)
208{
209 PRThread *t1, *t2;
210 CircBuf *cbp;
211
212 PR_EnterMonitor(mon);
213
214 alive = 2;
215
216 cbp = NewCB();
217
218 t1 = PR_CreateThread(PR_USER_THREAD,
219 CXReader, cbp,
220 PR_PRIORITY_NORMAL,
221 scope1,
222 PR_UNJOINABLE_THREAD,
223 0);
224 PR_ASSERT(t1);
225 t2 = PR_CreateThread(PR_USER_THREAD,
226 CXWriter, cbp,
227 PR_PRIORITY_NORMAL,
228 scope2,
229 PR_UNJOINABLE_THREAD,
230 0);
231 PR_ASSERT(t2);
232
233 /* Wait for both of the threads to exit */
234 while (alive) {
235 PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
236 }
237
238 DeleteCB(cbp);
239
240 PR_ExitMonitor(mon);
241}
242
243static void CondWaitContextSwitchUU(void)
244{
245 CondWaitContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
246}
247
248static void CondWaitContextSwitchUK(void)
249{
250 CondWaitContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
251}
252
253static void CondWaitContextSwitchKK(void)
254{
255 CondWaitContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
256}
257
258/************************************************************************/
259
260static void Measure(void (*func)(void), const char *msg)
261{
262 PRIntervalTime start, stop;
263 double d;
264
265 start = PR_IntervalNow();
266 (*func)();
267 stop = PR_IntervalNow();
268
269 d = (double)PR_IntervalToMicroseconds(stop - start);
270
271 if (debug_mode) printf("%40s: %6.2f usec\n", msg, d / count);
272
273 if (0 == d) failed = PR_TRUE;
274}
275
276static PRIntn PR_CALLBACK RealMain(int argc, char **argv)
277{
278 /* The command line argument: -d is used to determine if the test is being run
279 in debug mode. The regress tool requires only one line output:PASS or FAIL.
280 All of the printfs associated with this test has been handled with a if (debug_mode)
281 test.
282 Usage: test_name [-d] [-c n]
283 */
284 PLOptStatus os;
285 PLOptState *opt = PL_CreateOptState(argc, argv, "dc:");
286 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
287 {
288 if (PL_OPT_BAD == os) continue;
289 switch (opt->option)
290 {
291 case 'd': /* debug mode */
292 debug_mode = 1;
293 break;
294 case 'c': /* loop count */
295 count = atoi(opt->value);
296 break;
297 default:
298 break;
299 }
300 }
301 PL_DestroyOptState(opt);
302
303 if (0 == count) count = DEFAULT_COUNT;
304
305#ifdef XP_MAC
306 SetupMacPrintfLog("cvar.log");
307 debug_mode = 1;
308#endif
309
310 mon = PR_NewMonitor();
311
312 Measure(CondWaitContextSwitchUU, "cond var wait context switch- user/user");
313 Measure(CondWaitContextSwitchUK, "cond var wait context switch- user/kernel");
314 Measure(CondWaitContextSwitchKK, "cond var wait context switch- kernel/kernel");
315
316 PR_DestroyMonitor(mon);
317
318 if (debug_mode) printf("%s\n", (failed) ? "FAILED" : "PASSED");
319
320 if(failed)
321 return 1;
322 else
323 return 0;
324}
325
326
327PRIntn main(PRIntn argc, char *argv[])
328{
329 PRIntn rv;
330
331 PR_STDIO_INIT();
332 rv = PR_Initialize(RealMain, argc, argv, 0);
333 return rv;
334} /* main */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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