Mercurial > hg > aboriginal
view sources/patches/linux-noperl-timeconst.patch @ 1619:3413e8427702
The lfs m4 build wasn't including -lrt when probing for posix_spawn, thus trying to recreate what was already there and causing a conflicting definition. Change patch to insert it into libc proper.
author | Rob Landley <rob@landley.net> |
---|---|
date | Fri, 23 Aug 2013 06:02:55 -0500 |
parents | 3cbf1abde44a |
children | 6ffd2181ac58 |
line wrap: on
line source
Replace timeconst.bc with the c version I've been using for years (to replace the perl version). Eventually I should add bc to toybox, but for now... diff --git a/kernel/Makefile b/kernel/Makefile index eceac38..f00be6d 100644 --- /dev/null +++ linux/kernel/mktimeconst.c @@ -0,0 +1,110 @@ +/* Copyright 2010 Parallels Inc, licensed under GPLv2 */ +/* Copyright 2010-2013 Rob Landley <rob@landley.net> */ + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> + +int main(int argc, char *argv[]) +{ + uint64_t hz, periods[] = {1000, 1000000}; + char *names[] = {"MSEC", "USEC"}; + FILE *file; + int i, j; + + if (argc != 3 || (hz = atol(argv[1])) < 1 + || !(file = fopen(argv[2], "w"))) + { + fprintf(stderr, "Usage: mktimeconst HZ FILENAME\n\n"); + fprintf(stderr, "Generate a header file with constants to convert between\n"); + fprintf(stderr, "decimal HZ timer ticks and milisecond or microsecond delays,\n"); + fprintf(stderr, "using reciprocal multiplication to avoid 64 bit division.\n"); + exit(1); + } + + fprintf(file, + "/* Automatically generated by kernel/mktimeconst */\n" + "/* Conversion constants for HZ == %"PRIu64" */\n\n" + "#ifndef __KERNEL_TIMECONST_H\n" + "#define __KERNEL_TIMECONST_H\n\n" + "#include <linux/param.h>\n" + "#include <linux/types.h>\n\n" + "#if HZ != %"PRIu64"\n" + "#error \"kernel/timeconst.h has the wrong HZ value!\"\n" + "#endif\n\n", hz, hz); + + /* Repeat for MSEC and USEC */ + + for (i = 0; i < 2; i++) { + uint64_t gcd, period; + + /* Find greatest common denominator using Euclid's algorithm. */ + + gcd = hz; + period = periods[i]; + while (period) { + uint64_t temp = gcd % period; + gcd = period; + period = temp; + } + + /* Output both directions (HZ_TO_PERIOD and PERIOD_TO_HZ) */ + + for (j = 0; j < 2; j++) { + char name[16]; + uint64_t from = j ? periods[i] : hz; + uint64_t to = j ? hz : periods[i]; + uint64_t mul32 = 0, adj32 = 0, shift = 0; + + sprintf(name, j ? "%s_TO_HZ" : "HZ_TO_%s", names[i]); + + /* Figure out what shift value gives 32 significant + bits of MUL32 data. (Worst case to=1 from=1000000 + uses 52 bits, to<<shift won't overflow 64 bit math.) + */ + + for (;;) { + mul32 = ((to << shift) + from - 1) / from; + if (mul32 >= (1UL<<31)) + break; + shift++; + } + + /* ADJ32 is is just (((FROM/GCD)-1)<<SHIFT)/(FROM/GCD) + but this can overflow 64 bit math (examples, HZ=24 + or HZ=122). Worst case scenario uses 32+20+20=72 + bits. Workaround: split off bottom 32 bits and + reassemble after calculation (32+64=96 bits). */ + + adj32 = from / gcd; + + if (shift > 32) { + uint64_t upper, lower; + + upper = (adj32 - 1) << (shift - 32); + lower = (upper % adj32) << 32; + adj32 = ((upper/adj32) << 32) + (lower/adj32); + } else + adj32 = ((adj32 - 1) << shift) / adj32; + + /* Emit the constants into the header file. */ + + fprintf(file, "#define %s_MUL32\tU64_C(0x%"PRIx64")\n", + name, mul32); + fprintf(file, "#define %s_ADJ32\tU64_C(0x%"PRIx64")\n", + name, adj32); + fprintf(file, "#define %s_SHR32\t%"PRIu64"\n", + name, shift); + fprintf(file, "#define %s_NUM\t\tU64_C(%"PRIu64")\n", + name, to/gcd); + fprintf(file, "#define %s_DEN\t\tU64_C(%"PRIu64")\n\n", + name, from/gcd); + } + } + fprintf(file, "#endif /* __KERNEL_TIMECONST_H */\n"); + + /* Notice if the disk fills up. */ + + fflush(stdout); + return ferror(stdout); +} --- linux/kernel/timeconst.bc 2013-04-28 19:36:01.000000000 -0500 +++ /dev/null 2013-02-23 10:58:11.743993346 -0600 @@ -1,108 +0,0 @@ -scale=0 - -define gcd(a,b) { - auto t; - while (b) { - t = b; - b = a % b; - a = t; - } - return a; -} - -/* Division by reciprocal multiplication. */ -define fmul(b,n,d) { - return (2^b*n+d-1)/d; -} - -/* Adjustment factor when a ceiling value is used. Use as: - (imul * n) + (fmulxx * n + fadjxx) >> xx) */ -define fadj(b,n,d) { - auto v; - d = d/gcd(n,d); - v = 2^b*(d-1)/d; - return v; -} - -/* Compute the appropriate mul/adj values as well as a shift count, - which brings the mul value into the range 2^b-1 <= x < 2^b. Such - a shift value will be correct in the signed integer range and off - by at most one in the upper half of the unsigned range. */ -define fmuls(b,n,d) { - auto s, m; - for (s = 0; 1; s++) { - m = fmul(s,n,d); - if (m >= 2^(b-1)) - return s; - } - return 0; -} - -define timeconst(hz) { - print "/* Automatically generated by kernel/timeconst.bc */\n" - print "/* Time conversion constants for HZ == ", hz, " */\n" - print "\n" - - print "#ifndef KERNEL_TIMECONST_H\n" - print "#define KERNEL_TIMECONST_H\n\n" - - print "#include <linux/param.h>\n" - print "#include <linux/types.h>\n\n" - - print "#if HZ != ", hz, "\n" - print "#error \qkernel/timeconst.h has the wrong HZ value!\q\n" - print "#endif\n\n" - - if (hz < 2) { - print "#error Totally bogus HZ value!\n" - } else { - s=fmuls(32,1000,hz) - obase=16 - print "#define HZ_TO_MSEC_MUL32\tU64_C(0x", fmul(s,1000,hz), ")\n" - print "#define HZ_TO_MSEC_ADJ32\tU64_C(0x", fadj(s,1000,hz), ")\n" - obase=10 - print "#define HZ_TO_MSEC_SHR32\t", s, "\n" - - s=fmuls(32,hz,1000) - obase=16 - print "#define MSEC_TO_HZ_MUL32\tU64_C(0x", fmul(s,hz,1000), ")\n" - print "#define MSEC_TO_HZ_ADJ32\tU64_C(0x", fadj(s,hz,1000), ")\n" - obase=10 - print "#define MSEC_TO_HZ_SHR32\t", s, "\n" - - obase=10 - cd=gcd(hz,1000) - print "#define HZ_TO_MSEC_NUM\t\t", 1000/cd, "\n" - print "#define HZ_TO_MSEC_DEN\t\t", hz/cd, "\n" - print "#define MSEC_TO_HZ_NUM\t\t", hz/cd, "\n" - print "#define MSEC_TO_HZ_DEN\t\t", 1000/cd, "\n" - print "\n" - - s=fmuls(32,1000000,hz) - obase=16 - print "#define HZ_TO_USEC_MUL32\tU64_C(0x", fmul(s,1000000,hz), ")\n" - print "#define HZ_TO_USEC_ADJ32\tU64_C(0x", fadj(s,1000000,hz), ")\n" - obase=10 - print "#define HZ_TO_USEC_SHR32\t", s, "\n" - - s=fmuls(32,hz,1000000) - obase=16 - print "#define USEC_TO_HZ_MUL32\tU64_C(0x", fmul(s,hz,1000000), ")\n" - print "#define USEC_TO_HZ_ADJ32\tU64_C(0x", fadj(s,hz,1000000), ")\n" - obase=10 - print "#define USEC_TO_HZ_SHR32\t", s, "\n" - - obase=10 - cd=gcd(hz,1000000) - print "#define HZ_TO_USEC_NUM\t\t", 1000000/cd, "\n" - print "#define HZ_TO_USEC_DEN\t\t", hz/cd, "\n" - print "#define USEC_TO_HZ_NUM\t\t", hz/cd, "\n" - print "#define USEC_TO_HZ_DEN\t\t", 1000000/cd, "\n" - print "\n" - - print "#endif /* KERNEL_TIMECONST_H */\n" - } - halt -} - -timeconst(hz) --- linux/kernel/Makefile +++ linux/kernel/Makefile @@ -125,19 +125,13 @@ $(obj)/time.o: $(obj)/timeconst.h -quiet_cmd_hzfile = HZFILE $@ - cmd_hzfile = echo "hz=$(CONFIG_HZ)" > $@ - -targets += hz.bc -$(obj)/hz.bc: $(objtree)/include/config/hz.h FORCE - $(call if_changed,hzfile) - -quiet_cmd_bc = BC $@ - cmd_bc = bc -q $(filter-out FORCE,$^) > $@ +hostprogs-y += mktimeconst +quiet_cmd_mktimeconst = TIMEC $@ + cmd_mktimeconst = $(obj)/mktimeconst $(CONFIG_HZ) $@ || ( rm -f $@ && exit 1 ) targets += timeconst.h -$(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE - $(call if_changed,bc) +$(obj)/timeconst.h: $(obj)/mktimeconst FORCE + $(call if_changed,mktimeconst) ifeq ($(CONFIG_MODULE_SIG),y) #