optimize locking against vm changes for mmap/munmap
authorRich Felker <dalias@aerifal.cx>
Sat, 16 Aug 2014 06:41:45 +0000 (02:41 -0400)
committerRich Felker <dalias@aerifal.cx>
Sat, 16 Aug 2014 06:41:45 +0000 (02:41 -0400)
the whole point of this locking is to prevent munmap, or mmap with
MAP_FIXED, from deallocating virtual addresses, or changing the
backing a given virtual address refers to, during certain race windows
involving self-synchronized unmapping or destruction of pthread
synchronization objects. there is no need for exclusion in the other
direction, so it suffices to take the lock momentarily and release it
before making the syscall, rather than holding it across the syscall.

src/mman/mmap.c
src/mman/munmap.c

index 1917a540322e080a798524ea039e5a1a86359fec..56e39a7a1151e085306316e09ba8f41e9f3a065f 100644 (file)
@@ -16,8 +16,6 @@ weak_alias(dummy0, __vm_unlock);
 
 void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off)
 {
-       void *ret;
-
        if (off & OFF_MASK) {
                errno = EINVAL;
                return MAP_FAILED;
@@ -26,14 +24,15 @@ void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off)
                errno = ENOMEM;
                return MAP_FAILED;
        }
-       if (flags & MAP_FIXED) __vm_lock(-1);
+       if (flags & MAP_FIXED) {
+               __vm_lock(-1);
+               __vm_unlock();
+       }
 #ifdef SYS_mmap2
-       ret = (void *)syscall(SYS_mmap2, start, len, prot, flags, fd, off/UNIT);
+       return (void *)syscall(SYS_mmap2, start, len, prot, flags, fd, off/UNIT);
 #else
-       ret = (void *)syscall(SYS_mmap, start, len, prot, flags, fd, off);
+       return (void *)syscall(SYS_mmap, start, len, prot, flags, fd, off);
 #endif
-       if (flags & MAP_FIXED) __vm_unlock();
-       return ret;
 }
 
 weak_alias(__mmap, mmap);
index 8488d75ce5294af1f60ffc2bb9dd81d18e991a2b..359c691fc970ec4063b15ca9b23a3f63a35636d6 100644 (file)
@@ -11,8 +11,8 @@ int __munmap(void *start, size_t len)
 {
        int ret;
        __vm_lock(-1);
-       ret = syscall(SYS_munmap, start, len);
        __vm_unlock();
+       ret = syscall(SYS_munmap, start, len);
        return ret;
 }