diff options
author | H. Peter Anvin <hpa@zytor.com> | 2001-10-18 00:23:31 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2001-10-18 00:23:31 +0000 |
commit | 26f21f20a407f7982a9710e95bdc7496a2609edd (patch) | |
tree | 3b1c429687b0cbd2004f564212a38f5c71a88bfb | |
parent | da53395ccdb14220321de6813f2b92bc6764af35 (diff) | |
download | lpsm-26f21f20a407f7982a9710e95bdc7496a2609edd.tar.gz lpsm-26f21f20a407f7982a9710e95bdc7496a2609edd.tar.xz lpsm-26f21f20a407f7982a9710e95bdc7496a2609edd.zip |
Skip the unread -> clean transition by using a private *non*-anonymousbefore-file-backed-change
mapping.
-rw-r--r-- | arena.c | 90 | ||||
-rw-r--r-- | test_mmap.c | 29 |
2 files changed, 40 insertions, 79 deletions
@@ -39,10 +39,10 @@ #include "objstore.h" #include "internals.h" +/* This might end up being a bitmask eventually */ enum page_status { - page_unread = 0, - page_clean = 1, - page_dirty = 2, + page_clean = 0, + page_dirty = 1, }; /* @@ -110,7 +110,6 @@ static void objstore_sigsegv(int signal, siginfo_t *siginfo, void *ptr) void *page; uintptr_t npage, offset; char *pageinfo; - struct flock lock; int old_errno = errno; #ifdef __linux__ struct sigcontext *ctxt; @@ -151,25 +150,6 @@ static void objstore_sigsegv(int signal, siginfo_t *siginfo, void *ptr) mprotect(page, os->pagesize, PROT_READ|PROT_WRITE); switch ( (enum page_status) *pageinfo ) { - case page_unread: - lseek(os->main_fd, offset, SEEK_SET); - - lock.l_type = F_RDLCK; - lock.l_whence = SEEK_SET; - lock.l_start = offset; - lock.l_len = os->pagesize; - while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR ); - if ( objstore_read(os->main_fd, page, os->pagesize) < os->pagesize ) - abort(); /* Uh-oh... */ - - lock.l_type = F_UNLCK; - while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR ); - - mprotect(page, os->pagesize, PROT_READ); /* Make page readonly */ - *pageinfo = page_clean; /* Page read and clean */ - os->loaded_count++; /* For accounting purposes */ - break; - case page_clean: *pageinfo = page_dirty; /* Page now dirty */ os->dirty_count++; /* For accounting purposes */ @@ -362,8 +342,7 @@ void *objstore_init(const char *main_file, const char *log_file, size_t *arena_l lock.l_type = F_UNLCK; while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR ); - os->arena = mmap(arena_ptr, len, PROT_NONE, - MAP_ANON|MAP_PRIVATE|MAP_FIXED, 0, 0); + os->arena = mmap(arena_ptr, len, PROT_READ, MAP_PRIVATE|MAP_FIXED, os->main_fd, 0); if ( os->arena == MAP_FAILED ) goto errx3; @@ -375,18 +354,12 @@ void *objstore_init(const char *main_file, const char *log_file, size_t *arena_l if ( !os->pageinfo ) goto errx4; - /* The pageinfo up to and including file_len is "unread"; beyond - file_len we know it must be zero and thus it can be marked "clean" */ file_len = (file_len + os->pagesize - 1) & ~(os->pagesize-1); file_pages = file_len >> os->pageshift; len_pages = len >> os->pageshift; - memset(os->pageinfo, page_unread, file_pages); - - if ( len_pages > file_pages ) { - mprotect((char *)os->arena + file_len, len - file_len, PROT_READ); - memset(os->pageinfo + file_pages, page_clean, len_pages-file_pages); - } + /* All pages clean at this time */ + memset(os->pageinfo, page_clean, len_pages); sigact.sa_sigaction = objstore_sigsegv; sigemptyset(&sigact.sa_mask); @@ -475,35 +448,12 @@ pid_t objstore_checkpoint(double gc_factor, enum objsync_enum wait) return (pid_t)-1; /* Checkpoint failed! */ else if ( f > 0 ) { /* Parent process -- just mark all dirty pages clean */ + /* FIX: We probably want to do something more clever + than memset() here, and perhaps keep around the old dirty + array for a while. */ + mprotect(os->arena, os->arena_len, PROT_READ); + memset(os->pageinfo, page_clean, os->arena_len >> os->pageshift); - size_t size, count; - char *opi; - int found_dirty; - - /* Aggregate both clean and dirty pages; this should allow the OS - to avoid keeping track of quite as many memory protect regions */ - for ( pi = os->pageinfo ; pi < epi ; pi++ ) { - if ( *pi == page_dirty || *pi == page_clean ) { - found_dirty = (*pi == page_dirty); - page = (char *)os->arena + - ((uintptr_t)(pi - os->pageinfo) << os->pageshift); - - opi = pi; - size = os->pagesize; - count = 1; - while ( pi+1 < epi && - (pi[1] == page_dirty || pi[1] == page_clean) ) { - pi++; - found_dirty = found_dirty || (*pi == page_dirty); - count++; - size += os->pagesize; - } - if ( found_dirty ) { - mprotect(page, size, PROT_READ); - memset(opi, page_clean, count); - } - } - } os->dirty_count = 0; /* No pages dirty */ os->fork_seq++; /* Increase next sequence number */ @@ -662,9 +612,8 @@ int objstore_extend(size_t new_size) goto reset_size; /* Failure */ newp = mmap((char*)os->arena + old_size, - add_size, - PROT_NONE, - MAP_PRIVATE|MAP_ANON|MAP_FIXED, 0, 0); + add_size, PROT_READ, + MAP_PRIVATE|MAP_FIXED, os->main_fd, old_size); if ( newp == MAP_FAILED ) goto reset_size; /* Failure */ @@ -691,16 +640,9 @@ int objstore_extend(size_t new_size) /* No more failure bailouts, unlock */ while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR ); - /* If we extended the file, the new area is known to contain - zero, and can thus be considered "clean"; otherwise we have - to consider it "unread". */ - if ( file_pages > old_pages ) { - memset(os->pageinfo + old_pages, page_unread, file_pages-old_pages); - } - if ( file_pages < new_pages ) { - memset(os->pageinfo + file_pages, page_clean, new_pages-file_pages); - mprotect((char *)os->arena + file_size, new_size-file_size, PROT_READ); - } + /* Mark new pages clean */ + assert(new_pages >= file_pages); + memset(os->pageinfo + file_pages, page_clean, new_pages-file_pages); return 0; diff --git a/test_mmap.c b/test_mmap.c index 445870f..15c962d 100644 --- a/test_mmap.c +++ b/test_mmap.c @@ -7,15 +7,34 @@ int main(int argc, char *argv[]) { + char buffer[16384]; char *mapping; + int fd; - mapping = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0); - mmap(mapping+8192, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON|MAP_FIXED, 0, 0); + /* Test of anonymous mappings */ + + mapping = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + mmap(mapping+8192, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); strcpy(mapping+0, "Foo mani padme hum"); strcpy(mapping+4096, "Foo mani padme hum"); errno = 0; - mmap(mapping+4096, 4096, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANON, 0, 0); + mmap(mapping+4096, 4096, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); munmap(mapping, 16384); -} - + /* Test of non-anonymous private mappings */ + fd = open("mmaptest.dat", O_RDWR|O_TRUNC|O_CREAT, 0600); + memset(buffer, '#', 16384); + write(fd, buffer, 16384); + + mapping = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + strcpy(mapping+4096, "Foo mani padme hum"); + + mmap(mapping+8192, 8192, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE, fd, 8192); + + mmap(mapping+4096, 4096, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE, fd, 4096); + + munmap(mapping, 16384); + close(fd); + + return 0; +} |