[parisc-linux-cvs] Shared mmaps [Take 2]
Matthew Wilcox
willy@ldl.fc.hp.com
Sun, 04 Mar 2001 13:18:17 -0700
The patch I sent last night was flawed as it broke mremap. The flags
to mremap have different meanings than those to mmap. grr. So I invent
a new internal flag called _MAP_ALIGN to indicate we need better alignment
than PAGE_ALIGNMENT gives, et voila. A new patch.
Index: arch/ia64/kernel/sys_ia64.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/ia64/kernel/sys_ia64.c,v
retrieving revision 1.5
diff -u -p -r1.5 sys_ia64.c
--- sys_ia64.c 2001/01/24 23:58:50 1.5
+++ sys_ia64.c 2001/03/04 20:09:48
@@ -22,7 +22,7 @@
#define COLOR_ALIGN(addr) (((addr) + SHMLBA - 1) & ~(SHMLBA - 1))
unsigned long
-get_unmapped_area (unsigned long addr, unsigned long len)
+get_unmapped_area (unsigned long addr, unsigned long len, unsigned long flags)
{
struct vm_area_struct * vmm;
@@ -31,7 +31,7 @@ get_unmapped_area (unsigned long addr, u
if (!addr)
addr = TASK_UNMAPPED_BASE;
- if (current->thread.flags & IA64_THREAD_MAP_SHARED)
+ if (flags & _MAP_ALIGN)
addr = COLOR_ALIGN(addr);
else
addr = PAGE_ALIGN(addr);
@@ -45,6 +45,8 @@ get_unmapped_area (unsigned long addr, u
if (!vmm || addr + len <= vmm->vm_start)
return addr;
addr = vmm->vm_end;
+ if (flags & _MAP_ALIGN)
+ addr = COLOR_ALIGN(addr);
}
}
@@ -198,13 +200,11 @@ do_mmap2 (unsigned long addr, unsigned l
}
if (flags & MAP_SHARED)
- current->thread.flags |= IA64_THREAD_MAP_SHARED;
+ flags |= _MAP_ALIGN;
down(¤t->mm->mmap_sem);
addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up(¤t->mm->mmap_sem);
-
- current->thread.flags &= ~IA64_THREAD_MAP_SHARED;
if (file)
fput(file);
Index: arch/parisc/kernel/sys_parisc.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/sys_parisc.c,v
retrieving revision 1.8
diff -u -p -r1.8 sys_parisc.c
--- sys_parisc.c 2001/03/04 04:48:53 1.8
+++ sys_parisc.c 2001/03/04 20:09:48
@@ -1,7 +1,7 @@
/*
* linux/arch/parisc/kernel/sys_parisc.c
*
- * this implements the missing syscalls.
+ * this implements syscalls which are handled per-arch.
*/
#include <asm/uaccess.h>
@@ -10,8 +10,37 @@
#include <linux/linkage.h>
#include <linux/mm.h>
#include <linux/mman.h>
+#include <linux/shm.h>
#include <linux/smp_lock.h>
+#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
+
+unsigned long get_unmapped_area(unsigned long addr, unsigned long len, unsigned long flags)
+{
+ struct vm_area_struct * vmm;
+
+ if (len > TASK_SIZE)
+ return 0;
+ if (!addr)
+ addr = TASK_UNMAPPED_BASE;
+
+ if (flags & _MAP_ALIGN)
+ addr = COLOUR_ALIGN(addr);
+ else
+ addr = PAGE_ALIGN(addr);
+
+ for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
+ /* At this point: (!vmm || addr < vmm->vm_end). */
+ if (TASK_SIZE - len < addr)
+ return 0;
+ if (!vmm || addr + len <= vmm->vm_start)
+ return addr;
+ addr = vmm->vm_end;
+ if (flags & _MAP_ALIGN)
+ addr = COLOUR_ALIGN(addr);
+ }
+}
+
int sys_pipe(int *fildes)
{
int fd[2];
@@ -46,6 +75,9 @@ int sys_mmap(unsigned long addr, unsigne
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (flags & MAP_SHARED)
+ flags |= _MAP_ALIGN;
+
down(¤t->mm->mmap_sem);
error = do_mmap(file, addr, len, prot, flags, offset);
up(¤t->mm->mmap_sem);
@@ -56,10 +88,8 @@ out:
return error;
}
-long sys_shmat_wrapper(int shmid, void *shmaddr, int shmflag)
+long sys_shmat_wrapper(int shmid, char *shmaddr, int shmflag)
{
- extern int sys_shmat(int shmid, char *shmaddr, int shmflg,
- unsigned long * raddr);
unsigned long raddr;
int r;
Index: arch/sparc/kernel/sys_sparc.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/sparc/kernel/sys_sparc.c,v
retrieving revision 1.5
diff -u -p -r1.5 sys_sparc.c
--- sys_sparc.c 2001/01/25 00:00:10 1.5
+++ sys_sparc.c 2001/03/04 20:09:48
@@ -36,7 +36,7 @@ asmlinkage unsigned long sys_getpagesize
#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
-unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
+unsigned long get_unmapped_area(unsigned long addr, unsigned long len, unsigned long flags)
{
struct vm_area_struct * vmm;
@@ -48,7 +48,7 @@ unsigned long get_unmapped_area(unsigned
if (!addr)
addr = TASK_UNMAPPED_BASE;
- if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ if (flags & _MAP_ALIGN)
addr = COLOUR_ALIGN(addr);
else
addr = PAGE_ALIGN(addr);
@@ -64,7 +64,7 @@ unsigned long get_unmapped_area(unsigned
if (!vmm || addr + len <= vmm->vm_start)
return addr;
addr = vmm->vm_end;
- if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ if (flags & _MAP_ALIGN)
addr = COLOUR_ALIGN(addr);
}
}
@@ -234,14 +234,12 @@ static unsigned long do_mmap2(unsigned l
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
if (flags & MAP_SHARED)
- current->thread.flags |= SPARC_FLAG_MMAPSHARED;
+ flags |= _MAP_ALIGN;
down(¤t->mm->mmap_sem);
retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up(¤t->mm->mmap_sem);
- current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
-
out_putf:
if (file)
fput(file);
@@ -287,7 +285,7 @@ asmlinkage unsigned long sparc_mremap(un
down(¤t->mm->mmap_sem);
vma = find_vma(current->mm, addr);
if (vma && (vma->vm_flags & VM_SHARED))
- current->thread.flags |= SPARC_FLAG_MMAPSHARED;
+ flags |= _MAP_ALIGN;
if (flags & MREMAP_FIXED) {
if (ARCH_SUN4C_SUN4 &&
new_addr < 0xe0000000 &&
@@ -301,14 +299,13 @@ asmlinkage unsigned long sparc_mremap(un
ret = -ENOMEM;
if (!(flags & MREMAP_MAYMOVE))
goto out_sem;
- new_addr = get_unmapped_area (addr, new_len);
+ new_addr = get_unmapped_area (addr, new_len, flags);
if (!new_addr)
goto out_sem;
flags |= MREMAP_FIXED;
}
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
out_sem:
- current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
up(¤t->mm->mmap_sem);
out:
return ret;
Index: arch/sparc64/kernel/sys_sparc.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/sparc64/kernel/sys_sparc.c,v
retrieving revision 1.7
diff -u -p -r1.7 sys_sparc.c
--- sys_sparc.c 2001/01/25 00:00:16 1.7
+++ sys_sparc.c 2001/03/04 20:09:48
@@ -42,7 +42,7 @@ asmlinkage unsigned long sys_getpagesize
#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
-unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
+unsigned long get_unmapped_area(unsigned long addr, unsigned long len, unsigned long flags)
{
struct vm_area_struct * vmm;
unsigned long task_size = TASK_SIZE;
@@ -54,7 +54,7 @@ unsigned long get_unmapped_area(unsigned
if (!addr)
addr = TASK_UNMAPPED_BASE;
- if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ if (flags & _MAP_ALIGN)
addr = COLOUR_ALIGN(addr);
else
addr = PAGE_ALIGN(addr);
@@ -72,7 +72,7 @@ unsigned long get_unmapped_area(unsigned
if (!vmm || addr + len <= vmm->vm_start)
return addr;
addr = vmm->vm_end;
- if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ if (flags & _MAP_ALIGN)
addr = COLOUR_ALIGN(addr);
}
}
@@ -241,14 +241,12 @@ asmlinkage unsigned long sys_mmap(unsign
}
if (flags & MAP_SHARED)
- current->thread.flags |= SPARC_FLAG_MMAPSHARED;
+ flags |= _MAP_ALIGN;
down(¤t->mm->mmap_sem);
retval = do_mmap(file, addr, len, prot, flags, off);
up(¤t->mm->mmap_sem);
- current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
-
out_putf:
if (file)
fput(file);
@@ -288,7 +286,7 @@ asmlinkage unsigned long sys64_mremap(un
down(¤t->mm->mmap_sem);
vma = find_vma(current->mm, addr);
if (vma && (vma->vm_flags & VM_SHARED))
- current->thread.flags |= SPARC_FLAG_MMAPSHARED;
+ flags |= _MAP_ALIGN;
if (flags & MREMAP_FIXED) {
if (new_addr < PAGE_OFFSET &&
new_addr + new_len > -PAGE_OFFSET)
@@ -297,14 +295,13 @@ asmlinkage unsigned long sys64_mremap(un
ret = -ENOMEM;
if (!(flags & MREMAP_MAYMOVE))
goto out_sem;
- new_addr = get_unmapped_area(addr, new_len);
+ new_addr = get_unmapped_area(addr, new_len, flags);
if (!new_addr)
goto out_sem;
flags |= MREMAP_FIXED;
}
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
out_sem:
- current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
up(¤t->mm->mmap_sem);
out:
return ret;
Index: arch/sparc64/kernel/sys_sparc32.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/sparc64/kernel/sys_sparc32.c,v
retrieving revision 1.9
diff -u -p -r1.9 sys_sparc32.c
--- sys_sparc32.c 2001/02/02 03:35:43 1.9
+++ sys_sparc32.c 2001/03/04 20:09:48
@@ -4139,7 +4139,7 @@ asmlinkage unsigned long sys32_mremap(un
down(¤t->mm->mmap_sem);
vma = find_vma(current->mm, addr);
if (vma && (vma->vm_flags & VM_SHARED))
- current->thread.flags |= SPARC_FLAG_MMAPSHARED;
+ flags |= _MAP_ALIGN;
if (flags & MREMAP_FIXED) {
if (new_addr > 0xf0000000UL - new_len)
goto out_sem;
@@ -4147,14 +4147,13 @@ asmlinkage unsigned long sys32_mremap(un
ret = -ENOMEM;
if (!(flags & MREMAP_MAYMOVE))
goto out_sem;
- new_addr = get_unmapped_area(addr, new_len);
+ new_addr = get_unmapped_area(addr, new_len, flags);
if (!new_addr)
goto out_sem;
flags |= MREMAP_FIXED;
}
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
out_sem:
- current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
up(¤t->mm->mmap_sem);
out:
return ret;
Index: include/asm-parisc/processor.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/asm-parisc/processor.h,v
retrieving revision 1.41
diff -u -p -r1.41 processor.h
--- processor.h 2001/03/02 08:28:56 1.41
+++ processor.h 2001/03/04 20:09:48
@@ -324,4 +324,7 @@ extern inline unsigned long get_wchan(st
#define init_task (init_task_union.task)
#define init_stack (init_task_union.stack)
+/* We provide our own get_unmapped_area to cope with dcache aliasing */
+#define HAVE_ARCH_UNMAPPED_AREA
+
#endif /* __ASM_PARISC_PROCESSOR_H */
Index: include/asm-sparc/processor.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/asm-sparc/processor.h,v
retrieving revision 1.3
diff -u -p -r1.3 processor.h
--- processor.h 2001/01/25 00:03:14 1.3
+++ processor.h 2001/03/04 20:09:48
@@ -90,7 +90,6 @@ struct thread_struct {
#define SPARC_FLAG_KTHREAD 0x1 /* task is a kernel thread */
#define SPARC_FLAG_UNALIGNED 0x2 /* is allowed to do unaligned accesses */
-#define SPARC_FLAG_MMAPSHARED 0x4 /* task wants a shared mmap */
#define INIT_MMAP { &init_mm, (0), (0), \
NULL, __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
Index: include/asm-sparc64/processor.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/asm-sparc64/processor.h,v
retrieving revision 1.5
diff -u -p -r1.5 processor.h
--- processor.h 2001/01/25 00:03:15 1.5
+++ processor.h 2001/03/04 20:09:48
@@ -80,7 +80,6 @@ struct thread_struct {
#define SPARC_FLAG_32BIT 0x04 /* task is older 32-bit binary */
#define SPARC_FLAG_NEWCHILD 0x08 /* task is just-spawned child process */
#define SPARC_FLAG_PERFCTR 0x10 /* task has performance counters active */
-#define SPARC_FLAG_MMAPSHARED 0x20 /* task wants a shared mmap */
#define FAULT_CODE_WRITE 0x01 /* Write access, implies D-TLB */
#define FAULT_CODE_DTLB 0x02 /* Miss happened in D-TLB */
Index: include/linux/mm.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/linux/mm.h,v
retrieving revision 1.16
diff -u -p -r1.16 mm.h
--- mm.h 2001/02/08 22:39:19 1.16
+++ mm.h 2001/03/04 20:09:48
@@ -423,7 +423,7 @@ extern void insert_vm_struct(struct mm_s
extern void __insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
extern void build_mmap_avl(struct mm_struct *);
extern void exit_mmap(struct mm_struct *);
-extern unsigned long get_unmapped_area(unsigned long, unsigned long);
+extern unsigned long get_unmapped_area(unsigned long, unsigned long, unsigned long);
extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
Index: include/linux/mman.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/linux/mman.h,v
retrieving revision 1.2
diff -u -p -r1.2 mman.h
--- mman.h 2000/02/08 20:34:36 1.2
+++ mman.h 2001/03/04 20:09:48
@@ -5,5 +5,6 @@
#define MREMAP_MAYMOVE 1
#define MREMAP_FIXED 2
+#define _MAP_ALIGN 0x80000000 /* Align as required */
#endif /* _LINUX_MMAN_H */
Index: mm/mmap.c
===================================================================
RCS file: /home/cvs/parisc/linux/mm/mmap.c,v
retrieving revision 1.19
diff -u -p -r1.19 mmap.c
--- mmap.c 2001/02/02 03:37:18 1.19
+++ mmap.c 2001/03/04 20:09:48
@@ -254,7 +254,7 @@ unsigned long do_mmap_pgoff(struct file
if (addr & ~PAGE_MASK)
return -EINVAL;
} else {
- addr = get_unmapped_area(addr, len);
+ addr = get_unmapped_area(addr, len, flags);
if (!addr)
return -ENOMEM;
}
@@ -376,7 +376,7 @@ free_vma:
* Return value 0 means ENOMEM.
*/
#ifndef HAVE_ARCH_UNMAPPED_AREA
-unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
+unsigned long get_unmapped_area(unsigned long addr, unsigned long len, unsigned long flags)
{
struct vm_area_struct * vmm;
Index: mm/mremap.c
===================================================================
RCS file: /home/cvs/parisc/linux/mm/mremap.c,v
retrieving revision 1.7
diff -u -p -r1.7 mremap.c
--- mremap.c 2001/01/25 00:03:36 1.7
+++ mremap.c 2001/03/04 20:09:48
@@ -276,7 +276,7 @@ unsigned long do_mremap(unsigned long ad
ret = -ENOMEM;
if (flags & MREMAP_MAYMOVE) {
if (!(flags & MREMAP_FIXED)) {
- new_addr = get_unmapped_area(0, new_len);
+ new_addr = get_unmapped_area(0, new_len, flags);
if (!new_addr)
goto out;
}