summaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-01-11 04:02:40 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-01-11 04:02:40 +0000
commite47f00743fc4776491344f2c618cc8dc2c23bcbc (patch)
tree13e03a113a82a184c51c19c209867cfd3a59b3b9 /kernel/fork.c
parentb2ad5f821b1381492d792ca10b1eb7a107b48f14 (diff)
Merge with Linux 2.4.0.
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index f5d3a83df..99c1f2317 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -192,6 +192,8 @@ fail_nomem:
return retval;
}
+spinlock_t mmlist_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
+
#define allocate_mm() (kmem_cache_alloc(mm_cachep, SLAB_KERNEL))
#define free_mm(mm) (kmem_cache_free(mm_cachep, (mm)))
@@ -242,7 +244,9 @@ inline void __mmdrop(struct mm_struct *mm)
*/
void mmput(struct mm_struct *mm)
{
- if (atomic_dec_and_test(&mm->mm_users)) {
+ if (atomic_dec_and_lock(&mm->mm_users, &mmlist_lock)) {
+ list_del(&mm->mmlist);
+ spin_unlock(&mmlist_lock);
exit_mmap(mm);
mmdrop(mm);
}
@@ -272,9 +276,9 @@ void mm_release(void)
}
}
-static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
+static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
{
- struct mm_struct * mm;
+ struct mm_struct * mm, *oldmm;
int retval;
tsk->min_flt = tsk->maj_flt = 0;
@@ -289,12 +293,13 @@ static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
*
* We need to steal a active VM for that..
*/
- mm = current->mm;
- if (!mm)
+ oldmm = current->mm;
+ if (!oldmm)
return 0;
if (clone_flags & CLONE_VM) {
- atomic_inc(&mm->mm_users);
+ atomic_inc(&oldmm->mm_users);
+ mm = oldmm;
goto good_mm;
}
@@ -304,16 +309,25 @@ static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
goto fail_nomem;
/* Copy the current MM stuff.. */
- memcpy(mm, current->mm, sizeof(*mm));
+ memcpy(mm, oldmm, sizeof(*mm));
if (!mm_init(mm))
goto fail_nomem;
- tsk->mm = mm;
- tsk->active_mm = mm;
-
- down(&current->mm->mmap_sem);
+ down(&oldmm->mmap_sem);
retval = dup_mmap(mm);
- up(&current->mm->mmap_sem);
+ up(&oldmm->mmap_sem);
+
+ /*
+ * Add it to the mmlist after the parent.
+ *
+ * Doing it this way means that we can order
+ * the list, and fork() won't mess up the
+ * ordering significantly.
+ */
+ spin_lock(&mmlist_lock);
+ list_add(&mm->mmlist, &oldmm->mmlist);
+ spin_unlock(&mmlist_lock);
+
if (retval)
goto free_pt;