Blame view

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