Implement support for the async I/O system calls in 2.6 kernels. This
requires padding of the address space around calls to io_setup in order
to constrain the kernel's choice of address for the I/O context.

Based on patch from Scott Smith <scott-kde@gelatinous.com> with various
enhancements, this fixes bug #83060.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2485 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_memory.c b/coregrind/vg_memory.c
index 4a476f7..06586e4 100644
--- a/coregrind/vg_memory.c
+++ b/coregrind/vg_memory.c
@@ -545,6 +545,62 @@
    return ret;
 }
 
+void VG_(pad_address_space)(void)
+{
+   Addr addr = VG_(client_base);
+   Segment *s = VG_(SkipNode_First)(&sk_segments);
+   UInt args[6];
+   Addr ret;
+   
+   args[2] = 0;
+   args[3] = VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS;
+   args[4] = -1;
+   args[5] = 0;
+   
+   while (s && addr < VG_(valgrind_end)) {
+      if (addr < s->addr) {
+         args[0] = (UInt)addr;
+         args[1] = s->addr - addr;
+         
+         ret = VG_(do_syscall)(__NR_mmap, (UInt)args);
+      }
+        
+      addr = s->addr + s->len;
+      s = VG_(SkipNode_Next)(&sk_segments, s);
+   }
+
+   if (addr < VG_(valgrind_end)) {
+      args[0] = (UInt)addr;
+      args[1] = VG_(valgrind_end) - addr;
+
+      ret = VG_(do_syscall)(__NR_mmap, (UInt)args);
+   }
+
+   return;
+}
+
+void VG_(unpad_address_space)(void)
+{
+   Addr addr = VG_(client_base);
+   Segment *s = VG_(SkipNode_First)(&sk_segments);
+   Int ret;
+
+   while (s && addr < VG_(valgrind_end)) {
+      if (addr < s->addr) {
+         ret = VG_(do_syscall)(__NR_munmap, (UInt)addr, s->addr - addr);
+      }
+         
+      addr = s->addr + s->len;
+      s = VG_(SkipNode_Next)(&sk_segments, s);
+   }
+
+   if (addr < VG_(valgrind_end)) {
+      ret = VG_(do_syscall)(__NR_munmap, (UInt)addr, VG_(valgrind_end) - addr);
+   }
+
+   return;
+}
+
 Segment *VG_(find_segment)(Addr a)
 {
    return VG_(SkipList_Find)(&sk_segments, &a);