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     return loop;
40 }  /* PerSecond */
41 
Low(void * arg)42 static void PR_CALLBACK Low(void *arg)
43 {
44     PRUint32 t3 = 0, t2 = 0, t1 = 0, t0, *tn = (PRUint32*)arg;
45     while (1)
46     {
47         t0 = PerSecond(PR_IntervalNow());
48         *tn = (t3 + 3 * t2 + 3 * t1 + t0) / 8;
49         t3 = t2; t2 = t1; t1 = t0;
50     }
51 }  /* Low */
52 
High(void * arg)53 static void PR_CALLBACK High(void *arg)
54 {
55     PRUint32 t3 = 0, t2 = 0, t1 = 0, t0, *tn = (PRUint32*)arg;
56     while (1)
57     {
58         PRIntervalTime timein = PR_IntervalNow();
59         PR_Sleep(oneSecond >> 2);  /* 0.25 seconds */
60         t0 = PerSecond(timein);
61         *tn = (t3 + 3 * t2 + 3 * t1 + t0) / 8;
62         t3 = t2; t2 = t1; t1 = t0;
63     }
64 }  /* High */
65 
Help(void)66 static void Help(void)
67 {
68     PR_fprintf(
69 		debug_out, "Usage: priotest [-d] [-c n]\n");
70     PR_fprintf(
71 		debug_out, "-c n\tduration of test in seconds (default: %d)\n", DEFAULT_DURATION);
72     PR_fprintf(
73         debug_out, "-d\tturn on debugging output (default: FALSE)\n");
74 }  /* Help */
75 
RudimentaryTests(void)76 static void RudimentaryTests(void)
77 {
78     /*
79     ** Try some rudimentary tests like setting valid priority and
80     ** getting it back, or setting invalid priorities and getting
81     ** back a valid answer.
82     */
83     PRThreadPriority priority;
84     PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_URGENT);
85     priority = PR_GetThreadPriority(PR_GetCurrentThread());
86     failed = ((PR_TRUE == failed) || (PR_PRIORITY_URGENT != priority))
87         ? PR_TRUE : PR_FALSE;
88     if (debug_mode && (PR_PRIORITY_URGENT != priority))
89     {
90         PR_fprintf(debug_out, "PR_[S/G]etThreadPriority() failed\n");
91     }
92 
93 
94     PR_SetThreadPriority(
95         PR_GetCurrentThread(), (PRThreadPriority)(PR_PRIORITY_FIRST - 1));
96     priority = PR_GetThreadPriority(PR_GetCurrentThread());
97     failed = ((PR_TRUE == failed) || (PR_PRIORITY_FIRST != priority))
98         ? PR_TRUE : PR_FALSE;
99     if (debug_mode && (PR_PRIORITY_FIRST != priority))
100     {
101         PR_fprintf(debug_out, "PR_SetThreadPriority(-1) failed\n");
102     }
103 
104     PR_SetThreadPriority(
105         PR_GetCurrentThread(), (PRThreadPriority)(PR_PRIORITY_LAST + 1));
106     priority = PR_GetThreadPriority(PR_GetCurrentThread());
107     failed = ((PR_TRUE == failed) || (PR_PRIORITY_LAST != priority))
108         ? PR_TRUE : PR_FALSE;
109     if (debug_mode && (PR_PRIORITY_LAST != priority))
110     {
111         PR_fprintf(debug_out, "PR_SetThreadPriority(+1) failed\n");
112     }
113 
114 }  /* RudimentataryTests */
115 
CreateThreads(PRUint32 * lowCount,PRUint32 * highCount)116 static void CreateThreads(PRUint32 *lowCount, PRUint32 *highCount)
117 {
118     (void)PR_CreateThread(
119         PR_USER_THREAD, Low, lowCount, PR_PRIORITY_LOW,
120         PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
121     (void)PR_CreateThread(
122         PR_USER_THREAD, High, highCount, PR_PRIORITY_HIGH,
123         PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
124 } /* CreateThreads */
125 
main(int argc,char ** argv)126 int main(int argc, char **argv)
127 {
128     PLOptStatus os;
129     PRIntn duration = DEFAULT_DURATION;
130     PRUint32 totalCount, highCount = 0, lowCount = 0;
131 	PLOptState *opt = PL_CreateOptState(argc, argv, "hdc:");
132 
133     debug_out = PR_STDOUT;
134     oneSecond = PR_SecondsToInterval(1);
135 
136 	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
137     {
138 		if (PL_OPT_BAD == os) continue;
139         switch (opt->option)
140         {
141         case 'd':  /* debug mode */
142 			debug_mode = PR_TRUE;
143             break;
144         case 'c':  /* test duration */
145 			duration = atoi(opt->value);
146             break;
147         case 'h':  /* help message */
148          default:
149 			Help();
150 			return 2;
151         }
152     }
153 	PL_DestroyOptState(opt);
154     PR_STDIO_INIT();
155 
156     if (duration == 0) duration = DEFAULT_DURATION;
157 
158     RudimentaryTests();
159 
160     printf("Priority test: running for %d seconds\n\n", duration);
161 
162     (void)PerSecond(PR_IntervalNow());
163     totalCount = PerSecond(PR_IntervalNow());
164 
165     PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_URGENT);
166 
167     if (debug_mode)
168     {
169         PR_fprintf(debug_out,
170 		    "The high priority thread should get approximately three\n");
171         PR_fprintf( debug_out,
172 		    "times what the low priority thread manages. A maximum of \n");
173         PR_fprintf( debug_out, "%d cycles are available.\n\n", totalCount);
174     }
175 
176     duration = (duration + 4) / 5;
177     CreateThreads(&lowCount, &highCount);
178     while (duration--)
179     {
180         PRIntn loop = 5;
181         while (loop--) PR_Sleep(oneSecond);
182         if (debug_mode)
183             PR_fprintf(debug_out, "high : low :: %d : %d\n", highCount, lowCount);
184     }
185 
186 
187     PR_ProcessExit((failed) ? 1 : 0);
188 
189 	PR_NOT_REACHED("You can't get here -- but you did!");
190 	return 1;  /* or here */
191 
192 }  /* main */
193 
194 /* priotest.c */
195