Submitted By:            Igor Živković
Date:                    2014-07-26
Initial Package Version: 3.15.6
Upstream Status:         Unknown
Origin:                  sabotage
Description:             Replaces timeconst.bc with the C version thus removing
                         dependency on bc.

diff -Naur linux-3.15.6.orig/kernel/Makefile linux-3.15.6/kernel/Makefile
--- linux-3.15.6.orig/kernel/Makefile	2014-07-18 01:23:31.000000000 +0200
+++ linux-3.15.6/kernel/Makefile	2014-07-26 18:27:22.773033796 +0200
@@ -112,19 +112,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)
 
 ###############################################################################
 #
diff -Naur linux-3.15.6.orig/kernel/mktimeconst.c linux-3.15.6/kernel/mktimeconst.c
--- linux-3.15.6.orig/kernel/mktimeconst.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-3.15.6/kernel/mktimeconst.c	2014-07-26 18:26:45.490575624 +0200
@@ -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);
+}
