linux-mips
[Top] [All Lists]

Re: Linux Shared Memory Issue

To: turcotte@broadcom.com
Subject: Re: Linux Shared Memory Issue
From: Jun Sun <jsun@mvista.com>
Date: Wed, 24 Apr 2002 15:03:15 -0700
Cc: linux-mips@oss.sgi.com, Maurice Turcotte <mturc@broadcom.com>
References: <NDBBKEAAOJECIDBJKLIHOEDDCDAA.turcotte@broadcom.com>
Sender: owner-linux-mips@oss.sgi.com
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.2.1) Gecko/20010901

Looks like the infamous cache aliasing problem. Steve Longerbeam had a patch which may help. Please try it and let me know the results.

Thanks.

Jun


Maurice Turcotte wrote:

Greetings:

I am having a problem with Linux Kernel 2.4.5 on a mips.

I have two processes using share memory for IPC. This same
code works fine with Kernel 2.4.7 on a x86. The problem is that the second process reads old data out of the shared
memory.

The executive summary->

Process #1 writes "A" to shared memory at 0x2aac7210
Process #2 reads 0 from shared memory at address 0x2aaca210
Process #1 writes "B" to shared memory at 0x2aac7210
Process #2 read "A" from shared memory at address 0x2aaca210
Process #1 writes "C" to shared memory at 0x2aac7210
Process #2 read "B" from shared memory at address 0x2aaca210

It is interesting that the processes get different addresses
associated with the same shmId. I assume this is because of some user-space mapping that is going on.

I left out the semaphore diddling, but I believe that part of
the code is correct because it works flawlessly on the 2.4.7 x86.

Any tips on debugging this would be greatly appreciated. If this
is not the proper forum for questions like this, please point me
in the right direction.

Thanks,

mturc



diff -Nuar -X /home/stevel/dontdiff 
linux-2.4.17.orig/arch/mips/kernel/syscall.c 
linux-2.4.17/arch/mips/kernel/syscall.c
--- linux-2.4.17.orig/arch/mips/kernel/syscall.c        Sun Sep 16 16:29:10 2001
+++ linux-2.4.17/arch/mips/kernel/syscall.c     Thu Jan 24 15:02:18 2002
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/utsname.h>
 #include <linux/unistd.h>
+#include <linux/shm.h>
 #include <asm/branch.h>
 #include <asm/offset.h>
 #include <asm/ptrace.h>
@@ -53,6 +54,50 @@
 out:
        return res;
 }
+
+/*
+ * To avoid cache aliases, we map the shard page with same color.
+ */
+#define COLOUR_ALIGN(addr)    (((addr)+SHMLBA-1)&~(SHMLBA-1))
+
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
+                                    unsigned long len, unsigned long pgoff,
+                                    unsigned long flags)
+{
+       struct vm_area_struct *vma;
+
+       if (flags & MAP_FIXED) {
+               /*
+                * We do not accept a shared mapping if it would violate
+                * cache aliasing constraints.
+                */
+               if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
+                       return -EINVAL;
+               return addr;
+       }
+
+       if (len > TASK_SIZE)
+               return -ENOMEM;
+       if (!addr)
+               addr = TASK_UNMAPPED_BASE;
+
+       if (flags & MAP_SHARED)
+               addr = COLOUR_ALIGN(addr);
+       else
+               addr = PAGE_ALIGN(addr);
+
+       for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
+               /* At this point:  (!vma || addr < vma->vm_end). */
+               if (TASK_SIZE - len < addr)
+                       return -ENOMEM;
+               if (!vma || addr + len <= vma->vm_start)
+                       return addr;
+               addr = vma->vm_end;
+               if (flags & MAP_SHARED)
+                       addr = COLOUR_ALIGN(addr);
+       }
+}
+
 
 /* common code for old and new mmaps */
 static inline long
diff -Nuar -X /home/stevel/dontdiff 
linux-2.4.17.orig/include/asm-mips/pgtable.h 
linux-2.4.17/include/asm-mips/pgtable.h
--- linux-2.4.17.orig/include/asm-mips/pgtable.h        Thu Jan 24 14:35:06 2002
+++ linux-2.4.17/include/asm-mips/pgtable.h     Thu Jan 24 14:56:52 2002
@@ -64,6 +64,9 @@
 #define flush_icache_all()             do { } while(0)
 #endif
 
+/* We provide our own get_unmapped_area to avoid cache aliasing */
+#define HAVE_ARCH_UNMAPPED_AREA
+
 /*
  * - add_wired_entry() add a fixed TLB entry, and move wired register
  */
<Prev in Thread] Current Thread [Next in Thread>