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

Commit dce75a8c authored by John Stultz's avatar John Stultz
Browse files

alarmtimers: Add alarm_forward functionality



In order to avoid wasting time expiring and re-adding very high freq
periodic alarmtimers, introduce alarm_forward() which is similar to
hrtimer_forward and moves the timer to the next future expiration time
and returns the number of overruns.

CC: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
parent 54da23b7
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -42,4 +42,6 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period);
void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period);
void alarm_cancel(struct alarm *alarm);
void alarm_cancel(struct alarm *alarm);


u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval);

#endif
#endif
+36 −1
Original line number Original line Diff line number Diff line
@@ -347,6 +347,41 @@ void alarm_cancel(struct alarm *alarm)
}
}





u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval)
{
	u64 overrun = 1;
	ktime_t delta;

	delta = ktime_sub(now, alarm->node.expires);

	if (delta.tv64 < 0)
		return 0;

	if (unlikely(delta.tv64 >= interval.tv64)) {
		s64 incr = ktime_to_ns(interval);

		overrun = ktime_divns(delta, incr);

		alarm->node.expires = ktime_add_ns(alarm->node.expires,
							incr*overrun);

		if (alarm->node.expires.tv64 > now.tv64)
			return overrun;
		/*
		 * This (and the ktime_add() below) is the
		 * correction for exact:
		 */
		overrun++;
	}

	alarm->node.expires = ktime_add(alarm->node.expires, interval);
	return overrun;
}




/**
/**
 * clock2alarm - helper that converts from clockid to alarmtypes
 * clock2alarm - helper that converts from clockid to alarmtypes
 * @clockid: clockid.
 * @clockid: clockid.
@@ -376,7 +411,7 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,


	/* Re-add periodic timers */
	/* Re-add periodic timers */
	if (alarm->period.tv64) {
	if (alarm->period.tv64) {
		alarm->node.expires = ktime_add(now, alarm->period);
		ptr->it_overrun += alarm_forward(alarm, now, alarm->period);
		return ALARMTIMER_RESTART;
		return ALARMTIMER_RESTART;
	}
	}
	return ALARMTIMER_NORESTART;
	return ALARMTIMER_NORESTART;