Skip to content

Commit

Permalink
alarmtimer: Switch over to generic set/get/rearm routine
Browse files Browse the repository at this point in the history
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: Thomas Gleixner <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: John Stultz <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
KAGA-KOKO committed Jun 4, 2017
1 parent b3bf6f3 commit f2c4580
Showing 3 changed files with 29 additions and 110 deletions.
121 changes: 18 additions & 103 deletions kernel/time/alarmtimer.c
Original file line number Diff line number Diff line change
@@ -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);
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,
12 changes: 5 additions & 7 deletions kernel/time/posix-timers.c
Original file line number Diff line number Diff line change
@@ -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,10 +767,9 @@ 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,
struct itimerspec64 *new_setting,
struct itimerspec64 *old_setting)
int common_timer_set(struct k_itimer *timr, int flags,
struct itimerspec64 *new_setting,
struct itimerspec64 *old_setting)
{
const struct k_clock *kc = timr->kclock;
bool sigev_none;
@@ -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 changes: 6 additions & 0 deletions kernel/time/posix-timers.h
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit f2c4580

Please sign in to comment.