Mercurial > hg > aboriginal
annotate sources/patches/linux-noperl-timeconst.patch @ 1817:92d542aa6ceb draft
Teach system-image.sh to handle its own dependencies, rebuilding kernel and
repackaging cpio/squashfs as appropraite, and _not_ doing so when unneeded.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sun, 22 Nov 2015 14:54:16 -0600 |
parents | db11c049b66b |
children |
rev | line source |
---|---|
1598 | 1 Replace timeconst.bc with the c version I've been using for years (to replace |
2 the perl version). Eventually I should add bc to toybox, but for now... | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
3 |
1698 | 4 --- linux/kernel/time/timeconst.bc 2013-04-28 19:36:01.000000000 -0500 |
1598 | 5 +++ /dev/null 2013-02-23 10:58:11.743993346 -0600 |
1813 | 6 @@ -1,109 +0,0 @@ |
1598 | 7 -scale=0 |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
8 - |
1598 | 9 -define gcd(a,b) { |
10 - auto t; | |
11 - while (b) { | |
12 - t = b; | |
13 - b = a % b; | |
14 - a = t; | |
15 - } | |
16 - return a; | |
17 -} | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
18 - |
1598 | 19 -/* Division by reciprocal multiplication. */ |
20 -define fmul(b,n,d) { | |
21 - return (2^b*n+d-1)/d; | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
22 -} |
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
23 - |
1598 | 24 -/* Adjustment factor when a ceiling value is used. Use as: |
25 - (imul * n) + (fmulxx * n + fadjxx) >> xx) */ | |
26 -define fadj(b,n,d) { | |
27 - auto v; | |
28 - d = d/gcd(n,d); | |
29 - v = 2^b*(d-1)/d; | |
30 - return v; | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
31 -} |
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
32 - |
1598 | 33 -/* Compute the appropriate mul/adj values as well as a shift count, |
34 - which brings the mul value into the range 2^b-1 <= x < 2^b. Such | |
35 - a shift value will be correct in the signed integer range and off | |
36 - by at most one in the upper half of the unsigned range. */ | |
37 -define fmuls(b,n,d) { | |
38 - auto s, m; | |
39 - for (s = 0; 1; s++) { | |
40 - m = fmul(s,n,d); | |
41 - if (m >= 2^(b-1)) | |
42 - return s; | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
43 - } |
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
44 - return 0; |
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
45 -} |
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
46 - |
1598 | 47 -define timeconst(hz) { |
48 - print "/* Automatically generated by kernel/timeconst.bc */\n" | |
49 - print "/* Time conversion constants for HZ == ", hz, " */\n" | |
50 - print "\n" | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
51 - |
1598 | 52 - print "#ifndef KERNEL_TIMECONST_H\n" |
53 - print "#define KERNEL_TIMECONST_H\n\n" | |
54 - | |
55 - print "#include <linux/param.h>\n" | |
56 - print "#include <linux/types.h>\n\n" | |
57 - | |
58 - print "#if HZ != ", hz, "\n" | |
1813 | 59 - print "#error \qinclude/generated/timeconst.h has the wrong HZ value!\q\n" |
1598 | 60 - print "#endif\n\n" |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
61 - |
1598 | 62 - if (hz < 2) { |
63 - print "#error Totally bogus HZ value!\n" | |
64 - } else { | |
65 - s=fmuls(32,1000,hz) | |
66 - obase=16 | |
67 - print "#define HZ_TO_MSEC_MUL32\tU64_C(0x", fmul(s,1000,hz), ")\n" | |
68 - print "#define HZ_TO_MSEC_ADJ32\tU64_C(0x", fadj(s,1000,hz), ")\n" | |
69 - obase=10 | |
70 - print "#define HZ_TO_MSEC_SHR32\t", s, "\n" | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
71 - |
1598 | 72 - s=fmuls(32,hz,1000) |
73 - obase=16 | |
74 - print "#define MSEC_TO_HZ_MUL32\tU64_C(0x", fmul(s,hz,1000), ")\n" | |
75 - print "#define MSEC_TO_HZ_ADJ32\tU64_C(0x", fadj(s,hz,1000), ")\n" | |
76 - obase=10 | |
77 - print "#define MSEC_TO_HZ_SHR32\t", s, "\n" | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
78 - |
1598 | 79 - obase=10 |
80 - cd=gcd(hz,1000) | |
81 - print "#define HZ_TO_MSEC_NUM\t\t", 1000/cd, "\n" | |
82 - print "#define HZ_TO_MSEC_DEN\t\t", hz/cd, "\n" | |
83 - print "#define MSEC_TO_HZ_NUM\t\t", hz/cd, "\n" | |
84 - print "#define MSEC_TO_HZ_DEN\t\t", 1000/cd, "\n" | |
85 - print "\n" | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
86 - |
1598 | 87 - s=fmuls(32,1000000,hz) |
88 - obase=16 | |
89 - print "#define HZ_TO_USEC_MUL32\tU64_C(0x", fmul(s,1000000,hz), ")\n" | |
90 - print "#define HZ_TO_USEC_ADJ32\tU64_C(0x", fadj(s,1000000,hz), ")\n" | |
91 - obase=10 | |
92 - print "#define HZ_TO_USEC_SHR32\t", s, "\n" | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
93 - |
1598 | 94 - s=fmuls(32,hz,1000000) |
95 - obase=16 | |
96 - print "#define USEC_TO_HZ_MUL32\tU64_C(0x", fmul(s,hz,1000000), ")\n" | |
97 - print "#define USEC_TO_HZ_ADJ32\tU64_C(0x", fadj(s,hz,1000000), ")\n" | |
98 - obase=10 | |
99 - print "#define USEC_TO_HZ_SHR32\t", s, "\n" | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
100 - |
1598 | 101 - obase=10 |
102 - cd=gcd(hz,1000000) | |
103 - print "#define HZ_TO_USEC_NUM\t\t", 1000000/cd, "\n" | |
104 - print "#define HZ_TO_USEC_DEN\t\t", hz/cd, "\n" | |
105 - print "#define USEC_TO_HZ_NUM\t\t", hz/cd, "\n" | |
106 - print "#define USEC_TO_HZ_DEN\t\t", 1000000/cd, "\n" | |
107 - print "\n" | |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
108 - |
1598 | 109 - print "#endif /* KERNEL_TIMECONST_H */\n" |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
110 - } |
1598 | 111 - halt |
1337
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
112 -} |
1bc0c01950ca
Switch to the noperl patches for 2.6.38.
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
113 - |
1813 | 114 -hz = read(); |
1598 | 115 -timeconst(hz) |
1813 | 116 diff --git a/Kbuild b/Kbuild |
117 index f55cefd..e412515 100644 | |
118 --- a/Kbuild | |
119 +++ b/Kbuild | |
120 @@ -53,16 +53,18 @@ $(obj)/$(bounds-file): kernel/bounds.s FORCE | |
121 timeconst-file := include/generated/timeconst.h | |
122 | |
123 targets += $(timeconst-file) | |
124 +hostprogs-y += mktimeconst | |
125 +mktimeconst-objs = kernel/time/mktimeconst.o | |
1598 | 126 |
1813 | 127 quiet_cmd_gentimeconst = GEN $@ |
128 define cmd_gentimeconst | |
129 - (echo $(CONFIG_HZ) | bc -q $< ) > $@ | |
130 + $(obj)/mktimeconst $(CONFIG_HZ) $@ | |
131 endef | |
132 define filechk_gentimeconst | |
133 - (echo $(CONFIG_HZ) | bc -q $< ) | |
134 + $(obj)/mktimeconst $(CONFIG_HZ) - | |
135 endef | |
136 | |
137 -$(obj)/$(timeconst-file): kernel/time/timeconst.bc FORCE | |
138 +$(obj)/$(timeconst-file): $(obj)/mktimeconst FORCE | |
139 $(call filechk,gentimeconst) | |
1598 | 140 |
1813 | 141 ##### |
142 --- /dev/null | |
143 +++ b/kernel/time/mktimeconst.c | |
144 @@ -0,0 +1,110 @@ | |
145 + /* Copyright 2010-2013 Rob Landley <rob@landley.net> */ | |
146 + | |
147 + #include <inttypes.h> | |
148 + #include <stdio.h> | |
149 + #include <stdlib.h> | |
150 + #include <string.h> | |
151 + | |
152 + int main(int argc, char *argv[]) | |
153 + { | |
154 + uint64_t hz, periods[] = {1000, 1000000}; | |
155 + char *names[] = {"MSEC", "USEC"}; | |
156 + FILE *file; | |
157 + int i, j; | |
158 + | |
159 + if (argc != 3 || (hz = atol(argv[1])) < 1 | |
160 + || !(file = !strcmp(argv[2], "-") ? stdout : fopen(argv[2], "w"))) | |
161 + { | |
162 + fprintf(stderr, "Usage: mktimeconst HZ FILENAME\n\n"); | |
163 + fprintf(stderr, "Generate a header file with constants to convert between\n"); | |
164 + fprintf(stderr, "decimal HZ timer ticks and milisecond or microsecond delays,\n"); | |
165 + fprintf(stderr, "using reciprocal multiplication to avoid 64 bit division.\n"); | |
166 + exit(1); | |
167 + } | |
168 + | |
169 + fprintf(file, | |
170 + "/* Automatically generated by kernel/mktimeconst */\n" | |
171 + "/* Conversion constants for HZ == %"PRIu64" */\n\n" | |
172 + "#ifndef __KERNEL_TIMECONST_H\n" | |
173 + "#define __KERNEL_TIMECONST_H\n\n" | |
174 + "#include <linux/param.h>\n" | |
175 + "#include <linux/types.h>\n\n" | |
176 + "#if HZ != %"PRIu64"\n" | |
177 + "#error \"include/generated/timeconst.h has the wrong HZ value!\"\n" | |
178 + "#endif\n\n", hz, hz); | |
179 + | |
180 + /* Repeat for MSEC and USEC */ | |
181 + | |
182 + for (i = 0; i < 2; i++) { | |
183 + uint64_t gcd, period; | |
184 + | |
185 + /* Find greatest common denominator using Euclid's algorithm. */ | |
186 + | |
187 + gcd = hz; | |
188 + period = periods[i]; | |
189 + while (period) { | |
190 + uint64_t temp = gcd % period; | |
191 + gcd = period; | |
192 + period = temp; | |
193 + } | |
194 + | |
195 + /* Output both directions (HZ_TO_PERIOD and PERIOD_TO_HZ) */ | |
196 + | |
197 + for (j = 0; j < 2; j++) { | |
198 + char name[16]; | |
199 + uint64_t from = j ? periods[i] : hz; | |
200 + uint64_t to = j ? hz : periods[i]; | |
201 + uint64_t mul32 = 0, adj32 = 0, shift = 0; | |
202 + | |
203 + sprintf(name, j ? "%s_TO_HZ" : "HZ_TO_%s", names[i]); | |
204 + | |
205 + /* Figure out what shift value gives 32 significant | |
206 + bits of MUL32 data. (Worst case to=1 from=1000000 | |
207 + uses 52 bits, to<<shift won't overflow 64 bit math.) | |
208 + */ | |
209 + | |
210 + for (;;) { | |
211 + mul32 = ((to << shift) + from - 1) / from; | |
212 + if (mul32 >= (1UL<<31)) | |
213 + break; | |
214 + shift++; | |
215 + } | |
216 + | |
217 + /* ADJ32 is is just (((FROM/GCD)-1)<<SHIFT)/(FROM/GCD) | |
218 + but this can overflow 64 bit math (examples, HZ=24 | |
219 + or HZ=122). Worst case scenario uses 32+20+20=72 | |
220 + bits. Workaround: split off bottom 32 bits and | |
221 + reassemble after calculation (32+64=96 bits). */ | |
222 + | |
223 + adj32 = from / gcd; | |
224 + | |
225 + if (shift > 32) { | |
226 + uint64_t upper, lower; | |
227 + | |
228 + upper = (adj32 - 1) << (shift - 32); | |
229 + lower = (upper % adj32) << 32; | |
230 + adj32 = ((upper/adj32) << 32) + (lower/adj32); | |
231 + } else | |
232 + adj32 = ((adj32 - 1) << shift) / adj32; | |
233 + | |
234 + /* Emit the constants into the header file. */ | |
235 + | |
236 + fprintf(file, "#define %s_MUL32\tU64_C(0x%"PRIx64")\n", | |
237 + name, mul32); | |
238 + fprintf(file, "#define %s_ADJ32\tU64_C(0x%"PRIx64")\n", | |
239 + name, adj32); | |
240 + fprintf(file, "#define %s_SHR32\t%"PRIu64"\n", | |
241 + name, shift); | |
242 + fprintf(file, "#define %s_NUM\t\tU64_C(%"PRIu64")\n", | |
243 + name, to/gcd); | |
244 + fprintf(file, "#define %s_DEN\t\tU64_C(%"PRIu64")\n\n", | |
245 + name, from/gcd); | |
246 + } | |
247 + } | |
248 + fprintf(file, "#endif /* __KERNEL_TIMECONST_H */\n"); | |
249 + | |
250 + /* Notice if the disk fills up. */ | |
251 + | |
252 + fflush(file); | |
253 + return ferror(file); | |
254 + } |