Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 30208
b: refs/heads/master
c: cf3c769
h: refs/heads/master
v: v3
  • Loading branch information
john stultz authored and Linus Torvalds committed Jun 26, 2006
1 parent 589ad07 commit 99ba37e
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5eb6d20533d14a432df714520939a6181e28f099
refs/heads/master: cf3c769b4b0dd1146da84d5cf045dcfe53bd0f13
15 changes: 15 additions & 0 deletions trunk/include/linux/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ extern int do_getitimer(int which, struct itimerval *value);
extern void getnstimeofday(struct timespec *tv);

extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
extern int timekeeping_is_continuous(void);

/**
* timespec_to_ns - Convert timespec to nanoseconds
Expand Down Expand Up @@ -144,6 +145,20 @@ extern struct timespec ns_to_timespec(const s64 nsec);
*/
extern struct timeval ns_to_timeval(const s64 nsec);

/**
* timespec_add_ns - Adds nanoseconds to a timespec
* @a: pointer to timespec to be incremented
* @ns: unsigned nanoseconds value to be added
*/
static inline void timespec_add_ns(struct timespec *a, u64 ns)
{
ns += a->tv_nsec;
while(unlikely(ns >= NSEC_PER_SEC)) {
ns -= NSEC_PER_SEC;
a->tv_sec++;
}
a->tv_nsec = ns;
}
#endif /* __KERNEL__ */

#define NFDBITS __NFDBITS
Expand Down
2 changes: 2 additions & 0 deletions trunk/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ EXPORT_SYMBOL(do_gettimeofday);


#else
#ifndef CONFIG_GENERIC_TIME
/*
* Simulate gettimeofday using do_gettimeofday which only allows a timeval
* and therefore only yields usec accuracy
Expand All @@ -537,6 +538,7 @@ void getnstimeofday(struct timespec *tv)
}
EXPORT_SYMBOL_GPL(getnstimeofday);
#endif
#endif

/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
Expand Down
170 changes: 170 additions & 0 deletions trunk/kernel/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,169 @@ u64 current_tick_length(long shift)
#include <linux/clocksource.h>
static struct clocksource *clock; /* pointer to current clocksource */
static cycle_t last_clock_cycle; /* cycle value at last update_wall_time */

#ifdef CONFIG_GENERIC_TIME
/**
* __get_nsec_offset - Returns nanoseconds since last call to periodic_hook
*
* private function, must hold xtime_lock lock when being
* called. Returns the number of nanoseconds since the
* last call to update_wall_time() (adjusted by NTP scaling)
*/
static inline s64 __get_nsec_offset(void)
{
cycle_t cycle_now, cycle_delta;
s64 ns_offset;

/* read clocksource: */
cycle_now = read_clocksource(clock);

/* calculate the delta since the last update_wall_time: */
cycle_delta = (cycle_now - last_clock_cycle) & clock->mask;

/* convert to nanoseconds: */
ns_offset = cyc2ns(clock, cycle_delta);

return ns_offset;
}

/**
* __get_realtime_clock_ts - Returns the time of day in a timespec
* @ts: pointer to the timespec to be set
*
* Returns the time of day in a timespec. Used by
* do_gettimeofday() and get_realtime_clock_ts().
*/
static inline void __get_realtime_clock_ts(struct timespec *ts)
{
unsigned long seq;
s64 nsecs;

do {
seq = read_seqbegin(&xtime_lock);

*ts = xtime;
nsecs = __get_nsec_offset();

} while (read_seqretry(&xtime_lock, seq));

timespec_add_ns(ts, nsecs);
}

/**
* get_realtime_clock_ts - Returns the time of day in a timespec
* @ts: pointer to the timespec to be set
*
* Returns the time of day in a timespec.
*/
void getnstimeofday(struct timespec *ts)
{
__get_realtime_clock_ts(ts);
}

EXPORT_SYMBOL(getnstimeofday);

/**
* do_gettimeofday - Returns the time of day in a timeval
* @tv: pointer to the timeval to be set
*
* NOTE: Users should be converted to using get_realtime_clock_ts()
*/
void do_gettimeofday(struct timeval *tv)
{
struct timespec now;

__get_realtime_clock_ts(&now);
tv->tv_sec = now.tv_sec;
tv->tv_usec = now.tv_nsec/1000;
}

EXPORT_SYMBOL(do_gettimeofday);
/**
* do_settimeofday - Sets the time of day
* @tv: pointer to the timespec variable containing the new time
*
* Sets the time of day to the new time and update NTP and notify hrtimers
*/
int do_settimeofday(struct timespec *tv)
{
unsigned long flags;
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;

if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;

write_seqlock_irqsave(&xtime_lock, flags);

nsec -= __get_nsec_offset();

wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);

set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);

ntp_clear();

write_sequnlock_irqrestore(&xtime_lock, flags);

/* signal hrtimers about time change */
clock_was_set();

return 0;
}

EXPORT_SYMBOL(do_settimeofday);

/**
* change_clocksource - Swaps clocksources if a new one is available
*
* Accumulates current time interval and initializes new clocksource
*/
static int change_clocksource(void)
{
struct clocksource *new;
cycle_t now;
u64 nsec;
new = get_next_clocksource();
if (clock != new) {
now = read_clocksource(new);
nsec = __get_nsec_offset();
timespec_add_ns(&xtime, nsec);

clock = new;
last_clock_cycle = now;
printk(KERN_INFO "Time: %s clocksource has been installed.\n",
clock->name);
return 1;
} else if (clock->update_callback) {
return clock->update_callback();
}
return 0;
}
#else
#define change_clocksource() (0)
#endif

/**
* timeofday_is_continuous - check to see if timekeeping is free running
*/
int timekeeping_is_continuous(void)
{
unsigned long seq;
int ret;

do {
seq = read_seqbegin(&xtime_lock);

ret = clock->is_continuous;

} while (read_seqretry(&xtime_lock, seq));

return ret;
}

/*
* timekeeping_init - Initializes the clocksource and common timekeeping values
*/
Expand Down Expand Up @@ -901,6 +1064,13 @@ static void update_wall_time(void)
/* store full nanoseconds into xtime */
xtime.tv_nsec = remainder_snsecs >> clock->shift;
remainder_snsecs -= (s64)xtime.tv_nsec << clock->shift;

/* check to see if there is a new clocksource to use */
if (change_clocksource()) {
error = 0;
remainder_snsecs = 0;
calculate_clocksource_interval(clock, tick_nsec);
}
}

/*
Expand Down

0 comments on commit 99ba37e

Please sign in to comment.