diff options
Diffstat (limited to 'kernel/time/timekeeping.c')
| -rw-r--r-- | kernel/time/timekeeping.c | 141 |
1 files changed, 133 insertions, 8 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index d27c7562902..3bd7e3d5c63 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -353,7 +353,7 @@ EXPORT_SYMBOL(do_gettimeofday); | |||
| 353 | * | 353 | * |
| 354 | * Sets the time of day to the new time and update NTP and notify hrtimers | 354 | * Sets the time of day to the new time and update NTP and notify hrtimers |
| 355 | */ | 355 | */ |
| 356 | int do_settimeofday(struct timespec *tv) | 356 | int do_settimeofday(const struct timespec *tv) |
| 357 | { | 357 | { |
| 358 | struct timespec ts_delta; | 358 | struct timespec ts_delta; |
| 359 | unsigned long flags; | 359 | unsigned long flags; |
| @@ -387,6 +387,42 @@ int do_settimeofday(struct timespec *tv) | |||
| 387 | 387 | ||
| 388 | EXPORT_SYMBOL(do_settimeofday); | 388 | EXPORT_SYMBOL(do_settimeofday); |
| 389 | 389 | ||
| 390 | |||
| 391 | /** | ||
| 392 | * timekeeping_inject_offset - Adds or subtracts from the current time. | ||
| 393 | * @tv: pointer to the timespec variable containing the offset | ||
| 394 | * | ||
| 395 | * Adds or subtracts an offset value from the current time. | ||
| 396 | */ | ||
| 397 | int timekeeping_inject_offset(struct timespec *ts) | ||
| 398 | { | ||
| 399 | unsigned long flags; | ||
| 400 | |||
| 401 | if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) | ||
| 402 | return -EINVAL; | ||
| 403 | |||
| 404 | write_seqlock_irqsave(&xtime_lock, flags); | ||
| 405 | |||
| 406 | timekeeping_forward_now(); | ||
| 407 | |||
| 408 | xtime = timespec_add(xtime, *ts); | ||
| 409 | wall_to_monotonic = timespec_sub(wall_to_monotonic, *ts); | ||
| 410 | |||
| 411 | timekeeper.ntp_error = 0; | ||
| 412 | ntp_clear(); | ||
| 413 | |||
| 414 | update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, | ||
| 415 | timekeeper.mult); | ||
| 416 | |||
| 417 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
| 418 | |||
| 419 | /* signal hrtimers about time change */ | ||
| 420 | clock_was_set(); | ||
| 421 | |||
| 422 | return 0; | ||
| 423 | } | ||
| 424 | EXPORT_SYMBOL(timekeeping_inject_offset); | ||
| 425 | |||
| 390 | /** | 426 | /** |
| 391 | * change_clocksource - Swaps clocksources if a new one is available | 427 | * change_clocksource - Swaps clocksources if a new one is available |
| 392 | * | 428 | * |
| @@ -779,7 +815,7 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) | |||
| 779 | * | 815 | * |
| 780 | * Called from the timer interrupt, must hold a write on xtime_lock. | 816 | * Called from the timer interrupt, must hold a write on xtime_lock. |
| 781 | */ | 817 | */ |
| 782 | void update_wall_time(void) | 818 | static void update_wall_time(void) |
| 783 | { | 819 | { |
| 784 | struct clocksource *clock; | 820 | struct clocksource *clock; |
| 785 | cycle_t offset; | 821 | cycle_t offset; |
| @@ -871,7 +907,7 @@ void update_wall_time(void) | |||
| 871 | * getboottime - Return the real time of system boot. | 907 | * getboottime - Return the real time of system boot. |
| 872 | * @ts: pointer to the timespec to be set | 908 | * @ts: pointer to the timespec to be set |
| 873 | * | 909 | * |
| 874 | * Returns the time of day in a timespec. | 910 | * Returns the wall-time of boot in a timespec. |
| 875 | * | 911 | * |
| 876 | * This is based on the wall_to_monotonic offset and the total suspend | 912 | * This is based on the wall_to_monotonic offset and the total suspend |
| 877 | * time. Calls to settimeofday will affect the value returned (which | 913 | * time. Calls to settimeofday will affect the value returned (which |
| @@ -889,6 +925,55 @@ void getboottime(struct timespec *ts) | |||
| 889 | } | 925 | } |
| 890 | EXPORT_SYMBOL_GPL(getboottime); | 926 | EXPORT_SYMBOL_GPL(getboottime); |
| 891 | 927 | ||
| 928 | |||
| 929 | /** | ||
| 930 | * get_monotonic_boottime - Returns monotonic time since boot | ||
| 931 | * @ts: pointer to the timespec to be set | ||
| 932 | * | ||
| 933 | * Returns the monotonic time since boot in a timespec. | ||
| 934 | * | ||
| 935 | * This is similar to CLOCK_MONTONIC/ktime_get_ts, but also | ||
| 936 | * includes the time spent in suspend. | ||
| 937 | */ | ||
| 938 | void get_monotonic_boottime(struct timespec *ts) | ||
| 939 | { | ||
| 940 | struct timespec tomono, sleep; | ||
| 941 | unsigned int seq; | ||
| 942 | s64 nsecs; | ||
| 943 | |||
| 944 | WARN_ON(timekeeping_suspended); | ||
| 945 | |||
| 946 | do { | ||
| 947 | seq = read_seqbegin(&xtime_lock); | ||
| 948 | *ts = xtime; | ||
| 949 | tomono = wall_to_monotonic; | ||
| 950 | sleep = total_sleep_time; | ||
| 951 | nsecs = timekeeping_get_ns(); | ||
| 952 | |||
| 953 | } while (read_seqretry(&xtime_lock, seq)); | ||
| 954 | |||
| 955 | set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec, | ||
| 956 | ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec + nsecs); | ||
| 957 | } | ||
| 958 | EXPORT_SYMBOL_GPL(get_monotonic_boottime); | ||
| 959 | |||
| 960 | /** | ||
| 961 | * ktime_get_boottime - Returns monotonic time since boot in a ktime | ||
| 962 | * | ||
| 963 | * Returns the monotonic time since boot in a ktime | ||
| 964 | * | ||
| 965 | * This is similar to CLOCK_MONTONIC/ktime_get, but also | ||
| 966 | * includes the time spent in suspend. | ||
| 967 | */ | ||
| 968 | ktime_t ktime_get_boottime(void) | ||
| 969 | { | ||
| 970 | struct timespec ts; | ||
| 971 | |||
| 972 | get_monotonic_boottime(&ts); | ||
| 973 | return timespec_to_ktime(ts); | ||
| 974 | } | ||
| 975 | EXPORT_SYMBOL_GPL(ktime_get_boottime); | ||
| 976 | |||
| 892 | /** | 977 | /** |
| 893 | * monotonic_to_bootbased - Convert the monotonic time to boot based. | 978 | * monotonic_to_bootbased - Convert the monotonic time to boot based. |
| 894 | * @ts: pointer to the timespec to be converted | 979 | * @ts: pointer to the timespec to be converted |
| @@ -910,11 +995,6 @@ struct timespec __current_kernel_time(void) | |||
| 910 | return xtime; | 995 | return xtime; |
| 911 | } | 996 | } |
| 912 | 997 | ||
| 913 | struct timespec __get_wall_to_monotonic(void) | ||
| 914 | { | ||
| 915 | return wall_to_monotonic; | ||
| 916 | } | ||
| 917 | |||
| 918 | struct timespec current_kernel_time(void) | 998 | struct timespec current_kernel_time(void) |
| 919 | { | 999 | { |
| 920 | struct timespec now; | 1000 | struct timespec now; |
| @@ -946,3 +1026,48 @@ struct timespec get_monotonic_coarse(void) | |||
| 946 | now.tv_nsec + mono.tv_nsec); | 1026 | now.tv_nsec + mono.tv_nsec); |
| 947 | return now; | 1027 | return now; |
| 948 | } | 1028 | } |
| 1029 | |||
| 1030 | /* | ||
| 1031 | * The 64-bit jiffies value is not atomic - you MUST NOT read it | ||
| 1032 | * without sampling the sequence number in xtime_lock. | ||
| 1033 | * jiffies is defined in the linker script... | ||
| 1034 | */ | ||
| 1035 | void do_timer(unsigned long ticks) | ||
| 1036 | { | ||
| 1037 | jiffies_64 += ticks; | ||
| 1038 | update_wall_time(); | ||
| 1039 | calc_global_load(ticks); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | /** | ||
| 1043 | * get_xtime_and_monotonic_and_sleep_offset() - get xtime, wall_to_monotonic, | ||
| 1044 | * and sleep offsets. | ||
| 1045 | * @xtim: pointer to timespec to be set with xtime | ||
| 1046 | * @wtom: pointer to timespec to be set with wall_to_monotonic | ||
| 1047 | * @sleep: pointer to timespec to be set with time in suspend | ||
| 1048 | */ | ||
| 1049 | void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, | ||
| 1050 | struct timespec *wtom, struct timespec *sleep) | ||
| 1051 | { | ||
| 1052 | unsigned long seq; | ||
| 1053 | |||
| 1054 | do { | ||
| 1055 | seq = read_seqbegin(&xtime_lock); | ||
| 1056 | *xtim = xtime; | ||
| 1057 | *wtom = wall_to_monotonic; | ||
| 1058 | *sleep = total_sleep_time; | ||
| 1059 | } while (read_seqretry(&xtime_lock, seq)); | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | /** | ||
| 1063 | * xtime_update() - advances the timekeeping infrastructure | ||
| 1064 | * @ticks: number of ticks, that have elapsed since the last call. | ||
| 1065 | * | ||
| 1066 | * Must be called with interrupts disabled. | ||
| 1067 | */ | ||
| 1068 | void xtime_update(unsigned long ticks) | ||
| 1069 | { | ||
| 1070 | write_seqlock(&xtime_lock); | ||
| 1071 | do_timer(ticks); | ||
| 1072 | write_sequnlock(&xtime_lock); | ||
| 1073 | } | ||
