Subject: mmap
To: None <current-users@netbsd.org>
From: Andreas Wrede <andreas@planix.com>
List: current-users
Date: 11/09/1998 16:52:13
The configure script for the Cyrus imapd server ver 1.5.14 runs a test program 
to "Verify the OS supports the memory mapping semantics needed by 
map_private".

The program fails in different ways on both 1.3.2 and -current. On 1.3.2 it 
results in "private map does not show change", while on -current it prints 
"shared map does not match within page" (see code below).

I don't understand the intricacies of mmap well enough to see what is going 
on,  but the fact that there is a difference appears to indicate that we 
have a problem here.

Both 1.3.2 and -current are i386, -current is 1.3H from Nov 4, using gcc 
2.7.2.2, UVM and PMAP_NEW.

---[snip]---
    
/* Verify the OS supports the memory mapping semantics needed by map_private
 * from John Myers <jgmyers@netscape.com>
 */ 
    
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
    
#ifndef MAP_NORESERVE
#define MAP_NORESERVE 0
#endif
    
/* not on Linux */ 
#ifndef MAP_VARIABLE
#define MAP_VARIABLE 0
#endif 

#ifndef MAP_FAILED
#define MAP_FAILED ((void *) -1)
#endif 

fatal(char *s)
{   
    write(2, s, strlen(s));
    write(2, "\n", 1);
    unlink("conftestmmap");
    exit(1);
}   
    
main() {
    int fd = open("conftestmmap", O_RDWR|O_CREAT|O_TRUNC, 0666);
    int fd2;
    char *base_shared, *base_private, *base_private2;
    
    if (fd == -1) fatal("cannot create test file");
    if (write(fd, "test", 4) != 4) fatal("cannot write test file");
    base_shared = mmap((caddr_t)0, 10000, PROT_READ,
             MAP_SHARED | MAP_FILE| MAP_VARIABLE,
             fd, 0L);
    if (base_shared == MAP_FAILED) fatal("cannot create shared map"); 

    base_private = mmap((caddr_t)0, 4, PROT_READ,
             MAP_PRIVATE | MAP_NORESERVE | MAP_FILE| MAP_VARIABLE,
             fd, 0L);
    if (base_private == MAP_FAILED) fatal("cannot create private map");
    
    base_private2 = mmap((caddr_t)0, 4, PROT_READ,
             MAP_PRIVATE | MAP_NORESERVE | MAP_FILE| MAP_VARIABLE,
             fd, 0L);
    if (base_private == MAP_FAILED) fatal("cannot create private2 map");
    

    if (strncmp(base_shared, "test", 4) != 0) fatal("shared map does not match");   
    if (strncmp(base_private, "test", 4) != 0) fatal("private map does not match");

    if (write(fd, "test", 4) != 4) fatal("cannot extend test file within page");
    fsync(fd);
    msync((caddr_t)base_shared, 10000, MS_INVALIDATE);


    if (munmap(base_private, 4)) fatal("cannot unmap private map");
    base_private = mmap((caddr_t)0, 8, PROT_READ,
             MAP_PRIVATE | MAP_NORESERVE | MAP_FILE| MAP_VARIABLE,
             fd, 0L); 
    if (base_private == MAP_FAILED) fatal("cannot create private map second time");

    if (strncmp(base_shared+4, "test", 4) != 0) fatal("shared map does not match within page"); 
    if (strncmp(base_private+4, "test", 4) != 0) fatal("private map does not match within page");
    
    fd2 = open("conftestmmap", O_RDWR, 0666);
    if (lseek(fd2, 0, 0) == -1) fatal("cannot seek second fd");
    if (write(fd2, "xyzy", 4) != 4) fatal("cannot write second fd");
    fsync(fd2);
    
    
    if (munmap(base_private, 8)) fatal("cannot unmap private map");
    base_private = mmap((caddr_t)0, 8, PROT_READ,  
             MAP_PRIVATE | MAP_NORESERVE | MAP_FILE| MAP_VARIABLE, 
             fd, 0L);
    if (base_private == MAP_FAILED) fatal("cannot create private map third time");
    if (strncmp(base_private, "xyzy", 4) != 0) fatal("private map does not show change");
    
        
    {
        int i;
        for (i = 0; i < 9000; i++) {
            if (write(fd, "test", 4) != 4) fatal("cannot extend test file outside page");    
        }    
    }
   msync((caddr_t)base_shared, 10000, MS_INVALIDATE);
    msync((caddr_t)base_private, 10000, MS_INVALIDATE);
    
    if (strncmp(base_shared+9000, "test", 4) != 0) fatal("shared map does not match beyond page");
#if 0
    if (strncmp(base_private+9000, "test", 4) != 0) fatal("private map does notmatch beyond page");
#endif
    
    unlink("conftestmmap");
    exit(0);
}   
 
---[SNIP]---  

-- 
Andreas Wrede              Planix, Inc.
andreas@planix.com         Networking, System Administration, Consulting
http://www.planix.com      Toronto, Ontario, Canada