gettimeofday: gather variables into new struct

This commit is contained in:
NAKAMURA Gou
2015-11-11 17:19:10 +09:00
parent 4c181d7fc0
commit 1a5ff7f535
3 changed files with 37 additions and 26 deletions

View File

@@ -13,6 +13,7 @@
#ifndef __HEADER_SYSCALL_H #ifndef __HEADER_SYSCALL_H
#define __HEADER_SYSCALL_H #define __HEADER_SYSCALL_H
#include <ihk/atomic.h>
#include <ihk/context.h> #include <ihk/context.h>
#include <ihk/memconst.h> #include <ihk/memconst.h>
#include <rlimit.h> #include <rlimit.h>
@@ -288,8 +289,13 @@ struct procfs_file {
extern void terminate(int, int); extern void terminate(int, int);
/* kernel/syscall.c */ struct tod_data_s {
extern struct timespec origin_ts; /* realtime when tsc=0 */ int8_t do_local;
extern unsigned long clocks_per_sec; int8_t padding[7];
ihk_atomic64_t version;
unsigned long clocks_per_sec;
struct timespec origin; /* realtime when tsc=0 */
};
extern struct tod_data_s tod_data;
#endif #endif

View File

@@ -211,16 +211,20 @@ static void time_init(void)
ihk_mc_get_boot_time(&tv_sec, &tv_nsec); ihk_mc_get_boot_time(&tv_sec, &tv_nsec);
ns_per_kclock = ihk_mc_get_ns_per_tsc(); ns_per_kclock = ihk_mc_get_ns_per_tsc();
origin_ts.tv_sec = tv_sec; tod_data.origin.tv_sec = tv_sec;
origin_ts.tv_nsec = tv_nsec; tod_data.origin.tv_nsec = tv_nsec;
if (ns_per_kclock) { if (ns_per_kclock) {
clocks_per_sec = (1000L * NS_PER_SEC) / ns_per_kclock; tod_data.clocks_per_sec = (1000L * NS_PER_SEC) / ns_per_kclock;
} }
if (!ns_per_kclock) { if (!ns_per_kclock) {
gettime_local_support = 0; gettime_local_support = 0;
} }
if (gettime_local_support) {
tod_data.do_local = 1;
}
return; return;
} }

View File

@@ -95,10 +95,11 @@ static char *syscall_name[] MCKERNEL_UNUSED = {
#undef SYSCALL_DELEGATED #undef SYSCALL_DELEGATED
}; };
struct timespec origin_ts; struct tod_data_s tod_data = {
static ihk_spinlock_t origin_ts_lock = SPIN_LOCK_UNLOCKED; .do_local = 0,
ihk_atomic64_t origin_ts_version = IHK_ATOMIC64_INIT(0); .version = IHK_ATOMIC64_INIT(0),
unsigned long clocks_per_sec; };
static ihk_spinlock_t tod_data_lock = SPIN_LOCK_UNLOCKED;
void check_signal(unsigned long, void *, int); void check_signal(unsigned long, void *, int);
void do_signal(long rc, void *regs, struct thread *thread, struct sig_pending *pending, int num); void do_signal(long rc, void *regs, struct thread *thread, struct sig_pending *pending, int num);
@@ -4825,14 +4826,14 @@ static void calculate_time_from_tsc(struct timespec *ts)
long ns_delta; long ns_delta;
for (;;) { for (;;) {
while ((ver = ihk_atomic64_read(&origin_ts_version)) & 1) { while ((ver = ihk_atomic64_read(&tod_data.version)) & 1) {
/* settimeofday() is in progress */ /* settimeofday() is in progress */
cpu_pause(); cpu_pause();
} }
rmb(); rmb();
*ts = origin_ts; *ts = tod_data.origin;
rmb(); rmb();
if (ver == ihk_atomic64_read(&origin_ts_version)) { if (ver == ihk_atomic64_read(&tod_data.version)) {
break; break;
} }
@@ -4841,9 +4842,9 @@ static void calculate_time_from_tsc(struct timespec *ts)
} }
current_tsc = rdtsc(); current_tsc = rdtsc();
sec_delta = current_tsc / clocks_per_sec; sec_delta = current_tsc / tod_data.clocks_per_sec;
ns_delta = NS_PER_SEC * (current_tsc % clocks_per_sec) ns_delta = NS_PER_SEC * (current_tsc % tod_data.clocks_per_sec)
/ clocks_per_sec; / tod_data.clocks_per_sec;
/* calc. of ns_delta overflows if clocks_per_sec exceeds 18.44 GHz */ /* calc. of ns_delta overflows if clocks_per_sec exceeds 18.44 GHz */
ts->tv_sec += sec_delta; ts->tv_sec += sec_delta;
@@ -4902,8 +4903,8 @@ SYSCALL_DECLARE(settimeofday)
unsigned long tsc; unsigned long tsc;
dkprintf("sys_settimeofday(%p,%p)\n", utv, utz); dkprintf("sys_settimeofday(%p,%p)\n", utv, utz);
ihk_mc_spinlock_lock_noirq(&origin_ts_lock); ihk_mc_spinlock_lock_noirq(&tod_data_lock);
if (ihk_atomic64_read(&origin_ts_version) & 1) { if (ihk_atomic64_read(&tod_data.version) & 1) {
panic("settimeofday"); panic("settimeofday");
} }
@@ -4916,9 +4917,9 @@ SYSCALL_DECLARE(settimeofday)
newts.tv_nsec = (long)tv.tv_usec * 1000; newts.tv_nsec = (long)tv.tv_usec * 1000;
tsc = rdtsc(); tsc = rdtsc();
newts.tv_sec -= tsc / clocks_per_sec; newts.tv_sec -= tsc / tod_data.clocks_per_sec;
newts.tv_nsec -= NS_PER_SEC * (tsc % clocks_per_sec) newts.tv_nsec -= NS_PER_SEC * (tsc % tod_data.clocks_per_sec)
/ clocks_per_sec; / tod_data.clocks_per_sec;
if (newts.tv_nsec < 0) { if (newts.tv_nsec < 0) {
--newts.tv_sec; --newts.tv_sec;
newts.tv_nsec += NS_PER_SEC; newts.tv_nsec += NS_PER_SEC;
@@ -4928,17 +4929,17 @@ SYSCALL_DECLARE(settimeofday)
error = syscall_generic_forwarding(n, ctx); error = syscall_generic_forwarding(n, ctx);
if (!error && utv && gettime_local_support) { if (!error && utv && gettime_local_support) {
dkprintf("sys_settimeofday(%p,%p):origin_ts <-- %ld.%ld\n", dkprintf("sys_settimeofday(%p,%p):origin <-- %ld.%ld\n",
utv, utz, newts.tv_sec, newts.tv_nsec); utv, utz, newts.tv_sec, newts.tv_nsec);
ihk_atomic64_inc(&origin_ts_version); ihk_atomic64_inc(&tod_data.version);
wmb(); wmb();
origin_ts = newts; tod_data.origin = newts;
wmb(); wmb();
ihk_atomic64_inc(&origin_ts_version); ihk_atomic64_inc(&tod_data.version);
} }
out: out:
ihk_mc_spinlock_unlock_noirq(&origin_ts_lock); ihk_mc_spinlock_unlock_noirq(&tod_data_lock);
dkprintf("sys_settimeofday(%p,%p): %ld\n", utv, utz, error); dkprintf("sys_settimeofday(%p,%p): %ld\n", utv, utz, error);
return error; return error;
} }