浏览代码

some preliminaries for vdso clock support

these changes also make it so clock_gettime(CLOCK_REALTIME, &ts) works
even on pre-2.6 kernels, emulated via the gettimeofday syscall. there
is no cost for the fallback check, as it falls under the error case
that already must be checked for storing the error code in errno, but
which would normally be hidden inside __syscall_ret.
Rich Felker 13 年之前
父节点
当前提交
e3eb49321c
共有 3 个文件被更改,包括 35 次插入7 次删除
  1. 23 2
      src/time/clock_gettime.c
  2. 6 1
      src/time/gettimeofday.c
  3. 6 4
      src/time/time.c

+ 23 - 2
src/time/clock_gettime.c

@@ -1,7 +1,28 @@
 #include <time.h>
 #include <time.h>
+#include <errno.h>
+#include <stdint.h>
 #include "syscall.h"
 #include "syscall.h"
+#include "libc.h"
 
 
-int clock_gettime(clockid_t clk, struct timespec *ts)
+int __vdso_clock_gettime(clockid_t, struct timespec *) __attribute__((weak));
+static int (*cgt)(clockid_t, struct timespec *) = __vdso_clock_gettime;
+
+int __clock_gettime(clockid_t clk, struct timespec *ts)
 {
 {
-	return syscall(SYS_clock_gettime, clk, ts);
+	int r;
+	if (cgt) return cgt(clk, ts);
+	r = __syscall(SYS_clock_gettime, clk, ts);
+	if (!r) return r;
+	if (r == -ENOSYS) {
+		if (clk == CLOCK_REALTIME) {
+			__syscall(SYS_gettimeofday, clk, ts, 0);
+			ts->tv_nsec = (int)ts->tv_nsec * 1000;
+			return 0;
+		}
+		r = -EINVAL;
+	}
+	errno = -r;
+	return -1;
 }
 }
+
+weak_alias(__clock_gettime, clock_gettime);

+ 6 - 1
src/time/gettimeofday.c

@@ -1,8 +1,13 @@
+#include <time.h>
 #include <sys/time.h>
 #include <sys/time.h>
 #include "syscall.h"
 #include "syscall.h"
 
 
 int gettimeofday(struct timeval *tv, void *tz)
 int gettimeofday(struct timeval *tv, void *tz)
 {
 {
-	__syscall(SYS_gettimeofday, tv, 0);
+	struct timespec ts;
+	if (!tv) return 0;
+	clock_gettime(CLOCK_REALTIME, &ts);
+	tv->tv_sec = ts.tv_sec;
+	tv->tv_usec = (int)ts.tv_nsec / 1000;
 	return 0;
 	return 0;
 }
 }

+ 6 - 4
src/time/time.c

@@ -2,10 +2,12 @@
 #include <sys/time.h>
 #include <sys/time.h>
 #include "syscall.h"
 #include "syscall.h"
 
 
+int __clock_gettime(clockid_t, struct timespec *);
+
 time_t time(time_t *t)
 time_t time(time_t *t)
 {
 {
-	struct timeval tv;
-	__syscall(SYS_gettimeofday, &tv, 0);
-	if (t) *t = tv.tv_sec;
-	return tv.tv_sec;
+	struct timespec ts;
+	__clock_gettime(CLOCK_REALTIME, &ts);
+	if (t) *t = ts.tv_sec;
+	return ts.tv_sec;
 }
 }