1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /*
7 * File: priotest.c
8 * Purpose: testing priorities
9 */
10
11 #include "prcmon.h"
12 #include "prinit.h"
13 #include "prinrval.h"
14 #include "prlock.h"
15 #include "prlog.h"
16 #include "prmon.h"
17 #include "prprf.h"
18 #include "prthread.h"
19 #include "prtypes.h"
20
21 #include "plerror.h"
22 #include "plgetopt.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #define DEFAULT_DURATION 5
28
29 static PRBool failed = PR_FALSE;
30 static PRIntervalTime oneSecond;
31 static PRFileDesc *debug_out = NULL;
32 static PRBool debug_mode = PR_FALSE;
33
PerSecond(PRIntervalTime timein)34 static PRUint32 PerSecond(PRIntervalTime timein)
35 {
36 PRUint32 loop = 0;
37 while (((PRIntervalTime)(PR_IntervalNow()) - timein) < oneSecond) {
38 loop += 1;
39 }
40 return loop;
41 } /* PerSecond */
42
Low(void * arg)43 static void PR_CALLBACK Low(void *arg)
44 {
45 PRUint32 t3 = 0, t2 = 0, t1 = 0, t0, *tn = (PRUint32*)arg;
46 while (1)
47 {
48 t0 = PerSecond(PR_IntervalNow());
49 *tn = (t3 + 3 * t2 + 3 * t1 + t0) / 8;
50 t3 = t2; t2 = t1; t1 = t0;
51 }
52 } /* Low */
53
High(void * arg)54 static void PR_CALLBACK High(void *arg)
55 {
56 PRUint32 t3 = 0, t2 = 0, t1 = 0, t0, *tn = (PRUint32*)arg;
57 while (1)
58 {
59 PRIntervalTime timein = PR_IntervalNow();
60 PR_Sleep(oneSecond >> 2); /* 0.25 seconds */
61 t0 = PerSecond(timein);
62 *tn = (t3 + 3 * t2 + 3 * t1 + t0) / 8;
63 t3 = t2; t2 = t1; t1 = t0;
64 }
65 } /* High */
66
Help(void)67 static void Help(void)
68 {
69 PR_fprintf(
70 debug_out, "Usage: priotest [-d] [-c n]\n");
71 PR_fprintf(
72 debug_out, "-c n\tduration of test in seconds (default: %d)\n", DEFAULT_DURATION);
73 PR_fprintf(
74 debug_out, "-d\tturn on debugging output (default: FALSE)\n");
75 } /* Help */
76
RudimentaryTests(void)77 static void RudimentaryTests(void)
78 {
79 /*
80 ** Try some rudimentary tests like setting valid priority and
81 ** getting it back, or setting invalid priorities and getting
82 ** back a valid answer.
83 */
84 PRThreadPriority priority;
85 PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_URGENT);
86 priority = PR_GetThreadPriority(PR_GetCurrentThread());
87 failed = ((PR_TRUE == failed) || (PR_PRIORITY_URGENT != priority))
88 ? PR_TRUE : PR_FALSE;
89 if (debug_mode && (PR_PRIORITY_URGENT != priority))
90 {
91 PR_fprintf(debug_out, "PR_[S/G]etThreadPriority() failed\n");
92 }
93
94
95 PR_SetThreadPriority(
96 PR_GetCurrentThread(), (PRThreadPriority)(PR_PRIORITY_FIRST - 1));
97 priority = PR_GetThreadPriority(PR_GetCurrentThread());
98 failed = ((PR_TRUE == failed) || (PR_PRIORITY_FIRST != priority))
99 ? PR_TRUE : PR_FALSE;
100 if (debug_mode && (PR_PRIORITY_FIRST != priority))
101 {
102 PR_fprintf(debug_out, "PR_SetThreadPriority(-1) failed\n");
103 }
104
105 PR_SetThreadPriority(
106 PR_GetCurrentThread(), (PRThreadPriority)(PR_PRIORITY_LAST + 1));
107 priority = PR_GetThreadPriority(PR_GetCurrentThread());
108 failed = ((PR_TRUE == failed) || (PR_PRIORITY_LAST != priority))
109 ? PR_TRUE : PR_FALSE;
110 if (debug_mode && (PR_PRIORITY_LAST != priority))
111 {
112 PR_fprintf(debug_out, "PR_SetThreadPriority(+1) failed\n");
113 }
114
115 } /* RudimentataryTests */
116
CreateThreads(PRUint32 * lowCount,PRUint32 * highCount)117 static void CreateThreads(PRUint32 *lowCount, PRUint32 *highCount)
118 {
119 (void)PR_CreateThread(
120 PR_USER_THREAD, Low, lowCount, PR_PRIORITY_LOW,
121 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
122 (void)PR_CreateThread(
123 PR_USER_THREAD, High, highCount, PR_PRIORITY_HIGH,
124 PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
125 } /* CreateThreads */
126
main(int argc,char ** argv)127 int main(int argc, char **argv)
128 {
129 PLOptStatus os;
130 PRIntn duration = DEFAULT_DURATION;
131 PRUint32 totalCount, highCount = 0, lowCount = 0;
132 PLOptState *opt = PL_CreateOptState(argc, argv, "hdc:");
133
134 debug_out = PR_STDOUT;
135 oneSecond = PR_SecondsToInterval(1);
136
137 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
138 {
139 if (PL_OPT_BAD == os) {
140 continue;
141 }
142 switch (opt->option)
143 {
144 case 'd': /* debug mode */
145 debug_mode = PR_TRUE;
146 break;
147 case 'c': /* test duration */
148 duration = atoi(opt->value);
149 break;
150 case 'h': /* help message */
151 default:
152 Help();
153 return 2;
154 }
155 }
156 PL_DestroyOptState(opt);
157 PR_STDIO_INIT();
158
159 if (duration == 0) {
160 duration = DEFAULT_DURATION;
161 }
162
163 RudimentaryTests();
164
165 printf("Priority test: running for %d seconds\n\n", duration);
166
167 (void)PerSecond(PR_IntervalNow());
168 totalCount = PerSecond(PR_IntervalNow());
169
170 PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_URGENT);
171
172 if (debug_mode)
173 {
174 PR_fprintf(debug_out,
175 "The high priority thread should get approximately three\n");
176 PR_fprintf( debug_out,
177 "times what the low priority thread manages. A maximum of \n");
178 PR_fprintf( debug_out, "%d cycles are available.\n\n", totalCount);
179 }
180
181 duration = (duration + 4) / 5;
182 CreateThreads(&lowCount, &highCount);
183 while (duration--)
184 {
185 PRIntn loop = 5;
186 while (loop--) {
187 PR_Sleep(oneSecond);
188 }
189 if (debug_mode) {
190 PR_fprintf(debug_out, "high : low :: %d : %d\n", highCount, lowCount);
191 }
192 }
193
194
195 PR_ProcessExit((failed) ? 1 : 0);
196
197 PR_NOT_REACHED("You can't get here -- but you did!");
198 return 1; /* or here */
199
200 } /* main */
201
202 /* priotest.c */
203