VirtualBox

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

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

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 9.3 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 * A test for the pollable events.
40 *
41 * A number of threads are in a ring configuration, each waiting on
42 * a pollable event that is set by its upstream neighbor.
43 */
44
45#include "prinit.h"
46#include "prio.h"
47#include "prthread.h"
48#include "prerror.h"
49#include "prmem.h"
50#include "prlog.h"
51#include "prprf.h"
52
53#include "plgetopt.h"
54
55#include <stdlib.h>
56
57#define DEFAULT_THREADS 10
58#define DEFAULT_LOOPS 100
59
60PRIntn numThreads = DEFAULT_THREADS;
61PRIntn numIterations = DEFAULT_LOOPS;
62PRIntervalTime dally = PR_INTERVAL_NO_WAIT;
63PRFileDesc *debug_out = NULL;
64PRBool debug_mode = PR_FALSE;
65PRBool verbosity = PR_FALSE;
66
67typedef struct ThreadData {
68 PRFileDesc *event;
69 int index;
70 struct ThreadData *next;
71} ThreadData;
72
73void ThreadRoutine(void *arg)
74{
75 ThreadData *data = (ThreadData *) arg;
76 PRIntn i;
77 PRPollDesc pd;
78 PRInt32 rv;
79
80 pd.fd = data->event;
81 pd.in_flags = PR_POLL_READ;
82
83 for (i = 0; i < numIterations; i++) {
84 rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
85 if (rv == -1) {
86 PR_fprintf(PR_STDERR, "PR_Poll failed\n");
87 exit(1);
88 }
89 if (verbosity) {
90 PR_fprintf(debug_out, "thread %d awakened\n", data->index);
91 }
92 PR_ASSERT(rv != 0);
93 PR_ASSERT(pd.out_flags & PR_POLL_READ);
94 if (PR_WaitForPollableEvent(data->event) == PR_FAILURE) {
95 PR_fprintf(PR_STDERR, "consume event failed\n");
96 exit(1);
97 }
98 if (dally != PR_INTERVAL_NO_WAIT) {
99 PR_Sleep(dally);
100 }
101 if (verbosity) {
102 PR_fprintf(debug_out, "thread %d posting event\n", data->index);
103 }
104 if (PR_SetPollableEvent(data->next->event) == PR_FAILURE) {
105 PR_fprintf(PR_STDERR, "post event failed\n");
106 exit(1);
107 }
108 }
109}
110
111static void Help(void)
112{
113 debug_out = PR_STDOUT;
114
115 PR_fprintf(
116 debug_out, "Usage: pollable [-c n] [-t n] [-d] [-v] [-G] [-C n] [-D n]\n");
117 PR_fprintf(
118 debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
119 PR_fprintf(
120 debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
121 PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
122 PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
123 PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n");
124 PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
125 PR_fprintf(debug_out, "-D n\tdally setting (msecs) (default: 0)\n");
126} /* Help */
127
128int main(int argc, char **argv)
129{
130 ThreadData selfData;
131 ThreadData *data;
132 PRThread **thread;
133 void *block;
134 PRIntn i;
135 PRIntervalTime timeStart, timeEnd;
136 PRPollDesc pd;
137 PRInt32 rv;
138 PRThreadScope thread_scope = PR_LOCAL_THREAD;
139 PRBool help = PR_FALSE;
140 PRUintn concurrency = 1;
141 PRUintn average;
142 PLOptStatus os;
143 PLOptState *opt;
144
145 PR_STDIO_INIT();
146
147 opt = PL_CreateOptState(argc, argv, "hdvc:t:C:GD:");
148 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
149 if (PL_OPT_BAD == os) {
150 continue;
151 }
152 switch (opt->option) {
153 case 'v': /* verbose mode */
154 verbosity = PR_TRUE;
155 case 'd': /* debug mode */
156 debug_mode = PR_TRUE;
157 break;
158 case 'c': /* loop counter */
159 numIterations = atoi(opt->value);
160 break;
161 case 't': /* thread limit */
162 numThreads = atoi(opt->value);
163 break;
164 case 'C': /* Concurrency limit */
165 concurrency = atoi(opt->value);
166 break;
167 case 'G': /* global threads only */
168 thread_scope = PR_GLOBAL_THREAD;
169 break;
170 case 'D': /* dally */
171 dally = PR_MillisecondsToInterval(atoi(opt->value));
172 break;
173 case 'h': /* help message */
174 Help();
175 help = PR_TRUE;
176 break;
177 default:
178 break;
179 }
180 }
181 PL_DestroyOptState(opt);
182
183 if (help) {
184 return 1;
185 }
186
187 if (concurrency > 1) {
188 PR_SetConcurrency(concurrency);
189 }
190
191 if (PR_TRUE == debug_mode) {
192 debug_out = PR_STDOUT;
193 PR_fprintf(debug_out, "Test parameters\n");
194 PR_fprintf(debug_out, "\tThreads involved: %d\n", numThreads);
195 PR_fprintf(debug_out, "\tIteration limit: %d\n", numIterations);
196 PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency);
197 PR_fprintf(debug_out, "\tThread type: %s\n",
198 (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
199 }
200
201 /*
202 * Malloc a block of memory and divide it into data and thread.
203 */
204 block = PR_MALLOC(numThreads * (sizeof(ThreadData) + sizeof(PRThread *)));
205 if (block == NULL) {
206 PR_fprintf(PR_STDERR, "cannot malloc, failed\n");
207 exit(1);
208 }
209 data = (ThreadData *) block;
210 thread = (PRThread **) &data[numThreads];
211
212 /* Pollable event */
213 selfData.event = PR_NewPollableEvent();
214 if (selfData.event == NULL) {
215 PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n",
216 PR_GetError(), PR_GetOSError());
217 exit(1);
218 }
219 selfData.next = &data[0];
220 for (i = 0; i < numThreads; i++) {
221 data[i].event = PR_NewPollableEvent();
222 if (data[i].event == NULL) {
223 PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n",
224 PR_GetError(), PR_GetOSError());
225 exit(1);
226 }
227 data[i].index = i;
228 if (i != numThreads - 1) {
229 data[i].next = &data[i + 1];
230 } else {
231 data[i].next = &selfData;
232 }
233
234 thread[i] = PR_CreateThread(PR_USER_THREAD,
235 ThreadRoutine, &data[i], PR_PRIORITY_NORMAL,
236 thread_scope, PR_JOINABLE_THREAD, 0);
237 if (thread[i] == NULL) {
238 PR_fprintf(PR_STDERR, "cannot create thread\n");
239 exit(1);
240 }
241 }
242
243 timeStart = PR_IntervalNow();
244 pd.fd = selfData.event;
245 pd.in_flags = PR_POLL_READ;
246 for (i = 0; i < numIterations; i++) {
247 if (dally != PR_INTERVAL_NO_WAIT) {
248 PR_Sleep(dally);
249 }
250 if (verbosity) {
251 PR_fprintf(debug_out, "main thread posting event\n");
252 }
253 if (PR_SetPollableEvent(selfData.next->event) == PR_FAILURE) {
254 PR_fprintf(PR_STDERR, "set event failed\n");
255 exit(1);
256 }
257 rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
258 if (rv == -1) {
259 PR_fprintf(PR_STDERR, "wait failed\n");
260 exit(1);
261 }
262 PR_ASSERT(rv != 0);
263 PR_ASSERT(pd.out_flags & PR_POLL_READ);
264 if (verbosity) {
265 PR_fprintf(debug_out, "main thread awakened\n");
266 }
267 if (PR_WaitForPollableEvent(selfData.event) == PR_FAILURE) {
268 PR_fprintf(PR_STDERR, "consume event failed\n");
269 exit(1);
270 }
271 }
272 timeEnd = PR_IntervalNow();
273
274 if (debug_mode) {
275 average = PR_IntervalToMicroseconds(timeEnd - timeStart)
276 / (numIterations * numThreads);
277 PR_fprintf(debug_out, "Average switch times %d usecs for %d threads\n",
278 average, numThreads);
279 }
280
281 for (i = 0; i < numThreads; i++) {
282 if (PR_JoinThread(thread[i]) == PR_FAILURE) {
283 PR_fprintf(PR_STDERR, "join thread failed\n");
284 exit(1);
285 }
286 PR_DestroyPollableEvent(data[i].event);
287 }
288 PR_DELETE(block);
289 PR_DestroyPollableEvent(selfData.event);
290
291 PR_fprintf(PR_STDOUT, "PASSED\n");
292 return 0;
293}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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