mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
mm: factor out can_spin_trylock()
Deduplicate checks for whether the current context is safe for spin_trylock(). Does this function really belong in mm/internal.h or is it generic? Not sure. If someone ends up duplicating this logic elsewhere in the kernel, that would be a shame. But if it goes in some generic header, someone treats it as documentation about where it's guaranteed safe to spin_trylock(), and then it emerges that there are other subtle preconditions that didn't affect the mm usecase, that would be worse. So, just be conservative and keep it local. Link: https://lore.kernel.org/20260703-alloc-trylock-v5-18-c87b714e19d3@google.com Signed-off-by: Brendan Jackman <jackmanb@google.com> Suggested-by: Harry Yoo <harry@kernel.org> Link: https://lore.kernel.org/all/397859cb-b127-4cc6-9c71-044afc99bf0c@kernel.org/ Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org> Reviewed-by: Harry Yoo (Oracle) <harry@kernel.org> Reviewed-by: Zi Yan <ziy@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
5df11ba0eb
commit
3a01af8281
|
|
@ -1713,4 +1713,27 @@ static inline void mm_prepare_for_swap_entries(struct mm_struct *mm)
|
|||
}
|
||||
}
|
||||
|
||||
static inline bool can_spin_trylock(void)
|
||||
{
|
||||
/*
|
||||
* In PREEMPT_RT spin_trylock() will call raw_spin_lock() which is
|
||||
* unsafe in NMI. If spin_trylock() is called from hard IRQ the current
|
||||
* task may be waiting for one rt_spin_lock, but rt_spin_trylock() will
|
||||
* mark the task as the owner of another rt_spin_lock which will
|
||||
* confuse PI logic, so return immediately if called from hard IRQ or
|
||||
* NMI.
|
||||
*
|
||||
* Note, irqs_disabled() case is ok. spin_trylock() can be called
|
||||
* from raw_spin_lock_irqsave region.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT) && (in_nmi() || in_hardirq()))
|
||||
return false;
|
||||
|
||||
/* On UP, spin_trylock() always succeeds even when it is locked */
|
||||
if (!IS_ENABLED(CONFIG_SMP) && in_nmi())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* __MM_INTERNAL_H */
|
||||
|
|
|
|||
|
|
@ -5291,22 +5291,7 @@ static inline bool alloc_order_allowed(gfp_t gfp, unsigned int order,
|
|||
|
||||
static inline bool alloc_nolock_allowed(void)
|
||||
{
|
||||
/*
|
||||
* In PREEMPT_RT spin_trylock() will call raw_spin_lock() which is
|
||||
* unsafe in NMI. If spin_trylock() is called from hard IRQ the current
|
||||
* task may be waiting for one rt_spin_lock, but rt_spin_trylock() will
|
||||
* mark the task as the owner of another rt_spin_lock which will
|
||||
* confuse PI logic, so return immediately if called from hard IRQ or
|
||||
* NMI.
|
||||
*
|
||||
* Note, irqs_disabled() case is ok. This function can be called
|
||||
* from raw_spin_lock_irqsave region.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT) && (in_nmi() || in_hardirq()))
|
||||
return false;
|
||||
|
||||
/* On UP, spin_trylock() always succeeds even when it is locked */
|
||||
if (!IS_ENABLED(CONFIG_SMP) && in_nmi())
|
||||
if (!can_spin_trylock())
|
||||
return false;
|
||||
|
||||
/* Bailout, since _deferred_grow_zone() needs to take a lock */
|
||||
|
|
|
|||
10
mm/slub.c
10
mm/slub.c
|
|
@ -5380,15 +5380,7 @@ static void *__kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_f
|
|||
if (unlikely(!size))
|
||||
return ZERO_SIZE_PTR;
|
||||
|
||||
/*
|
||||
* See the comment for the same check in
|
||||
* alloc_frozen_pages_nolock_noprof()
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT) && (in_nmi() || in_hardirq()))
|
||||
return NULL;
|
||||
|
||||
/* On UP, spin_trylock() always succeeds even when it is locked */
|
||||
if (!IS_ENABLED(CONFIG_SMP) && in_nmi())
|
||||
if (!can_spin_trylock())
|
||||
return NULL;
|
||||
|
||||
retry:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user