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
*/
|