162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _LINUX_SCHED_MM_H 362306a36Sopenharmony_ci#define _LINUX_SCHED_MM_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/kernel.h> 662306a36Sopenharmony_ci#include <linux/atomic.h> 762306a36Sopenharmony_ci#include <linux/sched.h> 862306a36Sopenharmony_ci#include <linux/mm_types.h> 962306a36Sopenharmony_ci#include <linux/gfp.h> 1062306a36Sopenharmony_ci#include <linux/sync_core.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* 1362306a36Sopenharmony_ci * Routines for handling mm_structs 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_ciextern struct mm_struct *mm_alloc(void); 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/** 1862306a36Sopenharmony_ci * mmgrab() - Pin a &struct mm_struct. 1962306a36Sopenharmony_ci * @mm: The &struct mm_struct to pin. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * Make sure that @mm will not get freed even after the owning task 2262306a36Sopenharmony_ci * exits. This doesn't guarantee that the associated address space 2362306a36Sopenharmony_ci * will still exist later on and mmget_not_zero() has to be used before 2462306a36Sopenharmony_ci * accessing it. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * This is a preferred way to pin @mm for a longer/unbounded amount 2762306a36Sopenharmony_ci * of time. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Use mmdrop() to release the reference acquired by mmgrab(). 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * See also <Documentation/mm/active_mm.rst> for an in-depth explanation 3262306a36Sopenharmony_ci * of &mm_struct.mm_count vs &mm_struct.mm_users. 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_cistatic inline void mmgrab(struct mm_struct *mm) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci atomic_inc(&mm->mm_count); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic inline void smp_mb__after_mmgrab(void) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci smp_mb__after_atomic(); 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciextern void __mmdrop(struct mm_struct *mm); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic inline void mmdrop(struct mm_struct *mm) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci /* 4962306a36Sopenharmony_ci * The implicit full barrier implied by atomic_dec_and_test() is 5062306a36Sopenharmony_ci * required by the membarrier system call before returning to 5162306a36Sopenharmony_ci * user-space, after storing to rq->curr. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ci if (unlikely(atomic_dec_and_test(&mm->mm_count))) 5462306a36Sopenharmony_ci __mmdrop(mm); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#ifdef CONFIG_PREEMPT_RT 5862306a36Sopenharmony_ci/* 5962306a36Sopenharmony_ci * RCU callback for delayed mm drop. Not strictly RCU, but call_rcu() is 6062306a36Sopenharmony_ci * by far the least expensive way to do that. 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_cistatic inline void __mmdrop_delayed(struct rcu_head *rhp) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci struct mm_struct *mm = container_of(rhp, struct mm_struct, delayed_drop); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci __mmdrop(mm); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* 7062306a36Sopenharmony_ci * Invoked from finish_task_switch(). Delegates the heavy lifting on RT 7162306a36Sopenharmony_ci * kernels via RCU. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_cistatic inline void mmdrop_sched(struct mm_struct *mm) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci /* Provides a full memory barrier. See mmdrop() */ 7662306a36Sopenharmony_ci if (atomic_dec_and_test(&mm->mm_count)) 7762306a36Sopenharmony_ci call_rcu(&mm->delayed_drop, __mmdrop_delayed); 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci#else 8062306a36Sopenharmony_cistatic inline void mmdrop_sched(struct mm_struct *mm) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci mmdrop(mm); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci#endif 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* Helpers for lazy TLB mm refcounting */ 8762306a36Sopenharmony_cistatic inline void mmgrab_lazy_tlb(struct mm_struct *mm) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_MMU_LAZY_TLB_REFCOUNT)) 9062306a36Sopenharmony_ci mmgrab(mm); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic inline void mmdrop_lazy_tlb(struct mm_struct *mm) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_MMU_LAZY_TLB_REFCOUNT)) { 9662306a36Sopenharmony_ci mmdrop(mm); 9762306a36Sopenharmony_ci } else { 9862306a36Sopenharmony_ci /* 9962306a36Sopenharmony_ci * mmdrop_lazy_tlb must provide a full memory barrier, see the 10062306a36Sopenharmony_ci * membarrier comment finish_task_switch which relies on this. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ci smp_mb(); 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic inline void mmdrop_lazy_tlb_sched(struct mm_struct *mm) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_MMU_LAZY_TLB_REFCOUNT)) 10962306a36Sopenharmony_ci mmdrop_sched(mm); 11062306a36Sopenharmony_ci else 11162306a36Sopenharmony_ci smp_mb(); /* see mmdrop_lazy_tlb() above */ 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/** 11562306a36Sopenharmony_ci * mmget() - Pin the address space associated with a &struct mm_struct. 11662306a36Sopenharmony_ci * @mm: The address space to pin. 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci * Make sure that the address space of the given &struct mm_struct doesn't 11962306a36Sopenharmony_ci * go away. This does not protect against parts of the address space being 12062306a36Sopenharmony_ci * modified or freed, however. 12162306a36Sopenharmony_ci * 12262306a36Sopenharmony_ci * Never use this function to pin this address space for an 12362306a36Sopenharmony_ci * unbounded/indefinite amount of time. 12462306a36Sopenharmony_ci * 12562306a36Sopenharmony_ci * Use mmput() to release the reference acquired by mmget(). 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * See also <Documentation/mm/active_mm.rst> for an in-depth explanation 12862306a36Sopenharmony_ci * of &mm_struct.mm_count vs &mm_struct.mm_users. 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_cistatic inline void mmget(struct mm_struct *mm) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci atomic_inc(&mm->mm_users); 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic inline bool mmget_not_zero(struct mm_struct *mm) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci return atomic_inc_not_zero(&mm->mm_users); 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci/* mmput gets rid of the mappings and all user-space */ 14162306a36Sopenharmony_ciextern void mmput(struct mm_struct *); 14262306a36Sopenharmony_ci#ifdef CONFIG_MMU 14362306a36Sopenharmony_ci/* same as above but performs the slow path from the async context. Can 14462306a36Sopenharmony_ci * be called from the atomic context as well 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_civoid mmput_async(struct mm_struct *); 14762306a36Sopenharmony_ci#endif 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/* Grab a reference to a task's mm, if it is not already going away */ 15062306a36Sopenharmony_ciextern struct mm_struct *get_task_mm(struct task_struct *task); 15162306a36Sopenharmony_ci/* 15262306a36Sopenharmony_ci * Grab a reference to a task's mm, if it is not already going away 15362306a36Sopenharmony_ci * and ptrace_may_access with the mode parameter passed to it 15462306a36Sopenharmony_ci * succeeds. 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ciextern struct mm_struct *mm_access(struct task_struct *task, unsigned int mode); 15762306a36Sopenharmony_ci/* Remove the current tasks stale references to the old mm_struct on exit() */ 15862306a36Sopenharmony_ciextern void exit_mm_release(struct task_struct *, struct mm_struct *); 15962306a36Sopenharmony_ci/* Remove the current tasks stale references to the old mm_struct on exec() */ 16062306a36Sopenharmony_ciextern void exec_mm_release(struct task_struct *, struct mm_struct *); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci#ifdef CONFIG_MEMCG 16362306a36Sopenharmony_ciextern void mm_update_next_owner(struct mm_struct *mm); 16462306a36Sopenharmony_ci#else 16562306a36Sopenharmony_cistatic inline void mm_update_next_owner(struct mm_struct *mm) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci#endif /* CONFIG_MEMCG */ 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci#ifdef CONFIG_MMU 17162306a36Sopenharmony_ci#ifndef arch_get_mmap_end 17262306a36Sopenharmony_ci#define arch_get_mmap_end(addr, len, flags) (TASK_SIZE) 17362306a36Sopenharmony_ci#endif 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci#ifndef arch_get_mmap_base 17662306a36Sopenharmony_ci#define arch_get_mmap_base(addr, base) (base) 17762306a36Sopenharmony_ci#endif 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ciextern void arch_pick_mmap_layout(struct mm_struct *mm, 18062306a36Sopenharmony_ci struct rlimit *rlim_stack); 18162306a36Sopenharmony_ciextern unsigned long 18262306a36Sopenharmony_ciarch_get_unmapped_area(struct file *, unsigned long, unsigned long, 18362306a36Sopenharmony_ci unsigned long, unsigned long); 18462306a36Sopenharmony_ciextern unsigned long 18562306a36Sopenharmony_ciarch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, 18662306a36Sopenharmony_ci unsigned long len, unsigned long pgoff, 18762306a36Sopenharmony_ci unsigned long flags); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ciunsigned long 19062306a36Sopenharmony_cigeneric_get_unmapped_area(struct file *filp, unsigned long addr, 19162306a36Sopenharmony_ci unsigned long len, unsigned long pgoff, 19262306a36Sopenharmony_ci unsigned long flags); 19362306a36Sopenharmony_ciunsigned long 19462306a36Sopenharmony_cigeneric_get_unmapped_area_topdown(struct file *filp, unsigned long addr, 19562306a36Sopenharmony_ci unsigned long len, unsigned long pgoff, 19662306a36Sopenharmony_ci unsigned long flags); 19762306a36Sopenharmony_ci#else 19862306a36Sopenharmony_cistatic inline void arch_pick_mmap_layout(struct mm_struct *mm, 19962306a36Sopenharmony_ci struct rlimit *rlim_stack) {} 20062306a36Sopenharmony_ci#endif 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic inline bool in_vfork(struct task_struct *tsk) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci bool ret; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci /* 20762306a36Sopenharmony_ci * need RCU to access ->real_parent if CLONE_VM was used along with 20862306a36Sopenharmony_ci * CLONE_PARENT. 20962306a36Sopenharmony_ci * 21062306a36Sopenharmony_ci * We check real_parent->mm == tsk->mm because CLONE_VFORK does not 21162306a36Sopenharmony_ci * imply CLONE_VM 21262306a36Sopenharmony_ci * 21362306a36Sopenharmony_ci * CLONE_VFORK can be used with CLONE_PARENT/CLONE_THREAD and thus 21462306a36Sopenharmony_ci * ->real_parent is not necessarily the task doing vfork(), so in 21562306a36Sopenharmony_ci * theory we can't rely on task_lock() if we want to dereference it. 21662306a36Sopenharmony_ci * 21762306a36Sopenharmony_ci * And in this case we can't trust the real_parent->mm == tsk->mm 21862306a36Sopenharmony_ci * check, it can be false negative. But we do not care, if init or 21962306a36Sopenharmony_ci * another oom-unkillable task does this it should blame itself. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ci rcu_read_lock(); 22262306a36Sopenharmony_ci ret = tsk->vfork_done && 22362306a36Sopenharmony_ci rcu_dereference(tsk->real_parent)->mm == tsk->mm; 22462306a36Sopenharmony_ci rcu_read_unlock(); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci return ret; 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci/* 23062306a36Sopenharmony_ci * Applies per-task gfp context to the given allocation flags. 23162306a36Sopenharmony_ci * PF_MEMALLOC_NOIO implies GFP_NOIO 23262306a36Sopenharmony_ci * PF_MEMALLOC_NOFS implies GFP_NOFS 23362306a36Sopenharmony_ci * PF_MEMALLOC_PIN implies !GFP_MOVABLE 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_cistatic inline gfp_t current_gfp_context(gfp_t flags) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci unsigned int pflags = READ_ONCE(current->flags); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (unlikely(pflags & (PF_MEMALLOC_NOIO | PF_MEMALLOC_NOFS | PF_MEMALLOC_PIN))) { 24062306a36Sopenharmony_ci /* 24162306a36Sopenharmony_ci * NOIO implies both NOIO and NOFS and it is a weaker context 24262306a36Sopenharmony_ci * so always make sure it makes precedence 24362306a36Sopenharmony_ci */ 24462306a36Sopenharmony_ci if (pflags & PF_MEMALLOC_NOIO) 24562306a36Sopenharmony_ci flags &= ~(__GFP_IO | __GFP_FS); 24662306a36Sopenharmony_ci else if (pflags & PF_MEMALLOC_NOFS) 24762306a36Sopenharmony_ci flags &= ~__GFP_FS; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (pflags & PF_MEMALLOC_PIN) 25062306a36Sopenharmony_ci flags &= ~__GFP_MOVABLE; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci return flags; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci#ifdef CONFIG_LOCKDEP 25662306a36Sopenharmony_ciextern void __fs_reclaim_acquire(unsigned long ip); 25762306a36Sopenharmony_ciextern void __fs_reclaim_release(unsigned long ip); 25862306a36Sopenharmony_ciextern void fs_reclaim_acquire(gfp_t gfp_mask); 25962306a36Sopenharmony_ciextern void fs_reclaim_release(gfp_t gfp_mask); 26062306a36Sopenharmony_ci#else 26162306a36Sopenharmony_cistatic inline void __fs_reclaim_acquire(unsigned long ip) { } 26262306a36Sopenharmony_cistatic inline void __fs_reclaim_release(unsigned long ip) { } 26362306a36Sopenharmony_cistatic inline void fs_reclaim_acquire(gfp_t gfp_mask) { } 26462306a36Sopenharmony_cistatic inline void fs_reclaim_release(gfp_t gfp_mask) { } 26562306a36Sopenharmony_ci#endif 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci/* Any memory-allocation retry loop should use 26862306a36Sopenharmony_ci * memalloc_retry_wait(), and pass the flags for the most 26962306a36Sopenharmony_ci * constrained allocation attempt that might have failed. 27062306a36Sopenharmony_ci * This provides useful documentation of where loops are, 27162306a36Sopenharmony_ci * and a central place to fine tune the waiting as the MM 27262306a36Sopenharmony_ci * implementation changes. 27362306a36Sopenharmony_ci */ 27462306a36Sopenharmony_cistatic inline void memalloc_retry_wait(gfp_t gfp_flags) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci /* We use io_schedule_timeout because waiting for memory 27762306a36Sopenharmony_ci * typically included waiting for dirty pages to be 27862306a36Sopenharmony_ci * written out, which requires IO. 27962306a36Sopenharmony_ci */ 28062306a36Sopenharmony_ci __set_current_state(TASK_UNINTERRUPTIBLE); 28162306a36Sopenharmony_ci gfp_flags = current_gfp_context(gfp_flags); 28262306a36Sopenharmony_ci if (gfpflags_allow_blocking(gfp_flags) && 28362306a36Sopenharmony_ci !(gfp_flags & __GFP_NORETRY)) 28462306a36Sopenharmony_ci /* Probably waited already, no need for much more */ 28562306a36Sopenharmony_ci io_schedule_timeout(1); 28662306a36Sopenharmony_ci else 28762306a36Sopenharmony_ci /* Probably didn't wait, and has now released a lock, 28862306a36Sopenharmony_ci * so now is a good time to wait 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_ci io_schedule_timeout(HZ/50); 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci/** 29462306a36Sopenharmony_ci * might_alloc - Mark possible allocation sites 29562306a36Sopenharmony_ci * @gfp_mask: gfp_t flags that would be used to allocate 29662306a36Sopenharmony_ci * 29762306a36Sopenharmony_ci * Similar to might_sleep() and other annotations, this can be used in functions 29862306a36Sopenharmony_ci * that might allocate, but often don't. Compiles to nothing without 29962306a36Sopenharmony_ci * CONFIG_LOCKDEP. Includes a conditional might_sleep() if @gfp allows blocking. 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_cistatic inline void might_alloc(gfp_t gfp_mask) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci fs_reclaim_acquire(gfp_mask); 30462306a36Sopenharmony_ci fs_reclaim_release(gfp_mask); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci might_sleep_if(gfpflags_allow_blocking(gfp_mask)); 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci/** 31062306a36Sopenharmony_ci * memalloc_noio_save - Marks implicit GFP_NOIO allocation scope. 31162306a36Sopenharmony_ci * 31262306a36Sopenharmony_ci * This functions marks the beginning of the GFP_NOIO allocation scope. 31362306a36Sopenharmony_ci * All further allocations will implicitly drop __GFP_IO flag and so 31462306a36Sopenharmony_ci * they are safe for the IO critical section from the allocation recursion 31562306a36Sopenharmony_ci * point of view. Use memalloc_noio_restore to end the scope with flags 31662306a36Sopenharmony_ci * returned by this function. 31762306a36Sopenharmony_ci * 31862306a36Sopenharmony_ci * This function is safe to be used from any context. 31962306a36Sopenharmony_ci */ 32062306a36Sopenharmony_cistatic inline unsigned int memalloc_noio_save(void) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci unsigned int flags = current->flags & PF_MEMALLOC_NOIO; 32362306a36Sopenharmony_ci current->flags |= PF_MEMALLOC_NOIO; 32462306a36Sopenharmony_ci return flags; 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci/** 32862306a36Sopenharmony_ci * memalloc_noio_restore - Ends the implicit GFP_NOIO scope. 32962306a36Sopenharmony_ci * @flags: Flags to restore. 33062306a36Sopenharmony_ci * 33162306a36Sopenharmony_ci * Ends the implicit GFP_NOIO scope started by memalloc_noio_save function. 33262306a36Sopenharmony_ci * Always make sure that the given flags is the return value from the 33362306a36Sopenharmony_ci * pairing memalloc_noio_save call. 33462306a36Sopenharmony_ci */ 33562306a36Sopenharmony_cistatic inline void memalloc_noio_restore(unsigned int flags) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci current->flags = (current->flags & ~PF_MEMALLOC_NOIO) | flags; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci/** 34162306a36Sopenharmony_ci * memalloc_nofs_save - Marks implicit GFP_NOFS allocation scope. 34262306a36Sopenharmony_ci * 34362306a36Sopenharmony_ci * This functions marks the beginning of the GFP_NOFS allocation scope. 34462306a36Sopenharmony_ci * All further allocations will implicitly drop __GFP_FS flag and so 34562306a36Sopenharmony_ci * they are safe for the FS critical section from the allocation recursion 34662306a36Sopenharmony_ci * point of view. Use memalloc_nofs_restore to end the scope with flags 34762306a36Sopenharmony_ci * returned by this function. 34862306a36Sopenharmony_ci * 34962306a36Sopenharmony_ci * This function is safe to be used from any context. 35062306a36Sopenharmony_ci */ 35162306a36Sopenharmony_cistatic inline unsigned int memalloc_nofs_save(void) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci unsigned int flags = current->flags & PF_MEMALLOC_NOFS; 35462306a36Sopenharmony_ci current->flags |= PF_MEMALLOC_NOFS; 35562306a36Sopenharmony_ci return flags; 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci/** 35962306a36Sopenharmony_ci * memalloc_nofs_restore - Ends the implicit GFP_NOFS scope. 36062306a36Sopenharmony_ci * @flags: Flags to restore. 36162306a36Sopenharmony_ci * 36262306a36Sopenharmony_ci * Ends the implicit GFP_NOFS scope started by memalloc_nofs_save function. 36362306a36Sopenharmony_ci * Always make sure that the given flags is the return value from the 36462306a36Sopenharmony_ci * pairing memalloc_nofs_save call. 36562306a36Sopenharmony_ci */ 36662306a36Sopenharmony_cistatic inline void memalloc_nofs_restore(unsigned int flags) 36762306a36Sopenharmony_ci{ 36862306a36Sopenharmony_ci current->flags = (current->flags & ~PF_MEMALLOC_NOFS) | flags; 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic inline unsigned int memalloc_noreclaim_save(void) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci unsigned int flags = current->flags & PF_MEMALLOC; 37462306a36Sopenharmony_ci current->flags |= PF_MEMALLOC; 37562306a36Sopenharmony_ci return flags; 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic inline void memalloc_noreclaim_restore(unsigned int flags) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci current->flags = (current->flags & ~PF_MEMALLOC) | flags; 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic inline unsigned int memalloc_pin_save(void) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci unsigned int flags = current->flags & PF_MEMALLOC_PIN; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci current->flags |= PF_MEMALLOC_PIN; 38862306a36Sopenharmony_ci return flags; 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic inline void memalloc_pin_restore(unsigned int flags) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci current->flags = (current->flags & ~PF_MEMALLOC_PIN) | flags; 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci#ifdef CONFIG_MEMCG 39762306a36Sopenharmony_ciDECLARE_PER_CPU(struct mem_cgroup *, int_active_memcg); 39862306a36Sopenharmony_ci/** 39962306a36Sopenharmony_ci * set_active_memcg - Starts the remote memcg charging scope. 40062306a36Sopenharmony_ci * @memcg: memcg to charge. 40162306a36Sopenharmony_ci * 40262306a36Sopenharmony_ci * This function marks the beginning of the remote memcg charging scope. All the 40362306a36Sopenharmony_ci * __GFP_ACCOUNT allocations till the end of the scope will be charged to the 40462306a36Sopenharmony_ci * given memcg. 40562306a36Sopenharmony_ci * 40662306a36Sopenharmony_ci * NOTE: This function can nest. Users must save the return value and 40762306a36Sopenharmony_ci * reset the previous value after their own charging scope is over. 40862306a36Sopenharmony_ci */ 40962306a36Sopenharmony_cistatic inline struct mem_cgroup * 41062306a36Sopenharmony_ciset_active_memcg(struct mem_cgroup *memcg) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci struct mem_cgroup *old; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci if (!in_task()) { 41562306a36Sopenharmony_ci old = this_cpu_read(int_active_memcg); 41662306a36Sopenharmony_ci this_cpu_write(int_active_memcg, memcg); 41762306a36Sopenharmony_ci } else { 41862306a36Sopenharmony_ci old = current->active_memcg; 41962306a36Sopenharmony_ci current->active_memcg = memcg; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci return old; 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci#else 42562306a36Sopenharmony_cistatic inline struct mem_cgroup * 42662306a36Sopenharmony_ciset_active_memcg(struct mem_cgroup *memcg) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci return NULL; 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci#endif 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci#ifdef CONFIG_MEMBARRIER 43362306a36Sopenharmony_cienum { 43462306a36Sopenharmony_ci MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY = (1U << 0), 43562306a36Sopenharmony_ci MEMBARRIER_STATE_PRIVATE_EXPEDITED = (1U << 1), 43662306a36Sopenharmony_ci MEMBARRIER_STATE_GLOBAL_EXPEDITED_READY = (1U << 2), 43762306a36Sopenharmony_ci MEMBARRIER_STATE_GLOBAL_EXPEDITED = (1U << 3), 43862306a36Sopenharmony_ci MEMBARRIER_STATE_PRIVATE_EXPEDITED_SYNC_CORE_READY = (1U << 4), 43962306a36Sopenharmony_ci MEMBARRIER_STATE_PRIVATE_EXPEDITED_SYNC_CORE = (1U << 5), 44062306a36Sopenharmony_ci MEMBARRIER_STATE_PRIVATE_EXPEDITED_RSEQ_READY = (1U << 6), 44162306a36Sopenharmony_ci MEMBARRIER_STATE_PRIVATE_EXPEDITED_RSEQ = (1U << 7), 44262306a36Sopenharmony_ci}; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cienum { 44562306a36Sopenharmony_ci MEMBARRIER_FLAG_SYNC_CORE = (1U << 0), 44662306a36Sopenharmony_ci MEMBARRIER_FLAG_RSEQ = (1U << 1), 44762306a36Sopenharmony_ci}; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci#ifdef CONFIG_ARCH_HAS_MEMBARRIER_CALLBACKS 45062306a36Sopenharmony_ci#include <asm/membarrier.h> 45162306a36Sopenharmony_ci#endif 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_cistatic inline void membarrier_mm_sync_core_before_usermode(struct mm_struct *mm) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci if (current->mm != mm) 45662306a36Sopenharmony_ci return; 45762306a36Sopenharmony_ci if (likely(!(atomic_read(&mm->membarrier_state) & 45862306a36Sopenharmony_ci MEMBARRIER_STATE_PRIVATE_EXPEDITED_SYNC_CORE))) 45962306a36Sopenharmony_ci return; 46062306a36Sopenharmony_ci sync_core_before_usermode(); 46162306a36Sopenharmony_ci} 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ciextern void membarrier_exec_mmap(struct mm_struct *mm); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ciextern void membarrier_update_current_mm(struct mm_struct *next_mm); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci#else 46862306a36Sopenharmony_ci#ifdef CONFIG_ARCH_HAS_MEMBARRIER_CALLBACKS 46962306a36Sopenharmony_cistatic inline void membarrier_arch_switch_mm(struct mm_struct *prev, 47062306a36Sopenharmony_ci struct mm_struct *next, 47162306a36Sopenharmony_ci struct task_struct *tsk) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci#endif 47562306a36Sopenharmony_cistatic inline void membarrier_exec_mmap(struct mm_struct *mm) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_cistatic inline void membarrier_mm_sync_core_before_usermode(struct mm_struct *mm) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci} 48162306a36Sopenharmony_cistatic inline void membarrier_update_current_mm(struct mm_struct *next_mm) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci#endif 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci#endif /* _LINUX_SCHED_MM_H */ 487