[PATCH 09/13] linux: nptl: Replace lll_futex_{timed_}wait by futex-internal.h
Adhemerval Zanella
adhemerval.zanella@linaro.org
Wed Nov 25 17:19:37 GMT 2020
On 25/11/2020 12:46, Mike Crowe wrote:
> On Wednesday 25 November 2020 at 12:40:46 -0300, Adhemerval Zanella wrote:
>>
>>
>> On 25/11/2020 12:32, Mike Crowe wrote:
>>> On Monday 23 November 2020 at 16:52:52 -0300, Adhemerval Zanella wrote:
>>>> The idea is to make NPTL implementation to use on the functions
>>>> provided by futex-internal.h.
>>>>
>>>> Checked on x86_64-linux-gnu and i686-linux-gnu.
>>>> ---
>>>> nptl/lowlevellock.c | 6 +++---
>>>> nptl/pthread_mutex_lock.c | 9 +++++----
>>>> nptl/pthread_mutex_setprioceiling.c | 5 +++--
>>>> nptl/pthread_mutex_timedlock.c | 6 +++---
>>>> 4 files changed, 14 insertions(+), 12 deletions(-)
>>>
>>> [snip]
>>>
>>>> diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
>>>> index e643eab258..343acf6107 100644
>>>> --- a/nptl/pthread_mutex_timedlock.c
>>>> +++ b/nptl/pthread_mutex_timedlock.c
>>>> @@ -561,9 +561,9 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
>>>> goto failpp;
>>>> }
>>>>
>>>> - lll_futex_timed_wait (&mutex->__data.__lock,
>>>> - ceilval | 2, &rt,
>>>> - PTHREAD_MUTEX_PSHARED (mutex));
>>>> + __futex_abstimed_wait64 (
>>>> + (unsigned int *) &mutex->__data.__lock, clockid,
>>>> + ceilval | 2, &rt, PTHREAD_MUTEX_PSHARED (mutex));
>>>
>>> I think you've replaced the lll_futex_timed_wait call that expects a
>>> relative timeout with a __futex_abstimed_wait64 call that expects an
>>> absolute timeout, yet you still appear to be passing the relative timeout.
>>>
>>> However, it turns out that the implementation for the
>>> PTHREAD_MUTEX_PP_RECURSIVE_NP and friends case appears to be have been
>>> completely broken with clockid != CLOCK_REALTIME ever since I added it in
>>> 9d20e22e46d891b929a72b0f35586e079eb083fd anyway since the relative timeout
>>> is calculated by calling __clock_gettime64(CLOCK_REALTIME) (although at the
>>> time this was a less obvious __gettimeofday call.)
>>>
>>> I'll work on writing some test cases for the those types of mutex in the
>>> hope of catching both flaws before fixing them.
>>
>> Indeed, there is no need to calculate the relative timeout anymore. I think
>> the fix below should pass the absolute timeout directly. I will check
>> a possible regression tests as well.
>
> OK. I won't then. Thanks.
>
>> diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
>> index aaaafa21ce..86c5f4446e 100644
>> --- a/nptl/pthread_mutex_timedlock.c
>> +++ b/nptl/pthread_mutex_timedlock.c
>> @@ -508,7 +508,6 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
>> if (__pthread_current_priority () > ceiling)
>> {
>> result = EINVAL;
>> - failpp:
>> if (oldprio != -1)
>> __pthread_tpp_change_priority (oldprio, -1);
>> return result;
>> @@ -540,37 +539,9 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
>>
>> if (oldval != ceilval)
>> {
>> - /* Reject invalid timeouts. */
>> - if (! valid_nanoseconds (abstime->tv_nsec))
>> - {
>> - result = EINVAL;
>> - goto failpp;
>> - }
>
> If this is removed then is there a risk of getting into a busy loop if
> someone passes a bogus timespec? (Regardless of the answer, it makes sense
> to ensure that is tested somehow.)
The minimum supported kernel already does the same check on the futex call
(source for Linux 3.2):
2690 SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
2691 struct timespec __user *, utime, u32 __user *, uaddr2,
2692 u32, val3)
2693 {
2694 struct timespec ts;
2695 ktime_t t, *tp = NULL;
2696 u32 val2 = 0;
2697 int cmd = op & FUTEX_CMD_MASK;
2698
2699 if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
2700 cmd == FUTEX_WAIT_BITSET ||
2701 cmd == FUTEX_WAIT_REQUEUE_PI)) {
2702 if (copy_from_user(&ts, utime, sizeof(ts)) != 0)
2703 return -EFAULT;
2704 if (!timespec_valid(&ts))
2705 return -EINVAL;
2706
2707 t = timespec_to_ktime(ts);
2708 if (cmd == FUTEX_WAIT)
2709 t = ktime_add_safe(ktime_get(), t);
2710 tp = &t;
2711 }
113 #define timespec_valid(ts) \
114 (((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC))
So it will return EINVAL for bogus timespec.
More information about the Libc-alpha
mailing list