Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2c45807 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

alarmtimer: Switch over to generic set/get/rearm routine



All required callbacks are in place. Switch the alarm timer based posix
interval timer callbacks to the common implementation and remove the
incorrect private implementation.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: John Stultz <john.stultz@linaro.org>
Link: http://lkml.kernel.org/r/20170530211657.825471962@linutronix.de
parent b3bf6f36
Loading
Loading
Loading
Loading
+18 −103
Original line number Diff line number Diff line
@@ -515,20 +515,26 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid)
static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
							ktime_t now)
{
	unsigned long flags;
	struct k_itimer *ptr = container_of(alarm, struct k_itimer,
					    it.alarm.alarmtimer);
	enum alarmtimer_restart result = ALARMTIMER_NORESTART;
	unsigned long flags;
	int si_private = 0;

	spin_lock_irqsave(&ptr->it_lock, flags);
	if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) {
		if (posix_timer_event(ptr, 0))
			ptr->it_overrun++;
	}

	/* Re-add periodic timers */
	if (ptr->it_interval) {
		ptr->it_overrun += alarm_forward(alarm, now, ptr->it_interval);
	ptr->it_active = 0;
	if (ptr->it_interval)
		si_private = ++ptr->it_requeue_pending;

	if (posix_timer_event(ptr, si_private) && ptr->it_interval) {
		/*
		 * Handle ignored signals and rearm the timer. This will go
		 * away once we handle ignored signals proper.
		 */
		ptr->it_overrun += alarm_forward_now(alarm, ptr->it_interval);
		++ptr->it_requeue_pending;
		ptr->it_active = 1;
		result = ALARMTIMER_RESTART;
	}
	spin_unlock_irqrestore(&ptr->it_lock, flags);
@@ -658,97 +664,6 @@ static int alarm_timer_create(struct k_itimer *new_timer)
	return 0;
}

/**
 * alarm_timer_get - posix timer_get interface
 * @timr: k_itimer pointer
 * @cur_setting: itimerspec data to fill
 *
 * Copies out the current itimerspec data
 */
static void alarm_timer_get(struct k_itimer *timr,
			    struct itimerspec64 *cur_setting)
{
	ktime_t relative_expiry_time =
		alarm_expires_remaining(&(timr->it.alarm.alarmtimer));

	if (ktime_to_ns(relative_expiry_time) > 0) {
		cur_setting->it_value = ktime_to_timespec64(relative_expiry_time);
	} else {
		cur_setting->it_value.tv_sec = 0;
		cur_setting->it_value.tv_nsec = 0;
	}

	cur_setting->it_interval = ktime_to_timespec64(timr->it_interval);
}

/**
 * alarm_timer_del - posix timer_del interface
 * @timr: k_itimer pointer to be deleted
 *
 * Cancels any programmed alarms for the given timer.
 */
static int alarm_timer_del(struct k_itimer *timr)
{
	if (!rtcdev)
		return -ENOTSUPP;

	if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0)
		return TIMER_RETRY;

	return 0;
}

/**
 * alarm_timer_set - posix timer_set interface
 * @timr: k_itimer pointer to be deleted
 * @flags: timer flags
 * @new_setting: itimerspec to be used
 * @old_setting: itimerspec being replaced
 *
 * Sets the timer to new_setting, and starts the timer.
 */
static int alarm_timer_set(struct k_itimer *timr, int flags,
			   struct itimerspec64 *new_setting,
			   struct itimerspec64 *old_setting)
{
	ktime_t exp;

	if (!rtcdev)
		return -ENOTSUPP;

	if (flags & ~TIMER_ABSTIME)
		return -EINVAL;

	if (old_setting)
		alarm_timer_get(timr, old_setting);

	/* If the timer was already set, cancel it */
	if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0)
		return TIMER_RETRY;

	/* start the timer */
	timr->it_interval = timespec64_to_ktime(new_setting->it_interval);

	/*
	 * Rate limit to the tick as a hot fix to prevent DOS. Will be
	 * mopped up later.
	 */
	if (timr->it_interval < TICK_NSEC)
		timr->it_interval = TICK_NSEC;

	exp = timespec64_to_ktime(new_setting->it_value);
	/* Convert (if necessary) to absolute time */
	if (flags != TIMER_ABSTIME) {
		ktime_t now;

		now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime();
		exp = ktime_add_safe(now, exp);
	}

	alarm_start(&timr->it.alarm.alarmtimer, exp);
	return 0;
}

/**
 * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep
 * @alarm: ptr to alarm that fired
@@ -926,9 +841,9 @@ const struct k_clock alarm_clock = {
	.clock_getres		= alarm_clock_getres,
	.clock_get		= alarm_clock_get,
	.timer_create		= alarm_timer_create,
	.timer_set		= alarm_timer_set,
	.timer_del		= alarm_timer_del,
	.timer_get		= alarm_timer_get,
	.timer_set		= common_timer_set,
	.timer_del		= common_timer_del,
	.timer_get		= common_timer_get,
	.timer_arm		= alarm_timer_arm,
	.timer_rearm		= alarm_timer_rearm,
	.timer_forward		= alarm_timer_forward,
+5 −7
Original line number Diff line number Diff line
@@ -637,8 +637,7 @@ static int common_hrtimer_forward(struct k_itimer *timr, ktime_t now)
 * it is the same as a requeue pending timer WRT to what we should
 * report.
 */
static void
common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
{
	const struct k_clock *kc = timr->kclock;
	ktime_t now, remaining, iv;
@@ -768,8 +767,7 @@ static int common_hrtimer_try_to_cancel(struct k_itimer *timr)
}

/* Set a POSIX.1b interval timer. */
static int
common_timer_set(struct k_itimer *timr, int flags,
int common_timer_set(struct k_itimer *timr, int flags,
		     struct itimerspec64 *new_setting,
		     struct itimerspec64 *old_setting)
{
@@ -855,7 +853,7 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
	return error;
}

static int common_timer_del(struct k_itimer *timer)
int common_timer_del(struct k_itimer *timer)
{
	const struct k_clock *kc = timer->kclock;

+6 −0
Original line number Diff line number Diff line
@@ -33,3 +33,9 @@ extern const struct k_clock clock_thread;
extern const struct k_clock alarm_clock;

int posix_timer_event(struct k_itimer *timr, int si_private);

void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting);
int common_timer_set(struct k_itimer *timr, int flags,
		     struct itimerspec64 *new_setting,
		     struct itimerspec64 *old_setting);
int common_timer_del(struct k_itimer *timer);