[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(&current->mm->mmap_sem);
 	addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up(&current->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;
 		}