Merge tag 'microblaze-4.16-rc1' of git://git.monstr.eu/linux-2.6-microblaze
[linux-2.6-microblaze.git] / include / linux / sched / mm.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_SCHED_MM_H
3 #define _LINUX_SCHED_MM_H
4
5 #include <linux/kernel.h>
6 #include <linux/atomic.h>
7 #include <linux/sched.h>
8 #include <linux/mm_types.h>
9 #include <linux/gfp.h>
10
11 /*
12  * Routines for handling mm_structs
13  */
14 extern struct mm_struct *mm_alloc(void);
15
16 /**
17  * mmgrab() - Pin a &struct mm_struct.
18  * @mm: The &struct mm_struct to pin.
19  *
20  * Make sure that @mm will not get freed even after the owning task
21  * exits. This doesn't guarantee that the associated address space
22  * will still exist later on and mmget_not_zero() has to be used before
23  * accessing it.
24  *
25  * This is a preferred way to to pin @mm for a longer/unbounded amount
26  * of time.
27  *
28  * Use mmdrop() to release the reference acquired by mmgrab().
29  *
30  * See also <Documentation/vm/active_mm.txt> for an in-depth explanation
31  * of &mm_struct.mm_count vs &mm_struct.mm_users.
32  */
33 static inline void mmgrab(struct mm_struct *mm)
34 {
35         atomic_inc(&mm->mm_count);
36 }
37
38 extern void mmdrop(struct mm_struct *mm);
39
40 /**
41  * mmget() - Pin the address space associated with a &struct mm_struct.
42  * @mm: The address space to pin.
43  *
44  * Make sure that the address space of the given &struct mm_struct doesn't
45  * go away. This does not protect against parts of the address space being
46  * modified or freed, however.
47  *
48  * Never use this function to pin this address space for an
49  * unbounded/indefinite amount of time.
50  *
51  * Use mmput() to release the reference acquired by mmget().
52  *
53  * See also <Documentation/vm/active_mm.txt> for an in-depth explanation
54  * of &mm_struct.mm_count vs &mm_struct.mm_users.
55  */
56 static inline void mmget(struct mm_struct *mm)
57 {
58         atomic_inc(&mm->mm_users);
59 }
60
61 static inline bool mmget_not_zero(struct mm_struct *mm)
62 {
63         return atomic_inc_not_zero(&mm->mm_users);
64 }
65
66 /* mmput gets rid of the mappings and all user-space */
67 extern void mmput(struct mm_struct *);
68 #ifdef CONFIG_MMU
69 /* same as above but performs the slow path from the async context. Can
70  * be called from the atomic context as well
71  */
72 void mmput_async(struct mm_struct *);
73 #endif
74
75 /* Grab a reference to a task's mm, if it is not already going away */
76 extern struct mm_struct *get_task_mm(struct task_struct *task);
77 /*
78  * Grab a reference to a task's mm, if it is not already going away
79  * and ptrace_may_access with the mode parameter passed to it
80  * succeeds.
81  */
82 extern struct mm_struct *mm_access(struct task_struct *task, unsigned int mode);
83 /* Remove the current tasks stale references to the old mm_struct */
84 extern void mm_release(struct task_struct *, struct mm_struct *);
85
86 #ifdef CONFIG_MEMCG
87 extern void mm_update_next_owner(struct mm_struct *mm);
88 #else
89 static inline void mm_update_next_owner(struct mm_struct *mm)
90 {
91 }
92 #endif /* CONFIG_MEMCG */
93
94 #ifdef CONFIG_MMU
95 extern void arch_pick_mmap_layout(struct mm_struct *mm);
96 extern unsigned long
97 arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
98                        unsigned long, unsigned long);
99 extern unsigned long
100 arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
101                           unsigned long len, unsigned long pgoff,
102                           unsigned long flags);
103 #else
104 static inline void arch_pick_mmap_layout(struct mm_struct *mm) {}
105 #endif
106
107 static inline bool in_vfork(struct task_struct *tsk)
108 {
109         bool ret;
110
111         /*
112          * need RCU to access ->real_parent if CLONE_VM was used along with
113          * CLONE_PARENT.
114          *
115          * We check real_parent->mm == tsk->mm because CLONE_VFORK does not
116          * imply CLONE_VM
117          *
118          * CLONE_VFORK can be used with CLONE_PARENT/CLONE_THREAD and thus
119          * ->real_parent is not necessarily the task doing vfork(), so in
120          * theory we can't rely on task_lock() if we want to dereference it.
121          *
122          * And in this case we can't trust the real_parent->mm == tsk->mm
123          * check, it can be false negative. But we do not care, if init or
124          * another oom-unkillable task does this it should blame itself.
125          */
126         rcu_read_lock();
127         ret = tsk->vfork_done && tsk->real_parent->mm == tsk->mm;
128         rcu_read_unlock();
129
130         return ret;
131 }
132
133 /*
134  * Applies per-task gfp context to the given allocation flags.
135  * PF_MEMALLOC_NOIO implies GFP_NOIO
136  * PF_MEMALLOC_NOFS implies GFP_NOFS
137  */
138 static inline gfp_t current_gfp_context(gfp_t flags)
139 {
140         /*
141          * NOIO implies both NOIO and NOFS and it is a weaker context
142          * so always make sure it makes precendence
143          */
144         if (unlikely(current->flags & PF_MEMALLOC_NOIO))
145                 flags &= ~(__GFP_IO | __GFP_FS);
146         else if (unlikely(current->flags & PF_MEMALLOC_NOFS))
147                 flags &= ~__GFP_FS;
148         return flags;
149 }
150
151 #ifdef CONFIG_LOCKDEP
152 extern void fs_reclaim_acquire(gfp_t gfp_mask);
153 extern void fs_reclaim_release(gfp_t gfp_mask);
154 #else
155 static inline void fs_reclaim_acquire(gfp_t gfp_mask) { }
156 static inline void fs_reclaim_release(gfp_t gfp_mask) { }
157 #endif
158
159 static inline unsigned int memalloc_noio_save(void)
160 {
161         unsigned int flags = current->flags & PF_MEMALLOC_NOIO;
162         current->flags |= PF_MEMALLOC_NOIO;
163         return flags;
164 }
165
166 static inline void memalloc_noio_restore(unsigned int flags)
167 {
168         current->flags = (current->flags & ~PF_MEMALLOC_NOIO) | flags;
169 }
170
171 static inline unsigned int memalloc_nofs_save(void)
172 {
173         unsigned int flags = current->flags & PF_MEMALLOC_NOFS;
174         current->flags |= PF_MEMALLOC_NOFS;
175         return flags;
176 }
177
178 static inline void memalloc_nofs_restore(unsigned int flags)
179 {
180         current->flags = (current->flags & ~PF_MEMALLOC_NOFS) | flags;
181 }
182
183 static inline unsigned int memalloc_noreclaim_save(void)
184 {
185         unsigned int flags = current->flags & PF_MEMALLOC;
186         current->flags |= PF_MEMALLOC;
187         return flags;
188 }
189
190 static inline void memalloc_noreclaim_restore(unsigned int flags)
191 {
192         current->flags = (current->flags & ~PF_MEMALLOC) | flags;
193 }
194
195 #ifdef CONFIG_MEMBARRIER
196 enum {
197         MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY        = (1U << 0),
198         MEMBARRIER_STATE_SWITCH_MM                      = (1U << 1),
199 };
200
201 static inline void membarrier_execve(struct task_struct *t)
202 {
203         atomic_set(&t->mm->membarrier_state, 0);
204 }
205 #else
206 static inline void membarrier_execve(struct task_struct *t)
207 {
208 }
209 #endif
210
211 #endif /* _LINUX_SCHED_MM_H */