Skip to content

Commit c02d554

Browse files
ubizjakPeter Zijlstra
authored andcommitted
sched/core: Use try_cmpxchg in set_nr_{and_not,if}_polling
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 <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 1fcf54d commit c02d554

File tree

1 file changed

+9
-15
lines changed

1 file changed

+9
-15
lines changed

kernel/sched/core.c

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -873,15 +873,11 @@ static inline void hrtick_rq_init(struct rq *rq)
873873
({ \
874874
typeof(ptr) _ptr = (ptr); \
875875
typeof(mask) _mask = (mask); \
876-
typeof(*_ptr) _old, _val = *_ptr; \
876+
typeof(*_ptr) _val = *_ptr; \
877877
\
878-
for (;;) { \
879-
_old = cmpxchg(_ptr, _val, _val | _mask); \
880-
if (_old == _val) \
881-
break; \
882-
_val = _old; \
883-
} \
884-
_old; \
878+
do { \
879+
} while (!try_cmpxchg(_ptr, &_val, _val | _mask)); \
880+
_val; \
885881
})
886882

887883
#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG)
@@ -890,7 +886,7 @@ static inline void hrtick_rq_init(struct rq *rq)
890886
* this avoids any races wrt polling state changes and thereby avoids
891887
* spurious IPIs.
892888
*/
893-
static bool set_nr_and_not_polling(struct task_struct *p)
889+
static inline bool set_nr_and_not_polling(struct task_struct *p)
894890
{
895891
struct thread_info *ti = task_thread_info(p);
896892
return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG);
@@ -905,30 +901,28 @@ static bool set_nr_and_not_polling(struct task_struct *p)
905901
static bool set_nr_if_polling(struct task_struct *p)
906902
{
907903
struct thread_info *ti = task_thread_info(p);
908-
typeof(ti->flags) old, val = READ_ONCE(ti->flags);
904+
typeof(ti->flags) val = READ_ONCE(ti->flags);
909905

910906
for (;;) {
911907
if (!(val & _TIF_POLLING_NRFLAG))
912908
return false;
913909
if (val & _TIF_NEED_RESCHED)
914910
return true;
915-
old = cmpxchg(&ti->flags, val, val | _TIF_NEED_RESCHED);
916-
if (old == val)
911+
if (try_cmpxchg(&ti->flags, &val, val | _TIF_NEED_RESCHED))
917912
break;
918-
val = old;
919913
}
920914
return true;
921915
}
922916

923917
#else
924-
static bool set_nr_and_not_polling(struct task_struct *p)
918+
static inline bool set_nr_and_not_polling(struct task_struct *p)
925919
{
926920
set_tsk_need_resched(p);
927921
return true;
928922
}
929923

930924
#ifdef CONFIG_SMP
931-
static bool set_nr_if_polling(struct task_struct *p)
925+
static inline bool set_nr_if_polling(struct task_struct *p)
932926
{
933927
return false;
934928
}

0 commit comments

Comments
 (0)