Root/kernel/timeconst.pl

1#!/usr/bin/perl
2# -----------------------------------------------------------------------
3#
4# Copyright 2007-2008 rPath, Inc. - All Rights Reserved
5#
6# This file is part of the Linux kernel, and is made available under
7# the terms of the GNU General Public License version 2 or (at your
8# option) any later version; incorporated herein by reference.
9#
10# -----------------------------------------------------------------------
11#
12
13#
14# Usage: timeconst.pl HZ > timeconst.h
15#
16
17# Precomputed values for systems without Math::BigInt
18# Generated by:
19# timeconst.pl --can 24 32 48 64 100 122 128 200 250 256 300 512 1000 1024 1200
20%canned_values = (
21    24 => [
22        '0xa6aaaaab','0x2aaaaaa',26,
23        125,3,
24        '0xc49ba5e4','0x1fbe76c8b4',37,
25        3,125,
26        '0xa2c2aaab','0xaaaa',16,
27        125000,3,
28        '0xc9539b89','0x7fffbce4217d',47,
29        3,125000,
30    ], 32 => [
31        '0xfa000000','0x6000000',27,
32        125,4,
33        '0x83126e98','0xfdf3b645a',36,
34        4,125,
35        '0xf4240000','0x0',17,
36        31250,1,
37        '0x8637bd06','0x3fff79c842fa',46,
38        1,31250,
39    ], 48 => [
40        '0xa6aaaaab','0x6aaaaaa',27,
41        125,6,
42        '0xc49ba5e4','0xfdf3b645a',36,
43        6,125,
44        '0xa2c2aaab','0x15555',17,
45        62500,3,
46        '0xc9539b89','0x3fffbce4217d',46,
47        3,62500,
48    ], 64 => [
49        '0xfa000000','0xe000000',28,
50        125,8,
51        '0x83126e98','0x7ef9db22d',35,
52        8,125,
53        '0xf4240000','0x0',18,
54        15625,1,
55        '0x8637bd06','0x1fff79c842fa',45,
56        1,15625,
57    ], 100 => [
58        '0xa0000000','0x0',28,
59        10,1,
60        '0xcccccccd','0x733333333',35,
61        1,10,
62        '0x9c400000','0x0',18,
63        10000,1,
64        '0xd1b71759','0x1fff2e48e8a7',45,
65        1,10000,
66    ], 122 => [
67        '0x8325c53f','0xfbcda3a',28,
68        500,61,
69        '0xf9db22d1','0x7fbe76c8b',35,
70        61,500,
71        '0x8012e2a0','0x3ef36',18,
72        500000,61,
73        '0xffda4053','0x1ffffbce4217',45,
74        61,500000,
75    ], 128 => [
76        '0xfa000000','0x1e000000',29,
77        125,16,
78        '0x83126e98','0x3f7ced916',34,
79        16,125,
80        '0xf4240000','0x40000',19,
81        15625,2,
82        '0x8637bd06','0xfffbce4217d',44,
83        2,15625,
84    ], 200 => [
85        '0xa0000000','0x0',29,
86        5,1,
87        '0xcccccccd','0x333333333',34,
88        1,5,
89        '0x9c400000','0x0',19,
90        5000,1,
91        '0xd1b71759','0xfff2e48e8a7',44,
92        1,5000,
93    ], 250 => [
94        '0x80000000','0x0',29,
95        4,1,
96        '0x80000000','0x180000000',33,
97        1,4,
98        '0xfa000000','0x0',20,
99        4000,1,
100        '0x83126e98','0x7ff7ced9168',43,
101        1,4000,
102    ], 256 => [
103        '0xfa000000','0x3e000000',30,
104        125,32,
105        '0x83126e98','0x1fbe76c8b',33,
106        32,125,
107        '0xf4240000','0xc0000',20,
108        15625,4,
109        '0x8637bd06','0x7ffde7210be',43,
110        4,15625,
111    ], 300 => [
112        '0xd5555556','0x2aaaaaaa',30,
113        10,3,
114        '0x9999999a','0x1cccccccc',33,
115        3,10,
116        '0xd0555556','0xaaaaa',20,
117        10000,3,
118        '0x9d495183','0x7ffcb923a29',43,
119        3,10000,
120    ], 512 => [
121        '0xfa000000','0x7e000000',31,
122        125,64,
123        '0x83126e98','0xfdf3b645',32,
124        64,125,
125        '0xf4240000','0x1c0000',21,
126        15625,8,
127        '0x8637bd06','0x3ffef39085f',42,
128        8,15625,
129    ], 1000 => [
130        '0x80000000','0x0',31,
131        1,1,
132        '0x80000000','0x0',31,
133        1,1,
134        '0xfa000000','0x0',22,
135        1000,1,
136        '0x83126e98','0x1ff7ced9168',41,
137        1,1000,
138    ], 1024 => [
139        '0xfa000000','0xfe000000',32,
140        125,128,
141        '0x83126e98','0x7ef9db22',31,
142        128,125,
143        '0xf4240000','0x3c0000',22,
144        15625,16,
145        '0x8637bd06','0x1fff79c842f',41,
146        16,15625,
147    ], 1200 => [
148        '0xd5555556','0xd5555555',32,
149        5,6,
150        '0x9999999a','0x66666666',31,
151        6,5,
152        '0xd0555556','0x2aaaaa',22,
153        2500,3,
154        '0x9d495183','0x1ffcb923a29',41,
155        3,2500,
156    ]
157);
158
159$has_bigint = eval 'use Math::BigInt qw(bgcd); 1;';
160
161sub bint($)
162{
163    my($x) = @_;
164    return Math::BigInt->new($x);
165}
166
167#
168# Constants for division by reciprocal multiplication.
169# (bits, numerator, denominator)
170#
171sub fmul($$$)
172{
173    my ($b,$n,$d) = @_;
174
175    $n = bint($n);
176    $d = bint($d);
177
178    return scalar (($n << $b)+$d-bint(1))/$d;
179}
180
181sub fadj($$$)
182{
183    my($b,$n,$d) = @_;
184
185    $n = bint($n);
186    $d = bint($d);
187
188    $d = $d/bgcd($n, $d);
189    return scalar (($d-bint(1)) << $b)/$d;
190}
191
192sub fmuls($$$) {
193    my($b,$n,$d) = @_;
194    my($s,$m);
195    my($thres) = bint(1) << ($b-1);
196
197    $n = bint($n);
198    $d = bint($d);
199
200    for ($s = 0; 1; $s++) {
201        $m = fmul($s,$n,$d);
202        return $s if ($m >= $thres);
203    }
204    return 0;
205}
206
207# Generate a hex value if the result fits in 64 bits;
208# otherwise skip.
209sub bignum_hex($) {
210    my($x) = @_;
211    my $s = $x->as_hex();
212
213    return (length($s) > 18) ? undef : $s;
214}
215
216# Provides mul, adj, and shr factors for a specific
217# (bit, time, hz) combination
218sub muladj($$$) {
219    my($b, $t, $hz) = @_;
220    my $s = fmuls($b, $t, $hz);
221    my $m = fmul($s, $t, $hz);
222    my $a = fadj($s, $t, $hz);
223    return (bignum_hex($m), bignum_hex($a), $s);
224}
225
226# Provides numerator, denominator values
227sub numden($$) {
228    my($n, $d) = @_;
229    my $g = bgcd($n, $d);
230    return ($n/$g, $d/$g);
231}
232
233# All values for a specific (time, hz) combo
234sub conversions($$) {
235    my ($t, $hz) = @_;
236    my @val = ();
237
238    # HZ_TO_xx
239    push(@val, muladj(32, $t, $hz));
240    push(@val, numden($t, $hz));
241
242    # xx_TO_HZ
243    push(@val, muladj(32, $hz, $t));
244    push(@val, numden($hz, $t));
245
246    return @val;
247}
248
249sub compute_values($) {
250    my($hz) = @_;
251    my @val = ();
252    my $s, $m, $a, $g;
253
254    if (!$has_bigint) {
255        die "$0: HZ == $hz not canned and ".
256            "Math::BigInt not available\n";
257    }
258
259    # MSEC conversions
260    push(@val, conversions(1000, $hz));
261
262    # USEC conversions
263    push(@val, conversions(1000000, $hz));
264
265    return @val;
266}
267
268sub outputval($$)
269{
270    my($name, $val) = @_;
271    my $csuf;
272
273    if (defined($val)) {
274        if ($name !~ /SHR/) {
275        $val = "U64_C($val)";
276        }
277        printf "#define %-23s %s\n", $name.$csuf, $val.$csuf;
278    }
279}
280
281sub output($@)
282{
283    my($hz, @val) = @_;
284    my $pfx, $bit, $suf, $s, $m, $a;
285
286    print "/* Automatically generated by kernel/timeconst.pl */\n";
287    print "/* Conversion constants for HZ == $hz */\n";
288    print "\n";
289    print "#ifndef KERNEL_TIMECONST_H\n";
290    print "#define KERNEL_TIMECONST_H\n";
291    print "\n";
292
293    print "#include <linux/param.h>\n";
294    print "#include <linux/types.h>\n";
295
296    print "\n";
297    print "#if HZ != $hz\n";
298    print "#error \"kernel/timeconst.h has the wrong HZ value!\"\n";
299    print "#endif\n";
300    print "\n";
301
302    foreach $pfx ('HZ_TO_MSEC','MSEC_TO_HZ',
303              'HZ_TO_USEC','USEC_TO_HZ') {
304        foreach $bit (32) {
305            foreach $suf ('MUL', 'ADJ', 'SHR') {
306                outputval("${pfx}_$suf$bit", shift(@val));
307            }
308        }
309        foreach $suf ('NUM', 'DEN') {
310            outputval("${pfx}_$suf", shift(@val));
311        }
312    }
313
314    print "\n";
315    print "#endif /* KERNEL_TIMECONST_H */\n";
316}
317
318# Pretty-print Perl values
319sub perlvals(@) {
320    my $v;
321    my @l = ();
322
323    foreach $v (@_) {
324        if (!defined($v)) {
325            push(@l, 'undef');
326        } elsif ($v =~ /^0x/) {
327            push(@l, "\'".$v."\'");
328        } else {
329            push(@l, $v.'');
330        }
331    }
332    return join(',', @l);
333}
334
335($hz) = @ARGV;
336
337# Use this to generate the %canned_values structure
338if ($hz eq '--can') {
339    shift(@ARGV);
340    @hzlist = sort {$a <=> $b} (@ARGV);
341
342    print "# Precomputed values for systems without Math::BigInt\n";
343    print "# Generated by:\n";
344    print "# timeconst.pl --can ", join(' ', @hzlist), "\n";
345    print "\%canned_values = (\n";
346    my $pf = "\t";
347    foreach $hz (@hzlist) {
348        my @values = compute_values($hz);
349        print "$pf$hz => [\n";
350        while (scalar(@values)) {
351            my $bit;
352            foreach $bit (32) {
353                my $m = shift(@values);
354                my $a = shift(@values);
355                my $s = shift(@values);
356                print "\t\t", perlvals($m,$a,$s), ",\n";
357            }
358            my $n = shift(@values);
359            my $d = shift(@values);
360            print "\t\t", perlvals($n,$d), ",\n";
361        }
362        print "\t]";
363        $pf = ', ';
364    }
365    print "\n);\n";
366} else {
367    $hz += 0; # Force to number
368    if ($hz < 1) {
369        die "Usage: $0 HZ\n";
370    }
371
372    @val = @{$canned_values{$hz}};
373    if (!defined(@val)) {
374        @val = compute_values($hz);
375    }
376    output($hz, @val);
377}
378exit 0;
379

Archive Download this file



interactive