]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/language/c/libc/time/v2_0/tests/clock.c
Initial revision
[karo-tx-redboot.git] / packages / language / c / libc / time / v2_0 / tests / clock.c
1 //=================================================================
2 //
3 //        clock.c
4 //
5 //        Testcase for C library clock()
6 //
7 //=================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //=================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):     ctarpy, jlarmour
44 // Contributors:  
45 // Date:          1999-03-05
46 // Description:   Contains testcode for C library clock() function
47 //
48 //
49 //####DESCRIPTIONEND####
50
51 // CONFIGURATION
52
53 #include <pkgconf/libc_time.h>   // Configuration header
54 #include <pkgconf/system.h>
55 #include <pkgconf/isoinfra.h>
56 #include <pkgconf/infra.h>
57
58 #include <cyg/infra/testcase.h>
59
60 // This test is bound to fail often on the synthetic target -- we
61 // don't have exclusive access to the CPU.
62
63 #if defined(CYGPKG_HAL_SYNTH)
64 # define NA_MSG "Timing accuracy not guaranteed on synthetic target"
65 #elif !defined(CYGINT_ISO_MAIN_STARTUP)
66 # define NA_MSG "Requires main() startup"
67 #elif defined(CYGDBG_USE_TRACING)
68 # define NA_MSG "Cannot give an accurate test when tracing is enabled"
69 #endif
70
71 #ifdef NA_MSG
72 void
73 cyg_start(void)
74 {
75     CYG_TEST_INIT();
76     CYG_TEST_NA( NA_MSG );
77 }
78
79 #else
80
81
82 // INCLUDES
83
84 #include <time.h>
85 #include <cyg/infra/diag.h>
86 #include <cyg/hal/hal_cache.h>
87 #include <cyg/hal/hal_intr.h>
88
89
90 // CONSTANTS
91
92 // This defines how many loops before we decide that
93 // the clock doesnt work
94 #define MAX_TIMEOUT 100000
95
96 // Percentage error before we declare fail: range 0 - 100
97 #define TOLERANCE 40
98
99 // Permissible absolute deviation from mean value to take care of incorrect
100 // failure conclusions in case of small mean values (if absolute values of
101 // clock() are small, percentage variation can be large)
102 #define FUDGE_FACTOR 6
103
104 // Number of samples to take
105 #define SAMPLES 30
106
107 // We ignore ctrs[0] because it's always 0
108 // We ignore ctrs[1] because it will always be odd since it was
109 // the first measurement taken at the start of the looping, and
110 // the initial clock measurement (in clocks[0]) was not treated as
111 // part of the loop and therefore can't be considered to take the same
112 // time.
113 // We ignore ctrs[2] because it always seems to be substantially faster
114 // that the other samples. Probably due to cache/timing effect after the
115 // previous loop.
116 // Finally, ctrs[3] is skipped because it's also very fast on ARM targets.
117
118 #define SKIPPED_SAMPLES 6
119
120
121 // FUNCTIONS
122
123 static int
124 my_abs(int i)
125 {
126     return (i < 0) ? -i : i;
127 } // my_abs()
128
129
130 // Clock measurement is done in a separate function so that alignment
131 // constraints are deterministic - some processors may perform better
132 // in loops that are better aligned, so by making it always the same
133 // function, this is prevented.
134 // FIXME: how do we guarantee the compiler won't inline this on -O3?
135 static unsigned long
136 clock_loop( const int timeout, clock_t prevclock, clock_t *newclock )
137 {
138     clock_t c=0;
139     long i;
140
141     for (i=0; i<timeout; i++) {
142         c = clock();
143         if ( c != prevclock )
144             break; // Hit the next clock pulse
145     }
146     
147     if (i==timeout)
148         CYG_TEST_FAIL_FINISH("No change in clock state!");
149
150     // it should not overflow in the lifetime of this test
151     if (c < prevclock)
152         CYG_TEST_FAIL_FINISH("Clock decremented!");
153
154     *newclock = c;
155
156     return i;
157 } // clock_loop()
158
159 // both of these get zeroed out
160 static unsigned long ctrs[SAMPLES];
161 static clock_t clocks[SAMPLES];
162
163 int
164 main(int argc, char *argv[])
165 {
166     unsigned long mean=0, sum=0, maxerr=0;
167     int i;
168     unsigned int absdev;
169
170     CYG_TEST_INIT();
171
172     CYG_TEST_INFO("Starting tests from testcase " __FILE__ " for C library "
173                   "clock() function");
174
175     // First disable the caches - they may affect the timing loops
176     // below - causing the elapsed time during the clock() call to vary.
177     {
178         register CYG_INTERRUPT_STATE oldints;
179
180         HAL_DISABLE_INTERRUPTS(oldints);
181         HAL_DCACHE_SYNC();
182         HAL_ICACHE_DISABLE();
183         HAL_DCACHE_DISABLE();
184         HAL_DCACHE_SYNC();
185         HAL_ICACHE_INVALIDATE_ALL();
186         HAL_DCACHE_INVALIDATE_ALL();
187         HAL_RESTORE_INTERRUPTS(oldints);
188     }
189
190     // This waits for a clock tick, to ensure that we are at the
191     // start of a clock period. Then sit in a tight loop to get
192     // the clock period. Repeat this, and make sure that it the
193     // two timed periods are acceptably close.
194
195     clocks[0] = clock();
196     
197     if (clocks[0] == (clock_t)-1)  // unimplemented is potentially valid.
198     {
199 #ifdef CYGSEM_LIBC_TIME_CLOCK_WORKING
200         CYG_TEST_FAIL_FINISH( "clock() returns -1, meaning unimplemented");
201 #else
202         CYG_TEST_PASS_FINISH( "clock() returns -1, meaning unimplemented");
203 #endif
204     } // if
205
206     // record clocks in a tight consistent loop to avoid random variations
207     for (i=1; i<SAMPLES; i++) {
208         ctrs[i] = clock_loop( MAX_TIMEOUT, clocks[i-1], &clocks[i] );
209     }
210
211     for (i=0;i<SAMPLES;i++) {
212         // output what we got - useful for diagnostics of occasional
213         // test failures
214         diag_printf("clocks[%d] = %d, ctrs[%d] = %d\n", i, clocks[i],
215                     i, ctrs[i]);
216
217         // Now we work out the error etc.
218         if (i>=SKIPPED_SAMPLES) {
219             sum += ctrs[i];
220         }
221     }
222
223     // deduce out the average
224     mean = sum / (SAMPLES-SKIPPED_SAMPLES);
225
226     // now go through valid results and compare against average
227     for (i=SKIPPED_SAMPLES;i<SAMPLES;i++) {
228         unsigned long err;
229
230         absdev = my_abs(ctrs[i]-mean);
231         // use mean+1 as divisor to avoid div-by-zero
232         err = (100 * absdev) / (mean+1);
233         if (err > TOLERANCE && absdev > FUDGE_FACTOR) {
234             diag_printf("mean=%d, ctrs[%d]=%d, err=%d\n", mean, i, ctrs[i],
235                         err);
236             CYG_TEST_FAIL_FINISH("clock() within tolerance");
237         }
238         if (err > maxerr)
239             maxerr=err;
240     }
241
242     diag_printf("mean=%d, maxerr=%d\n", mean, maxerr);
243     CYG_TEST_PASS_FINISH("clock() stable");
244
245 } // main()
246
247 #endif // ifndef NA_MSG
248
249 // EOF clock.c