Skip to content

Commit

Permalink
sched/core: Use try_cmpxchg in set_nr_{and_not,if}_polling
Browse files Browse the repository at this point in the history
Use try_cmpxchg instead of cmpxchg (*ptr, old, new) != old in
set_nr_{and_not,if}_polling. x86 cmpxchg returns success in ZF flag,
so this change saves a compare after cmpxchg.

The definition of cmpxchg based fetch_or was changed in the
same way as atomic_fetch_##op definitions were changed
in e6790e4.

Also declare these two functions as inline to ensure inlining. In the
case of set_nr_and_not_polling, the compiler (gcc) tries to outsmart
itself by constructing the boolean return value with logic operations
on the fetched value, and these extra operations enlarge the function
over the inlining threshold value.

Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20220629151552.6015-1-ubizjak@gmail.com
  • Loading branch information
Uros Bizjak authored and Peter Zijlstra committed Jul 4, 2022
1 parent 1fcf54d commit c02d554
Showing 1 changed file with 9 additions and 15 deletions.
24 changes: 9 additions & 15 deletions kernel/sched/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -873,15 +873,11 @@ static inline void hrtick_rq_init(struct rq *rq)
({ \
typeof(ptr) _ptr = (ptr); \
typeof(mask) _mask = (mask); \
typeof(*_ptr) _old, _val = *_ptr; \
typeof(*_ptr) _val = *_ptr; \
\
for (;;) { \
_old = cmpxchg(_ptr, _val, _val | _mask); \
if (_old == _val) \
break; \
_val = _old; \
} \
_old; \
do { \
} while (!try_cmpxchg(_ptr, &_val, _val | _mask)); \
_val; \
})

#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG)
Expand All @@ -890,7 +886,7 @@ static inline void hrtick_rq_init(struct rq *rq)
* this avoids any races wrt polling state changes and thereby avoids
* spurious IPIs.
*/
static bool set_nr_and_not_polling(struct task_struct *p)
static inline bool set_nr_and_not_polling(struct task_struct *p)
{
struct thread_info *ti = task_thread_info(p);
return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG);
Expand All @@ -905,30 +901,28 @@ static bool set_nr_and_not_polling(struct task_struct *p)
static bool set_nr_if_polling(struct task_struct *p)
{
struct thread_info *ti = task_thread_info(p);
typeof(ti->flags) old, val = READ_ONCE(ti->flags);
typeof(ti->flags) val = READ_ONCE(ti->flags);

for (;;) {
if (!(val & _TIF_POLLING_NRFLAG))
return false;
if (val & _TIF_NEED_RESCHED)
return true;
old = cmpxchg(&ti->flags, val, val | _TIF_NEED_RESCHED);
if (old == val)
if (try_cmpxchg(&ti->flags, &val, val | _TIF_NEED_RESCHED))
break;
val = old;
}
return true;
}

#else
static bool set_nr_and_not_polling(struct task_struct *p)
static inline bool set_nr_and_not_polling(struct task_struct *p)
{
set_tsk_need_resched(p);
return true;
}

#ifdef CONFIG_SMP
static bool set_nr_if_polling(struct task_struct *p)
static inline bool set_nr_if_polling(struct task_struct *p)
{
return false;
}
Expand Down

0 comments on commit c02d554

Please sign in to comment.