diff options
Diffstat (limited to 'kernel/time/posix-timers.c')
| -rw-r--r-- | kernel/time/posix-timers.c | 88 | 
1 files changed, 64 insertions, 24 deletions
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 0ec5b7a1d769..ff0eb30de346 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -30,6 +30,7 @@  #include <linux/hashtable.h>  #include <linux/compat.h>  #include <linux/nospec.h> +#include <linux/time_namespace.h>  #include "timekeeping.h"  #include "posix-timers.h" @@ -165,12 +166,17 @@ static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)  }  /* Get clock_realtime */ -static int posix_clock_realtime_get(clockid_t which_clock, struct timespec64 *tp) +static int posix_get_realtime_timespec(clockid_t which_clock, struct timespec64 *tp)  {  	ktime_get_real_ts64(tp);  	return 0;  } +static ktime_t posix_get_realtime_ktime(clockid_t which_clock) +{ +	return ktime_get_real(); +} +  /* Set clock_realtime */  static int posix_clock_realtime_set(const clockid_t which_clock,  				    const struct timespec64 *tp) @@ -187,18 +193,25 @@ static int posix_clock_realtime_adj(const clockid_t which_clock,  /*   * Get monotonic time for posix timers   */ -static int posix_ktime_get_ts(clockid_t which_clock, struct timespec64 *tp) +static int posix_get_monotonic_timespec(clockid_t which_clock, struct timespec64 *tp)  {  	ktime_get_ts64(tp); +	timens_add_monotonic(tp);  	return 0;  } +static ktime_t posix_get_monotonic_ktime(clockid_t which_clock) +{ +	return ktime_get(); +} +  /*   * Get monotonic-raw time for posix timers   */  static int posix_get_monotonic_raw(clockid_t which_clock, struct timespec64 *tp)  {  	ktime_get_raw_ts64(tp); +	timens_add_monotonic(tp);  	return 0;  } @@ -213,6 +226,7 @@ static int posix_get_monotonic_coarse(clockid_t which_clock,  						struct timespec64 *tp)  {  	ktime_get_coarse_ts64(tp); +	timens_add_monotonic(tp);  	return 0;  } @@ -222,18 +236,29 @@ static int posix_get_coarse_res(const clockid_t which_clock, struct timespec64 *  	return 0;  } -static int posix_get_boottime(const clockid_t which_clock, struct timespec64 *tp) +static int posix_get_boottime_timespec(const clockid_t which_clock, struct timespec64 *tp)  {  	ktime_get_boottime_ts64(tp); +	timens_add_boottime(tp);  	return 0;  } -static int posix_get_tai(clockid_t which_clock, struct timespec64 *tp) +static ktime_t posix_get_boottime_ktime(const clockid_t which_clock) +{ +	return ktime_get_boottime(); +} + +static int posix_get_tai_timespec(clockid_t which_clock, struct timespec64 *tp)  {  	ktime_get_clocktai_ts64(tp);  	return 0;  } +static ktime_t posix_get_tai_ktime(clockid_t which_clock) +{ +	return ktime_get_clocktai(); +} +  static int posix_get_hrtimer_res(clockid_t which_clock, struct timespec64 *tp)  {  	tp->tv_sec = 0; @@ -645,7 +670,6 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)  {  	const struct k_clock *kc = timr->kclock;  	ktime_t now, remaining, iv; -	struct timespec64 ts64;  	bool sig_none;  	sig_none = timr->it_sigev_notify == SIGEV_NONE; @@ -663,12 +687,7 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)  			return;  	} -	/* -	 * The timespec64 based conversion is suboptimal, but it's not -	 * worth to implement yet another callback. -	 */ -	kc->clock_get(timr->it_clock, &ts64); -	now = timespec64_to_ktime(ts64); +	now = kc->clock_get_ktime(timr->it_clock);  	/*  	 * When a requeue is pending or this is a SIGEV_NONE timer move the @@ -781,7 +800,7 @@ static void common_hrtimer_arm(struct k_itimer *timr, ktime_t expires,  	 * Posix magic: Relative CLOCK_REALTIME timers are not affected by  	 * clock modifications, so they become CLOCK_MONOTONIC based under the  	 * hood. See hrtimer_init(). Update timr->kclock, so the generic -	 * functions which use timr->kclock->clock_get() work. +	 * functions which use timr->kclock->clock_get_*() work.  	 *  	 * Note: it_clock stays unmodified, because the next timer_set() might  	 * use ABSTIME, so it needs to switch back. @@ -866,6 +885,8 @@ int common_timer_set(struct k_itimer *timr, int flags,  	timr->it_interval = timespec64_to_ktime(new_setting->it_interval);  	expires = timespec64_to_ktime(new_setting->it_value); +	if (flags & TIMER_ABSTIME) +		expires = timens_ktime_to_host(timr->it_clock, expires);  	sigev_none = timr->it_sigev_notify == SIGEV_NONE;  	kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none); @@ -1067,7 +1088,7 @@ SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,  	if (!kc)  		return -EINVAL; -	error = kc->clock_get(which_clock, &kernel_tp); +	error = kc->clock_get_timespec(which_clock, &kernel_tp);  	if (!error && put_timespec64(&kernel_tp, tp))  		error = -EFAULT; @@ -1149,7 +1170,7 @@ SYSCALL_DEFINE2(clock_gettime32, clockid_t, which_clock,  	if (!kc)  		return -EINVAL; -	err = kc->clock_get(which_clock, &ts); +	err = kc->clock_get_timespec(which_clock, &ts);  	if (!err && put_old_timespec32(&ts, tp))  		err = -EFAULT; @@ -1200,7 +1221,22 @@ SYSCALL_DEFINE2(clock_getres_time32, clockid_t, which_clock,  static int common_nsleep(const clockid_t which_clock, int flags,  			 const struct timespec64 *rqtp)  { -	return hrtimer_nanosleep(rqtp, flags & TIMER_ABSTIME ? +	ktime_t texp = timespec64_to_ktime(*rqtp); + +	return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ? +				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL, +				 which_clock); +} + +static int common_nsleep_timens(const clockid_t which_clock, int flags, +			 const struct timespec64 *rqtp) +{ +	ktime_t texp = timespec64_to_ktime(*rqtp); + +	if (flags & TIMER_ABSTIME) +		texp = timens_ktime_to_host(which_clock, texp); + +	return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ?  				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,  				 which_clock);  } @@ -1261,7 +1297,8 @@ SYSCALL_DEFINE4(clock_nanosleep_time32, clockid_t, which_clock, int, flags,  static const struct k_clock clock_realtime = {  	.clock_getres		= posix_get_hrtimer_res, -	.clock_get		= posix_clock_realtime_get, +	.clock_get_timespec	= posix_get_realtime_timespec, +	.clock_get_ktime	= posix_get_realtime_ktime,  	.clock_set		= posix_clock_realtime_set,  	.clock_adj		= posix_clock_realtime_adj,  	.nsleep			= common_nsleep, @@ -1279,8 +1316,9 @@ static const struct k_clock clock_realtime = {  static const struct k_clock clock_monotonic = {  	.clock_getres		= posix_get_hrtimer_res, -	.clock_get		= posix_ktime_get_ts, -	.nsleep			= common_nsleep, +	.clock_get_timespec	= posix_get_monotonic_timespec, +	.clock_get_ktime	= posix_get_monotonic_ktime, +	.nsleep			= common_nsleep_timens,  	.timer_create		= common_timer_create,  	.timer_set		= common_timer_set,  	.timer_get		= common_timer_get, @@ -1295,22 +1333,23 @@ static const struct k_clock clock_monotonic = {  static const struct k_clock clock_monotonic_raw = {  	.clock_getres		= posix_get_hrtimer_res, -	.clock_get		= posix_get_monotonic_raw, +	.clock_get_timespec	= posix_get_monotonic_raw,  };  static const struct k_clock clock_realtime_coarse = {  	.clock_getres		= posix_get_coarse_res, -	.clock_get		= posix_get_realtime_coarse, +	.clock_get_timespec	= posix_get_realtime_coarse,  };  static const struct k_clock clock_monotonic_coarse = {  	.clock_getres		= posix_get_coarse_res, -	.clock_get		= posix_get_monotonic_coarse, +	.clock_get_timespec	= posix_get_monotonic_coarse,  };  static const struct k_clock clock_tai = {  	.clock_getres		= posix_get_hrtimer_res, -	.clock_get		= posix_get_tai, +	.clock_get_ktime	= posix_get_tai_ktime, +	.clock_get_timespec	= posix_get_tai_timespec,  	.nsleep			= common_nsleep,  	.timer_create		= common_timer_create,  	.timer_set		= common_timer_set, @@ -1326,8 +1365,9 @@ static const struct k_clock clock_tai = {  static const struct k_clock clock_boottime = {  	.clock_getres		= posix_get_hrtimer_res, -	.clock_get		= posix_get_boottime, -	.nsleep			= common_nsleep, +	.clock_get_ktime	= posix_get_boottime_ktime, +	.clock_get_timespec	= posix_get_boottime_timespec, +	.nsleep			= common_nsleep_timens,  	.timer_create		= common_timer_create,  	.timer_set		= common_timer_set,  	.timer_get		= common_timer_get,  |