aboutsummaryrefslogtreecommitdiffstats
path: root/arena.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2001-10-18 00:23:31 +0000
committerH. Peter Anvin <hpa@zytor.com>2001-10-18 00:23:31 +0000
commit26f21f20a407f7982a9710e95bdc7496a2609edd (patch)
tree3b1c429687b0cbd2004f564212a38f5c71a88bfb /arena.c
parentda53395ccdb14220321de6813f2b92bc6764af35 (diff)
downloadlpsm-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.
Diffstat (limited to 'arena.c')
-rw-r--r--arena.c90
1 files changed, 16 insertions, 74 deletions
diff --git a/arena.c b/arena.c
index c95c1ce..7ab018e 100644
--- a/arena.c
+++ b/arena.c
@@ -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;