mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-26 14:14:01 +08:00
98962465ed
The dynamic tick allows the kernel to sleep for periods longer than a single tick, but it does not limit the sleep time currently. In the worst case the kernel could sleep longer than the wrap around time of the time keeping clock source which would result in losing track of time. Prevent this by limiting it to the safe maximum sleep time of the current time keeping clock source. The value is calculated when the clock source is registered. [ tglx: simplified the code a bit and massaged the commit msg ] Signed-off-by: Jon Hunter <jon-hunter@ti.com> Cc: John Stultz <johnstul@us.ibm.com> LKML-Reference: <1250617512-23567-2-git-send-email-jon-hunter@ti.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
294 lines
8.4 KiB
C
294 lines
8.4 KiB
C
#ifndef _LINUX_TIME_H
|
|
#define _LINUX_TIME_H
|
|
|
|
#include <linux/types.h>
|
|
|
|
#ifdef __KERNEL__
|
|
# include <linux/cache.h>
|
|
# include <linux/seqlock.h>
|
|
# include <linux/math64.h>
|
|
#endif
|
|
|
|
#ifndef _STRUCT_TIMESPEC
|
|
#define _STRUCT_TIMESPEC
|
|
struct timespec {
|
|
__kernel_time_t tv_sec; /* seconds */
|
|
long tv_nsec; /* nanoseconds */
|
|
};
|
|
#endif
|
|
|
|
struct timeval {
|
|
__kernel_time_t tv_sec; /* seconds */
|
|
__kernel_suseconds_t tv_usec; /* microseconds */
|
|
};
|
|
|
|
struct timezone {
|
|
int tz_minuteswest; /* minutes west of Greenwich */
|
|
int tz_dsttime; /* type of dst correction */
|
|
};
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
extern struct timezone sys_tz;
|
|
|
|
/* Parameters used to convert the timespec values: */
|
|
#define MSEC_PER_SEC 1000L
|
|
#define USEC_PER_MSEC 1000L
|
|
#define NSEC_PER_USEC 1000L
|
|
#define NSEC_PER_MSEC 1000000L
|
|
#define USEC_PER_SEC 1000000L
|
|
#define NSEC_PER_SEC 1000000000L
|
|
#define FSEC_PER_SEC 1000000000000000L
|
|
|
|
#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
|
|
|
|
static inline int timespec_equal(const struct timespec *a,
|
|
const struct timespec *b)
|
|
{
|
|
return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
|
|
}
|
|
|
|
/*
|
|
* lhs < rhs: return <0
|
|
* lhs == rhs: return 0
|
|
* lhs > rhs: return >0
|
|
*/
|
|
static inline int timespec_compare(const struct timespec *lhs, const struct timespec *rhs)
|
|
{
|
|
if (lhs->tv_sec < rhs->tv_sec)
|
|
return -1;
|
|
if (lhs->tv_sec > rhs->tv_sec)
|
|
return 1;
|
|
return lhs->tv_nsec - rhs->tv_nsec;
|
|
}
|
|
|
|
static inline int timeval_compare(const struct timeval *lhs, const struct timeval *rhs)
|
|
{
|
|
if (lhs->tv_sec < rhs->tv_sec)
|
|
return -1;
|
|
if (lhs->tv_sec > rhs->tv_sec)
|
|
return 1;
|
|
return lhs->tv_usec - rhs->tv_usec;
|
|
}
|
|
|
|
extern unsigned long mktime(const unsigned int year, const unsigned int mon,
|
|
const unsigned int day, const unsigned int hour,
|
|
const unsigned int min, const unsigned int sec);
|
|
|
|
extern void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec);
|
|
extern struct timespec timespec_add_safe(const struct timespec lhs,
|
|
const struct timespec rhs);
|
|
|
|
/*
|
|
* sub = lhs - rhs, in normalized form
|
|
*/
|
|
static inline struct timespec timespec_sub(struct timespec lhs,
|
|
struct timespec rhs)
|
|
{
|
|
struct timespec ts_delta;
|
|
set_normalized_timespec(&ts_delta, lhs.tv_sec - rhs.tv_sec,
|
|
lhs.tv_nsec - rhs.tv_nsec);
|
|
return ts_delta;
|
|
}
|
|
|
|
/*
|
|
* Returns true if the timespec is norm, false if denorm:
|
|
*/
|
|
#define timespec_valid(ts) \
|
|
(((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC))
|
|
|
|
extern struct timespec xtime;
|
|
extern struct timespec wall_to_monotonic;
|
|
extern seqlock_t xtime_lock;
|
|
|
|
extern void read_persistent_clock(struct timespec *ts);
|
|
extern void read_boot_clock(struct timespec *ts);
|
|
extern int update_persistent_clock(struct timespec now);
|
|
extern int no_sync_cmos_clock __read_mostly;
|
|
void timekeeping_init(void);
|
|
extern int timekeeping_suspended;
|
|
|
|
unsigned long get_seconds(void);
|
|
struct timespec current_kernel_time(void);
|
|
struct timespec __current_kernel_time(void); /* does not hold xtime_lock */
|
|
struct timespec get_monotonic_coarse(void);
|
|
|
|
#define CURRENT_TIME (current_kernel_time())
|
|
#define CURRENT_TIME_SEC ((struct timespec) { get_seconds(), 0 })
|
|
|
|
/* Some architectures do not supply their own clocksource.
|
|
* This is mainly the case in architectures that get their
|
|
* inter-tick times by reading the counter on their interval
|
|
* timer. Since these timers wrap every tick, they're not really
|
|
* useful as clocksources. Wrapping them to act like one is possible
|
|
* but not very efficient. So we provide a callout these arches
|
|
* can implement for use with the jiffies clocksource to provide
|
|
* finer then tick granular time.
|
|
*/
|
|
#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
|
|
extern u32 arch_gettimeoffset(void);
|
|
#else
|
|
static inline u32 arch_gettimeoffset(void) { return 0; }
|
|
#endif
|
|
|
|
extern void do_gettimeofday(struct timeval *tv);
|
|
extern int do_settimeofday(struct timespec *tv);
|
|
extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
|
|
#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
|
|
extern long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags);
|
|
struct itimerval;
|
|
extern int do_setitimer(int which, struct itimerval *value,
|
|
struct itimerval *ovalue);
|
|
extern unsigned int alarm_setitimer(unsigned int seconds);
|
|
extern int do_getitimer(int which, struct itimerval *value);
|
|
extern void getnstimeofday(struct timespec *tv);
|
|
extern void getrawmonotonic(struct timespec *ts);
|
|
extern void getboottime(struct timespec *ts);
|
|
extern void monotonic_to_bootbased(struct timespec *ts);
|
|
|
|
extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
|
|
extern int timekeeping_valid_for_hres(void);
|
|
extern u64 timekeeping_max_deferment(void);
|
|
extern void update_wall_time(void);
|
|
extern void update_xtime_cache(u64 nsec);
|
|
extern void timekeeping_leap_insert(int leapsecond);
|
|
|
|
struct tms;
|
|
extern void do_sys_times(struct tms *);
|
|
|
|
/*
|
|
* Similar to the struct tm in userspace <time.h>, but it needs to be here so
|
|
* that the kernel source is self contained.
|
|
*/
|
|
struct tm {
|
|
/*
|
|
* the number of seconds after the minute, normally in the range
|
|
* 0 to 59, but can be up to 60 to allow for leap seconds
|
|
*/
|
|
int tm_sec;
|
|
/* the number of minutes after the hour, in the range 0 to 59*/
|
|
int tm_min;
|
|
/* the number of hours past midnight, in the range 0 to 23 */
|
|
int tm_hour;
|
|
/* the day of the month, in the range 1 to 31 */
|
|
int tm_mday;
|
|
/* the number of months since January, in the range 0 to 11 */
|
|
int tm_mon;
|
|
/* the number of years since 1900 */
|
|
long tm_year;
|
|
/* the number of days since Sunday, in the range 0 to 6 */
|
|
int tm_wday;
|
|
/* the number of days since January 1, in the range 0 to 365 */
|
|
int tm_yday;
|
|
};
|
|
|
|
void time_to_tm(time_t totalsecs, int offset, struct tm *result);
|
|
|
|
/**
|
|
* timespec_to_ns - Convert timespec to nanoseconds
|
|
* @ts: pointer to the timespec variable to be converted
|
|
*
|
|
* Returns the scalar nanosecond representation of the timespec
|
|
* parameter.
|
|
*/
|
|
static inline s64 timespec_to_ns(const struct timespec *ts)
|
|
{
|
|
return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
|
|
}
|
|
|
|
/**
|
|
* timeval_to_ns - Convert timeval to nanoseconds
|
|
* @ts: pointer to the timeval variable to be converted
|
|
*
|
|
* Returns the scalar nanosecond representation of the timeval
|
|
* parameter.
|
|
*/
|
|
static inline s64 timeval_to_ns(const struct timeval *tv)
|
|
{
|
|
return ((s64) tv->tv_sec * NSEC_PER_SEC) +
|
|
tv->tv_usec * NSEC_PER_USEC;
|
|
}
|
|
|
|
/**
|
|
* ns_to_timespec - Convert nanoseconds to timespec
|
|
* @nsec: the nanoseconds value to be converted
|
|
*
|
|
* Returns the timespec representation of the nsec parameter.
|
|
*/
|
|
extern struct timespec ns_to_timespec(const s64 nsec);
|
|
|
|
/**
|
|
* ns_to_timeval - Convert nanoseconds to timeval
|
|
* @nsec: the nanoseconds value to be converted
|
|
*
|
|
* Returns the timeval representation of the nsec parameter.
|
|
*/
|
|
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
|
|
*
|
|
* This must always be inlined because its used from the x86-64 vdso,
|
|
* which cannot call other kernel functions.
|
|
*/
|
|
static __always_inline void timespec_add_ns(struct timespec *a, u64 ns)
|
|
{
|
|
a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
|
|
a->tv_nsec = ns;
|
|
}
|
|
#endif /* __KERNEL__ */
|
|
|
|
#define NFDBITS __NFDBITS
|
|
|
|
#define FD_SETSIZE __FD_SETSIZE
|
|
#define FD_SET(fd,fdsetp) __FD_SET(fd,fdsetp)
|
|
#define FD_CLR(fd,fdsetp) __FD_CLR(fd,fdsetp)
|
|
#define FD_ISSET(fd,fdsetp) __FD_ISSET(fd,fdsetp)
|
|
#define FD_ZERO(fdsetp) __FD_ZERO(fdsetp)
|
|
|
|
/*
|
|
* Names of the interval timers, and structure
|
|
* defining a timer setting:
|
|
*/
|
|
#define ITIMER_REAL 0
|
|
#define ITIMER_VIRTUAL 1
|
|
#define ITIMER_PROF 2
|
|
|
|
struct itimerspec {
|
|
struct timespec it_interval; /* timer period */
|
|
struct timespec it_value; /* timer expiration */
|
|
};
|
|
|
|
struct itimerval {
|
|
struct timeval it_interval; /* timer interval */
|
|
struct timeval it_value; /* current value */
|
|
};
|
|
|
|
/*
|
|
* The IDs of the various system clocks (for POSIX.1b interval timers):
|
|
*/
|
|
#define CLOCK_REALTIME 0
|
|
#define CLOCK_MONOTONIC 1
|
|
#define CLOCK_PROCESS_CPUTIME_ID 2
|
|
#define CLOCK_THREAD_CPUTIME_ID 3
|
|
#define CLOCK_MONOTONIC_RAW 4
|
|
#define CLOCK_REALTIME_COARSE 5
|
|
#define CLOCK_MONOTONIC_COARSE 6
|
|
|
|
/*
|
|
* The IDs of various hardware clocks:
|
|
*/
|
|
#define CLOCK_SGI_CYCLE 10
|
|
#define MAX_CLOCKS 16
|
|
#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC)
|
|
#define CLOCKS_MONO CLOCK_MONOTONIC
|
|
|
|
/*
|
|
* The various flags for setting POSIX.1b interval timers:
|
|
*/
|
|
#define TIMER_ABSTIME 0x01
|
|
|
|
#endif
|