* [PATCH] isdn: Use ktime_t instead of 'struct timeval'
@ 2015-05-11 2:32 Tina Ruchandani
2015-05-11 15:31 ` Arnd Bergmann
0 siblings, 1 reply; 2+ messages in thread
From: Tina Ruchandani @ 2015-05-11 2:32 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Karsten Keil, netdev, y2038
'struct timeval' uses 32-bit representation for seconds which will
overflow in year 2038 and beyond. mISDN/clock.c needs to compute and
store elapsed time in intervals of 125 microseconds. This patch replaces
the usage of 'struct timeval' with 64-bit ktime_t which is y2038 safe.
The patch also replaces use of wall-clock time (do_gettimeofday) with
monotonic time (ktime_get) since we only care about elapsed time here.
Signed-off-by: Tina Ruchandani <ruchandani.tina@gmail.com>
---
drivers/isdn/mISDN/clock.c | 53 +++++++++++++++++-----------------------------
include/linux/mISDNif.h | 2 +-
2 files changed, 21 insertions(+), 34 deletions(-)
diff --git a/drivers/isdn/mISDN/clock.c b/drivers/isdn/mISDN/clock.c
index 693fb7c..7550f2e 100644
--- a/drivers/isdn/mISDN/clock.c
+++ b/drivers/isdn/mISDN/clock.c
@@ -37,6 +37,7 @@
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/spinlock.h>
+#include <linux/ktime.h>
#include <linux/mISDNif.h>
#include <linux/export.h>
#include "core.h"
@@ -45,7 +46,7 @@ static u_int *debug;
static LIST_HEAD(iclock_list);
static DEFINE_RWLOCK(iclock_lock);
static u16 iclock_count; /* counter of last clock */
-static struct timeval iclock_tv; /* time stamp of last clock */
+static ktime_t iclock_tv; /* time stamp of last clock */
static int iclock_tv_valid; /* already received one timestamp */
static struct mISDNclock *iclock_current;
@@ -53,7 +54,7 @@ void
mISDN_init_clock(u_int *dp)
{
debug = dp;
- do_gettimeofday(&iclock_tv);
+ iclock_tv = ktime_get();
}
static void
@@ -139,12 +140,11 @@ mISDN_unregister_clock(struct mISDNclock *iclock)
EXPORT_SYMBOL(mISDN_unregister_clock);
void
-mISDN_clock_update(struct mISDNclock *iclock, int samples, struct timeval *tv)
+mISDN_clock_update(struct mISDNclock *iclock, int samples, ktime_t *tv)
{
u_long flags;
- struct timeval tv_now;
- time_t elapsed_sec;
- int elapsed_8000th;
+ ktime_t tv_now;
+ u16 delta;
write_lock_irqsave(&iclock_lock, flags);
if (iclock_current != iclock) {
@@ -160,28 +160,20 @@ mISDN_clock_update(struct mISDNclock *iclock, int samples, struct timeval *tv)
/* increment sample counter by given samples */
iclock_count += samples;
if (tv) { /* tv must be set, if function call is delayed */
- iclock_tv.tv_sec = tv->tv_sec;
- iclock_tv.tv_usec = tv->tv_usec;
+ iclock_tv = *tv;
} else
- do_gettimeofday(&iclock_tv);
+ iclock_tv = ktime_get();
} else {
/* calc elapsed time by system clock */
if (tv) { /* tv must be set, if function call is delayed */
- tv_now.tv_sec = tv->tv_sec;
- tv_now.tv_usec = tv->tv_usec;
+ tv_now = *tv;
} else
- do_gettimeofday(&tv_now);
- elapsed_sec = tv_now.tv_sec - iclock_tv.tv_sec;
- elapsed_8000th = (tv_now.tv_usec / 125)
- - (iclock_tv.tv_usec / 125);
- if (elapsed_8000th < 0) {
- elapsed_sec -= 1;
- elapsed_8000th += 8000;
- }
+ tv_now = ktime_get();
+ delta = ktime_to_us(ktime_sub(tv_now, iclock_tv));
+ delta = delta / 125;
/* add elapsed time to counter and set new timestamp */
- iclock_count += elapsed_sec * 8000 + elapsed_8000th;
- iclock_tv.tv_sec = tv_now.tv_sec;
- iclock_tv.tv_usec = tv_now.tv_usec;
+ iclock_count += delta;
+ iclock_tv = tv_now;
iclock_tv_valid = 1;
if (*debug & DEBUG_CLOCK)
printk("Received first clock from source '%s'.\n",
@@ -195,22 +187,17 @@ unsigned short
mISDN_clock_get(void)
{
u_long flags;
- struct timeval tv_now;
- time_t elapsed_sec;
- int elapsed_8000th;
+ ktime_t tv_now;
+ u16 delta;
u16 count;
read_lock_irqsave(&iclock_lock, flags);
/* calc elapsed time by system clock */
- do_gettimeofday(&tv_now);
- elapsed_sec = tv_now.tv_sec - iclock_tv.tv_sec;
- elapsed_8000th = (tv_now.tv_usec / 125) - (iclock_tv.tv_usec / 125);
- if (elapsed_8000th < 0) {
- elapsed_sec -= 1;
- elapsed_8000th += 8000;
- }
+ tv_now = ktime_get();
+ delta = ktime_to_us(ktime_sub(tv_now, iclock_tv));
+ delta = delta / 125;
/* add elapsed time to counter */
- count = iclock_count + elapsed_sec * 8000 + elapsed_8000th;
+ count = iclock_count + delta;
read_unlock_irqrestore(&iclock_lock, flags);
return count;
}
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index 246a352..ac02c54 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -596,7 +596,7 @@ static inline struct mISDNdevice *dev_to_mISDN(struct device *dev)
}
extern void set_channel_address(struct mISDNchannel *, u_int, u_int);
-extern void mISDN_clock_update(struct mISDNclock *, int, struct timeval *);
+extern void mISDN_clock_update(struct mISDNclock *, int, ktime_t *);
extern unsigned short mISDN_clock_get(void);
extern const char *mISDNDevName4ch(struct mISDNchannel *);
--
2.2.0.rc0.207.ga3a616c
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] isdn: Use ktime_t instead of 'struct timeval'
2015-05-11 2:32 [PATCH] isdn: Use ktime_t instead of 'struct timeval' Tina Ruchandani
@ 2015-05-11 15:31 ` Arnd Bergmann
0 siblings, 0 replies; 2+ messages in thread
From: Arnd Bergmann @ 2015-05-11 15:31 UTC (permalink / raw)
To: Tina Ruchandani; +Cc: Karsten Keil, netdev, y2038
On Monday 11 May 2015 08:02:57 Tina Ruchandani wrote:
> - do_gettimeofday(&tv_now);
> - elapsed_sec = tv_now.tv_sec - iclock_tv.tv_sec;
> - elapsed_8000th = (tv_now.tv_usec / 125)
> - - (iclock_tv.tv_usec / 125);
> - if (elapsed_8000th < 0) {
> - elapsed_sec -= 1;
> - elapsed_8000th += 8000;
> - }
> + tv_now = ktime_get();
A minor coding style comment here: If you have a multi-line
block after if() using curly braces, then you should also use
that for the else path, even if that is just one line.
However, if both sides do not need curly braces, leave them
out entirely.
> + delta = ktime_to_us(ktime_sub(tv_now, iclock_tv));
We have a ktime_us_delta() function now that would simplify this
slightly.
> + delta = delta / 125;
This looks like a possible bug: delta is a 16-bit number, so it will
be truncated to 65536 microseconds when assigning the result of
ktime_us_delta() or ktime_to_us(), and then you divide by 125, so
it will now be a number that is smaller than 524, and if the elapsed
time is more than 65536 microseconds, you can an incorrect result.
You can avoid that by using a 32-bit temporary, or doing it
implicitly as
delta = ktime_us_delta(tv_now, iclock_tv) / 125;
Another option would be to calculate the right number from the
nanoseconds:
delta = ktime_divns(ktime_sub(tv_now, iclock_tv), (NS_PER_SEC / 8000));
Arnd
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2015-05-11 15:31 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-11 2:32 [PATCH] isdn: Use ktime_t instead of 'struct timeval' Tina Ruchandani
2015-05-11 15:31 ` Arnd Bergmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).