diff options
Diffstat (limited to 'kernel/time')
| -rw-r--r-- | kernel/time/timekeeping.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index ce618010c373..16280ff3cf82 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -1062,6 +1062,33 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, | |||
| 1062 | return offset; | 1062 | return offset; |
| 1063 | } | 1063 | } |
| 1064 | 1064 | ||
| 1065 | #ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD | ||
| 1066 | static inline void old_vsyscall_fixup(struct timekeeper *tk) | ||
| 1067 | { | ||
| 1068 | s64 remainder; | ||
| 1069 | |||
| 1070 | /* | ||
| 1071 | * Store only full nanoseconds into xtime_nsec after rounding | ||
| 1072 | * it up and add the remainder to the error difference. | ||
| 1073 | * XXX - This is necessary to avoid small 1ns inconsistnecies caused | ||
| 1074 | * by truncating the remainder in vsyscalls. However, it causes | ||
| 1075 | * additional work to be done in timekeeping_adjust(). Once | ||
| 1076 | * the vsyscall implementations are converted to use xtime_nsec | ||
| 1077 | * (shifted nanoseconds), and CONFIG_GENERIC_TIME_VSYSCALL_OLD | ||
| 1078 | * users are removed, this can be killed. | ||
| 1079 | */ | ||
| 1080 | remainder = tk->xtime_nsec & ((1ULL << tk->shift) - 1); | ||
| 1081 | tk->xtime_nsec -= remainder; | ||
| 1082 | tk->xtime_nsec += 1ULL << tk->shift; | ||
| 1083 | tk->ntp_error += remainder << tk->ntp_error_shift; | ||
| 1084 | |||
| 1085 | } | ||
| 1086 | #else | ||
| 1087 | #define old_vsyscall_fixup(tk) | ||
| 1088 | #endif | ||
| 1089 | |||
| 1090 | |||
| 1091 | |||
| 1065 | /** | 1092 | /** |
| 1066 | * update_wall_time - Uses the current clocksource to increment the wall time | 1093 | * update_wall_time - Uses the current clocksource to increment the wall time |
| 1067 | * | 1094 | * |
| @@ -1073,7 +1100,6 @@ static void update_wall_time(void) | |||
| 1073 | cycle_t offset; | 1100 | cycle_t offset; |
| 1074 | int shift = 0, maxshift; | 1101 | int shift = 0, maxshift; |
| 1075 | unsigned long flags; | 1102 | unsigned long flags; |
| 1076 | s64 remainder; | ||
| 1077 | 1103 | ||
| 1078 | write_seqlock_irqsave(&tk->lock, flags); | 1104 | write_seqlock_irqsave(&tk->lock, flags); |
| 1079 | 1105 | ||
| @@ -1115,20 +1141,11 @@ static void update_wall_time(void) | |||
| 1115 | /* correct the clock when NTP error is too big */ | 1141 | /* correct the clock when NTP error is too big */ |
| 1116 | timekeeping_adjust(tk, offset); | 1142 | timekeeping_adjust(tk, offset); |
| 1117 | 1143 | ||
| 1118 | |||
| 1119 | /* | 1144 | /* |
| 1120 | * Store only full nanoseconds into xtime_nsec after rounding | 1145 | * XXX This can be killed once everyone converts |
| 1121 | * it up and add the remainder to the error difference. | 1146 | * to the new update_vsyscall. |
| 1122 | * XXX - This is necessary to avoid small 1ns inconsistnecies caused | 1147 | */ |
| 1123 | * by truncating the remainder in vsyscalls. However, it causes | 1148 | old_vsyscall_fixup(tk); |
| 1124 | * additional work to be done in timekeeping_adjust(). Once | ||
| 1125 | * the vsyscall implementations are converted to use xtime_nsec | ||
| 1126 | * (shifted nanoseconds), this can be killed. | ||
| 1127 | */ | ||
| 1128 | remainder = tk->xtime_nsec & ((1ULL << tk->shift) - 1); | ||
| 1129 | tk->xtime_nsec -= remainder; | ||
| 1130 | tk->xtime_nsec += 1ULL << tk->shift; | ||
| 1131 | tk->ntp_error += remainder << tk->ntp_error_shift; | ||
| 1132 | 1149 | ||
| 1133 | /* | 1150 | /* |
| 1134 | * Finally, make sure that after the rounding | 1151 | * Finally, make sure that after the rounding |
