[parisc-linux-cvs] Shared mmaps
Matthew Wilcox
willy@ldl.fc.hp.com
Sat, 03 Mar 2001 23:19:32 -0700
Here's how i'm thinking about solving the shared mmap problem on PA-RISC.
It compiles, i haven't booted it; I'm going to bed. Comments welcome,
as always.
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 06:11:02
@@ -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_SHARED)
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_SHARED)
+ addr = COLOR_ALIGN(addr);
}
}
@@ -197,14 +199,9 @@ do_mmap2 (unsigned long addr, unsigned l
return -EBADF;
}
- if (flags & MAP_SHARED)
- current->thread.flags |= IA64_THREAD_MAP_SHARED;
-
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 06:11:02
@@ -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_SHARED)
+ 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_SHARED)
+ addr = COLOUR_ALIGN(addr);
+ }
+}
+
int sys_pipe(int *fildes)
{
int fd[2];
@@ -56,10 +85,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 06:11:02
@@ -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;
@@ -301,7 +301,7 @@ 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, 0);
if (!new_addr)
goto out_sem;
flags |= MREMAP_FIXED;
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 06:11:02
@@ -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;
@@ -297,7 +297,7 @@ 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, 0);
if (!new_addr)
goto out_sem;
flags |= MREMAP_FIXED;
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 06:11:02
@@ -4147,7 +4147,7 @@ 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, 0);
if (!new_addr)
goto out_sem;
flags |= MREMAP_FIXED;
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 06:11:02
@@ -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/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 06:11:02
@@ -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: 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 06:11:02
@@ -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 06:11:02
@@ -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;
}