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