From 456f17cd1a2873b3e83cee85bcb30708037cb4e8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 13 Aug 2002 00:36:37 -0700 Subject: [PATCH] [PATCH] user-vm-unlock-2.5.31-A2 This implements CLONE_VM_RELEASE, which lets the child release the 'user VM' at mm_release() time. --- arch/i386/kernel/process.c | 27 ++++++++++++++++++++------- include/linux/sched.h | 2 ++ kernel/fork.c | 6 ++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index fdcd260eba588..49cb229920396 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -566,6 +566,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, struct_cpy(childregs, regs); childregs->eax = 0; childregs->esp = esp; + p->user_vm_lock = NULL; p->thread.esp = (unsigned long) childregs; p->thread.esp0 = (unsigned long) (childregs+1); @@ -579,6 +580,19 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, unlazy_fpu(tsk); struct_cpy(&p->thread.i387, &tsk->thread.i387); + if (unlikely(NULL != tsk->thread.ts_io_bitmap)) { + p->thread.ts_io_bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); + if (!p->thread.ts_io_bitmap) + return -ENOMEM; + memcpy(p->thread.ts_io_bitmap, tsk->thread.ts_io_bitmap, + IO_BITMAP_BYTES); + } + + /* + * The common fastpath: + */ + if (!(clone_flags & (CLONE_SETTLS | CLONE_SETTID | CLONE_RELEASE_VM))) + return 0; /* * Set a new TLS for the child thread? */ @@ -608,14 +622,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, if (put_user(p->pid, (pid_t *)childregs->edx)) return -EFAULT; - if (unlikely(NULL != tsk->thread.ts_io_bitmap)) { - p->thread.ts_io_bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); - if (!p->thread.ts_io_bitmap) - return -ENOMEM; - memcpy(p->thread.ts_io_bitmap, tsk->thread.ts_io_bitmap, - IO_BITMAP_BYTES); + /* + * Does the userspace VM want any unlock on mm_release()? + */ + if (clone_flags & CLONE_RELEASE_VM) { + childregs->esp -= sizeof(0UL); + p->user_vm_lock = (long *) esp; } - return 0; } diff --git a/include/linux/sched.h b/include/linux/sched.h index 63a6b938b1457..fcd107c3d29cc 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -48,6 +48,7 @@ struct exec_domain; #define CLONE_SETTLS 0x00080000 /* create a new TLS for the child */ #define CLONE_SETTID 0x00100000 /* write the TID back to userspace */ #define CLONE_DETACHED 0x00200000 /* parent wants no child-exit signal */ +#define CLONE_RELEASE_VM 0x00400000 /* release the userspace VM */ #define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD) @@ -306,6 +307,7 @@ struct task_struct { wait_queue_head_t wait_chldexit; /* for wait4() */ struct completion *vfork_done; /* for vfork() */ + long *user_vm_lock; /* for CLONE_RELEASE_VM */ unsigned long rt_priority; unsigned long it_real_value, it_prof_value, it_virt_value; diff --git a/kernel/fork.c b/kernel/fork.c index 95baf72369106..3cb62cfcf4fd5 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -367,6 +367,12 @@ void mm_release(void) tsk->vfork_done = NULL; complete(vfork_done); } + if (tsk->user_vm_lock) + /* + * We dont check the error code - if userspace has + * not set up a proper pointer then tough luck. + */ + put_user(0UL, tsk->user_vm_lock); } static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) -- 2.53.0