|
@@ -559,17 +559,20 @@ EXPORT_SYMBOL(usecs_to_jiffies);
|
|
|
* that a remainder subtract here would not do the right thing as the
|
|
|
* resolution values don't fall on second boundries. I.e. the line:
|
|
|
* nsec -= nsec % TICK_NSEC; is NOT a correct resolution rounding.
|
|
|
+ * Note that due to the small error in the multiplier here, this
|
|
|
+ * rounding is incorrect for sufficiently large values of tv_nsec, but
|
|
|
+ * well formed timespecs should have tv_nsec < NSEC_PER_SEC, so we're
|
|
|
+ * OK.
|
|
|
*
|
|
|
* Rather, we just shift the bits off the right.
|
|
|
*
|
|
|
* The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec
|
|
|
* value to a scaled second value.
|
|
|
*/
|
|
|
-unsigned long
|
|
|
-timespec_to_jiffies(const struct timespec *value)
|
|
|
+static unsigned long
|
|
|
+__timespec_to_jiffies(unsigned long sec, long nsec)
|
|
|
{
|
|
|
- unsigned long sec = value->tv_sec;
|
|
|
- long nsec = value->tv_nsec + TICK_NSEC - 1;
|
|
|
+ nsec = nsec + TICK_NSEC - 1;
|
|
|
|
|
|
if (sec >= MAX_SEC_IN_JIFFIES){
|
|
|
sec = MAX_SEC_IN_JIFFIES;
|
|
@@ -580,6 +583,13 @@ timespec_to_jiffies(const struct timespec *value)
|
|
|
(NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+unsigned long
|
|
|
+timespec_to_jiffies(const struct timespec *value)
|
|
|
+{
|
|
|
+ return __timespec_to_jiffies(value->tv_sec, value->tv_nsec);
|
|
|
+}
|
|
|
+
|
|
|
EXPORT_SYMBOL(timespec_to_jiffies);
|
|
|
|
|
|
void
|
|
@@ -596,31 +606,27 @@ jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)
|
|
|
}
|
|
|
EXPORT_SYMBOL(jiffies_to_timespec);
|
|
|
|
|
|
-/* Same for "timeval"
|
|
|
- *
|
|
|
- * Well, almost. The problem here is that the real system resolution is
|
|
|
- * in nanoseconds and the value being converted is in micro seconds.
|
|
|
- * Also for some machines (those that use HZ = 1024, in-particular),
|
|
|
- * there is a LARGE error in the tick size in microseconds.
|
|
|
-
|
|
|
- * The solution we use is to do the rounding AFTER we convert the
|
|
|
- * microsecond part. Thus the USEC_ROUND, the bits to be shifted off.
|
|
|
- * Instruction wise, this should cost only an additional add with carry
|
|
|
- * instruction above the way it was done above.
|
|
|
+/*
|
|
|
+ * We could use a similar algorithm to timespec_to_jiffies (with a
|
|
|
+ * different multiplier for usec instead of nsec). But this has a
|
|
|
+ * problem with rounding: we can't exactly add TICK_NSEC - 1 to the
|
|
|
+ * usec value, since it's not necessarily integral.
|
|
|
+ *
|
|
|
+ * We could instead round in the intermediate scaled representation
|
|
|
+ * (i.e. in units of 1/2^(large scale) jiffies) but that's also
|
|
|
+ * perilous: the scaling introduces a small positive error, which
|
|
|
+ * combined with a division-rounding-upward (i.e. adding 2^(scale) - 1
|
|
|
+ * units to the intermediate before shifting) leads to accidental
|
|
|
+ * overflow and overestimates.
|
|
|
+ *
|
|
|
+ * At the cost of one additional multiplication by a constant, just
|
|
|
+ * use the timespec implementation.
|
|
|
*/
|
|
|
unsigned long
|
|
|
timeval_to_jiffies(const struct timeval *value)
|
|
|
{
|
|
|
- unsigned long sec = value->tv_sec;
|
|
|
- long usec = value->tv_usec;
|
|
|
-
|
|
|
- if (sec >= MAX_SEC_IN_JIFFIES){
|
|
|
- sec = MAX_SEC_IN_JIFFIES;
|
|
|
- usec = 0;
|
|
|
- }
|
|
|
- return (((u64)sec * SEC_CONVERSION) +
|
|
|
- (((u64)usec * USEC_CONVERSION + USEC_ROUND) >>
|
|
|
- (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
|
|
|
+ return __timespec_to_jiffies(value->tv_sec,
|
|
|
+ value->tv_usec * NSEC_PER_USEC);
|
|
|
}
|
|
|
EXPORT_SYMBOL(timeval_to_jiffies);
|
|
|
|