forked from Minki/linux
Merge branches 'locking-urgent-for-linus' and 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull futex and timer fixes from Thomas Gleixner: "A oneliner bugfix for the jinxed futex code: - Drop hash bucket lock in the error exit path. I really could slap myself for intruducing that bug while fixing all the other horror in that code three month ago ... and the timer department is not too proud about the following fixes: - Deal with a long standing rounding bug in the timeval to jiffies conversion. It's a real issue and this fix fell through the cracks for quite some time. - Another round of alarmtimer fixes. Finally this code gets used more widely and the subtle issues hidden for quite some time are noticed and fixed. Nothing really exciting, just the itty bitty details which bite the serious users here and there" * 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: futex: Unlock hb->lock in futex_wait_requeue_pi() error path * 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: alarmtimer: Lock k_itimer during timer callback alarmtimer: Do not signal SIGEV_NONE timers alarmtimer: Return relative times in timer_gettime jiffies: Fix timeval conversion to jiffies
This commit is contained in:
commit
1536340e7c
@ -258,23 +258,11 @@ extern unsigned long preset_lpj;
|
||||
#define SEC_JIFFIE_SC (32 - SHIFT_HZ)
|
||||
#endif
|
||||
#define NSEC_JIFFIE_SC (SEC_JIFFIE_SC + 29)
|
||||
#define USEC_JIFFIE_SC (SEC_JIFFIE_SC + 19)
|
||||
#define SEC_CONVERSION ((unsigned long)((((u64)NSEC_PER_SEC << SEC_JIFFIE_SC) +\
|
||||
TICK_NSEC -1) / (u64)TICK_NSEC))
|
||||
|
||||
#define NSEC_CONVERSION ((unsigned long)((((u64)1 << NSEC_JIFFIE_SC) +\
|
||||
TICK_NSEC -1) / (u64)TICK_NSEC))
|
||||
#define USEC_CONVERSION \
|
||||
((unsigned long)((((u64)NSEC_PER_USEC << USEC_JIFFIE_SC) +\
|
||||
TICK_NSEC -1) / (u64)TICK_NSEC))
|
||||
/*
|
||||
* USEC_ROUND is used in the timeval to jiffie conversion. See there
|
||||
* for more details. It is the scaled resolution rounding value. Note
|
||||
* that it is a 64-bit value. Since, when it is applied, we are already
|
||||
* in jiffies (albit scaled), it is nothing but the bits we will shift
|
||||
* off.
|
||||
*/
|
||||
#define USEC_ROUND (u64)(((u64)1 << USEC_JIFFIE_SC) - 1)
|
||||
/*
|
||||
* The maximum jiffie value is (MAX_INT >> 1). Here we translate that
|
||||
* into seconds. The 64-bit case will overflow if we are not careful,
|
||||
|
@ -2592,6 +2592,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
|
||||
* shared futexes. We need to compare the keys:
|
||||
*/
|
||||
if (match_futex(&q.key, &key2)) {
|
||||
queue_unlock(hb);
|
||||
ret = -EINVAL;
|
||||
goto out_put_keys;
|
||||
}
|
||||
|
@ -464,18 +464,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);
|
||||
if (posix_timer_event(ptr, 0) != 0)
|
||||
ptr->it_overrun++;
|
||||
enum alarmtimer_restart result = ALARMTIMER_NORESTART;
|
||||
|
||||
spin_lock_irqsave(&ptr->it_lock, flags);
|
||||
if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) {
|
||||
if (posix_timer_event(ptr, 0) != 0)
|
||||
ptr->it_overrun++;
|
||||
}
|
||||
|
||||
/* Re-add periodic timers */
|
||||
if (ptr->it.alarm.interval.tv64) {
|
||||
ptr->it_overrun += alarm_forward(alarm, now,
|
||||
ptr->it.alarm.interval);
|
||||
return ALARMTIMER_RESTART;
|
||||
result = ALARMTIMER_RESTART;
|
||||
}
|
||||
return ALARMTIMER_NORESTART;
|
||||
spin_unlock_irqrestore(&ptr->it_lock, flags);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -541,18 +549,22 @@ static int alarm_timer_create(struct k_itimer *new_timer)
|
||||
* @new_timer: k_itimer pointer
|
||||
* @cur_setting: itimerspec data to fill
|
||||
*
|
||||
* Copies the itimerspec data out from the k_itimer
|
||||
* Copies out the current itimerspec data
|
||||
*/
|
||||
static void alarm_timer_get(struct k_itimer *timr,
|
||||
struct itimerspec *cur_setting)
|
||||
{
|
||||
memset(cur_setting, 0, sizeof(struct itimerspec));
|
||||
ktime_t relative_expiry_time =
|
||||
alarm_expires_remaining(&(timr->it.alarm.alarmtimer));
|
||||
|
||||
cur_setting->it_interval =
|
||||
ktime_to_timespec(timr->it.alarm.interval);
|
||||
cur_setting->it_value =
|
||||
ktime_to_timespec(timr->it.alarm.alarmtimer.node.expires);
|
||||
return;
|
||||
if (ktime_to_ns(relative_expiry_time) > 0) {
|
||||
cur_setting->it_value = ktime_to_timespec(relative_expiry_time);
|
||||
} else {
|
||||
cur_setting->it_value.tv_sec = 0;
|
||||
cur_setting->it_value.tv_nsec = 0;
|
||||
}
|
||||
|
||||
cur_setting->it_interval = ktime_to_timespec(timr->it.alarm.interval);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -559,17 +559,20 @@ EXPORT_SYMBOL(usecs_to_jiffies);
|
||||
* that a remainder subtract here would not do the right thing as the
|
||||
* resolution values don't fall on second boundries. I.e. the line:
|
||||
* nsec -= nsec % TICK_NSEC; is NOT a correct resolution rounding.
|
||||
* Note that due to the small error in the multiplier here, this
|
||||
* rounding is incorrect for sufficiently large values of tv_nsec, but
|
||||
* well formed timespecs should have tv_nsec < NSEC_PER_SEC, so we're
|
||||
* OK.
|
||||
*
|
||||
* Rather, we just shift the bits off the right.
|
||||
*
|
||||
* The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec
|
||||
* value to a scaled second value.
|
||||
*/
|
||||
unsigned long
|
||||
timespec_to_jiffies(const struct timespec *value)
|
||||
static unsigned long
|
||||
__timespec_to_jiffies(unsigned long sec, long nsec)
|
||||
{
|
||||
unsigned long sec = value->tv_sec;
|
||||
long nsec = value->tv_nsec + TICK_NSEC - 1;
|
||||
nsec = nsec + TICK_NSEC - 1;
|
||||
|
||||
if (sec >= MAX_SEC_IN_JIFFIES){
|
||||
sec = MAX_SEC_IN_JIFFIES;
|
||||
@ -580,6 +583,13 @@ timespec_to_jiffies(const struct timespec *value)
|
||||
(NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
|
||||
|
||||
}
|
||||
|
||||
unsigned long
|
||||
timespec_to_jiffies(const struct timespec *value)
|
||||
{
|
||||
return __timespec_to_jiffies(value->tv_sec, value->tv_nsec);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(timespec_to_jiffies);
|
||||
|
||||
void
|
||||
@ -596,31 +606,27 @@ jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)
|
||||
}
|
||||
EXPORT_SYMBOL(jiffies_to_timespec);
|
||||
|
||||
/* Same for "timeval"
|
||||
/*
|
||||
* We could use a similar algorithm to timespec_to_jiffies (with a
|
||||
* different multiplier for usec instead of nsec). But this has a
|
||||
* problem with rounding: we can't exactly add TICK_NSEC - 1 to the
|
||||
* usec value, since it's not necessarily integral.
|
||||
*
|
||||
* Well, almost. The problem here is that the real system resolution is
|
||||
* in nanoseconds and the value being converted is in micro seconds.
|
||||
* Also for some machines (those that use HZ = 1024, in-particular),
|
||||
* there is a LARGE error in the tick size in microseconds.
|
||||
|
||||
* The solution we use is to do the rounding AFTER we convert the
|
||||
* microsecond part. Thus the USEC_ROUND, the bits to be shifted off.
|
||||
* Instruction wise, this should cost only an additional add with carry
|
||||
* instruction above the way it was done above.
|
||||
* We could instead round in the intermediate scaled representation
|
||||
* (i.e. in units of 1/2^(large scale) jiffies) but that's also
|
||||
* perilous: the scaling introduces a small positive error, which
|
||||
* combined with a division-rounding-upward (i.e. adding 2^(scale) - 1
|
||||
* units to the intermediate before shifting) leads to accidental
|
||||
* overflow and overestimates.
|
||||
*
|
||||
* At the cost of one additional multiplication by a constant, just
|
||||
* use the timespec implementation.
|
||||
*/
|
||||
unsigned long
|
||||
timeval_to_jiffies(const struct timeval *value)
|
||||
{
|
||||
unsigned long sec = value->tv_sec;
|
||||
long usec = value->tv_usec;
|
||||
|
||||
if (sec >= MAX_SEC_IN_JIFFIES){
|
||||
sec = MAX_SEC_IN_JIFFIES;
|
||||
usec = 0;
|
||||
}
|
||||
return (((u64)sec * SEC_CONVERSION) +
|
||||
(((u64)usec * USEC_CONVERSION + USEC_ROUND) >>
|
||||
(USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
|
||||
return __timespec_to_jiffies(value->tv_sec,
|
||||
value->tv_usec * NSEC_PER_USEC);
|
||||
}
|
||||
EXPORT_SYMBOL(timeval_to_jiffies);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user