Skip to contentSkip to conversation

getmonotonictime system call and patch for evdev to use such time

PATCH In review Michal Maruška 2 participants 2 messages Jun 19, 2005

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 getmonotonictime system call and patch for evdev to use such time

Events from the evdev device are timestamped with gettimeofday. If a userland application wants to see a duration of a key press, all it can do is look at the 2 timestamps.

If settimeofday is called in between, it will see a false duration, which is not what it needs. So, for my needs I only want the monotonic (since boot) time. I understand, that someone else might want to maintain compatibility, and have the kind of time selectable (ioctl), but that's above my current kernel knowledge.

If no event arrives I would still like to measure the progressed duration, and thus get the monotonic time, so a system call getmonotonictime is needed.

I found do_posix_clock_monotonic_gettime and made simple wrapper around it. I do NOT claim i know how to add a new system call! And it's i386 only.

All i did is testing with simple:

   struct timeval  tp;
   syscall(289, &tv);
arch/i386/kernel/syscall_table.S +1 -0
@@ -289,3 +289,4 @@
 	.long sys_add_key
 	.long sys_request_key
 	.long sys_keyctl
+        .long sys_getmonotonictime
drivers/input/evdev.c +2 -2
@@ -52,7 +52,7 @@
 	if (evdev->grab) {
 		list = evdev->grab;
 
-		do_gettimeofday(&list->buffer[list->head].time);
+		do_getmonotonictime(&list->buffer[list->head].time);
 		list->buffer[list->head].type = type;
 		list->buffer[list->head].code = code;
 		list->buffer[list->head].value = value;
@@ -62,7 +62,7 @@
 	} else
 		list_for_each_entry(list, &evdev->list, node) {
 
-			do_gettimeofday(&list->buffer[list->head].time);
+			do_getmonotonictime(&list->buffer[list->head].time);
 			list->buffer[list->head].type = type;
 			list->buffer[list->head].code = code;
 			list->buffer[list->head].value = value;
include/linux/time.h +1 -0
@@ -92,6 +92,7 @@
 #define CURRENT_TIME (current_kernel_time())
 #define CURRENT_TIME_SEC ((struct timespec) { xtime.tv_sec, 0 })
 
+extern void do_getmonotonictime (struct timeval *tv);
 extern void do_gettimeofday(struct timeval *tv);
 extern int do_settimeofday(struct timespec *tv);
 extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
kernel/time.c +31 -1
@@ -5,7 +5,7 @@
  *
  *  This file contains the interface functions for the various
  *  time related system calls: time, stime, gettimeofday, settimeofday,
- *			       adjtime
+ *			       adjtime, getmonotonictime
  */
 /*
  * Modification history kernel/time.c
@@ -25,6 +25,9 @@
  * 2004-07-14	 Christoph Lameter
  *	Added getnstimeofday to allow the posix timer functions to return
  *	with nanosecond accuracy
+ * 2005-06-19  Michal Maruska
+ *      Added getmonotonictime to provide time and (input event) timestamps
+ *      independent of time changes (settimeofday)
  */
 
 #include <linux/module.h>
@@ -112,6 +115,33 @@
 	return 0;
 }
 
+asmlinkage long sys_getmonotonictime(struct timeval __user *tv)
+{
+	if (likely(tv != NULL)) {
+		struct timeval ktv;
+		do_getmonotonictime(&ktv);
+		/* indeed it works! */
+		/* printk("%s\n", __FUNCTION__); */
+		if (copy_to_user(tv, &ktv, sizeof(ktv)))
+			return -EFAULT; 
+	}
+	return 0;
+}
+
+
+void do_getmonotonictime (struct timeval *tv)
+{
+	struct timespec kts;
+        if (unlikely(tv == NULL)) return;        /* should not happen */
+           
+	do_posix_clock_monotonic_gettime(&kts);
+	/* transform the "struct timespec" into  "struct timeval" */
+	tv->tv_sec = kts.tv_sec;
+	tv->tv_usec = kts.tv_nsec / NSEC_PER_USEC;
+}
+
+EXPORT_SYMBOL(do_getmonotonictime);
+
 /*
  * Adjust the time obtained from the CMOS to be UTC time instead of
  * local time.
#1 lore raw
Quoted 2 lines · Michal Maruška

I found do_posix_clock_monotonic_gettime and made simple wrapper around it. I do NOT claim i know how to add a new system call! And it's i386 only.

There is a system call already.

man clock_gettime

tglx