]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Attempt to emulate mremap() on non-Linux systems by allocating a second mapping immed...
authordan <dan@noemail.net>
Mon, 1 Apr 2013 17:56:59 +0000 (17:56 +0000)
committerdan <dan@noemail.net>
Mon, 1 Apr 2013 17:56:59 +0000 (17:56 +0000)
FossilOrigin-Name: 4d67433db8fb4754ae6b192945e479f3d7bad579

manifest
manifest.uuid
src/os_unix.c

index e6eca96ae65529e6a45123388305253aed711d8d..52c1269c2e071ecc0b0adde237a36638b1068b28 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sxFetch\sand\sxUnfetch\smethods\sto\sthe\sos_win.c\sVFS.
-D 2013-04-01T17:22:51.830
+C Attempt\sto\semulate\smremap()\son\snon-Linux\ssystems\sby\sallocating\sa\ssecond\smapping\simmediately\sfollowing\sthe\sfirst\sin\svirtual\smemory.
+D 2013-04-01T17:56:59.408
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in df3e48659d80e1b7765785d8d66c86b320f72cc7
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -160,7 +160,7 @@ F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
 F src/os.c 809d0707cec693e1b9b376ab229271ad74c3d35d
 F src/os.h ae08bcc5f6ec6b339f4a2adf3931bb88cc14c3e4
 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
-F src/os_unix.c d6981218583748080374ed98a03f6a87e2bdc9e0
+F src/os_unix.c d136eca0cff2f8a5ac2f45867d5e5153d60e377c
 F src/os_win.c f705e7ce230f86104dedcc2987a21d564b236659
 F src/pager.c 2b9980e87296812a6ce51121a3335550ae25e3ec
 F src/pager.h 5cb78b8e1adfd5451e600be7719f5a99d87ac3b1
@@ -1040,7 +1040,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P a1040f0397d57855500926494c978623286ddc77
-R 52b13f77704d4760e77e0cfd9ab57bff
-U drh
-Z 878a27609130450cef13cc90a8feab48
+P a1653a257d6af6e8b10c819e68b12f6c2f485811
+R 144bfd1ec5d6fde06365c0d3ea4b879a
+U dan
+Z 4e8a79b712821b5d3d9730a626894d79
index c685b6feac45cfdacdb4a1642a3796a75ce456f5..694ae46ba87bb5799e03589cef84e38738570419 100644 (file)
@@ -1 +1 @@
-a1653a257d6af6e8b10c819e68b12f6c2f485811
\ No newline at end of file
+4d67433db8fb4754ae6b192945e479f3d7bad579
\ No newline at end of file
index f91f4c4e7a8f287b9050955fc9dc953da59e2b4a..e92c7cc4a47658e8f59e517f766820b07b2cfd30 100644 (file)
@@ -313,6 +313,17 @@ struct unixFile {
 #define threadid 0
 #endif
 
+/*
+** HAVE_MREMAP defaults to true on Linux and false everywhere else.
+*/
+#if !defined(HAVE_MREMAP)
+# if defined(__linux__) && defined(_GNU_SOURCE)
+#  define HAVE_MREMAP 1
+# else
+#  define HAVE_MREMAP 0
+# endif
+#endif
+
 /*
 ** Different Unix systems declare open() in different ways.  Same use
 ** open(const char*,int,mode_t).  Others use open(const char*,int,...).
@@ -450,7 +461,7 @@ static struct unix_syscall {
   { "munmap",       (sqlite3_syscall_ptr)munmap,          0 },
 #define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent)
 
-#if defined(__linux__) && defined(_GNU_SOURCE)
+#if HAVE_MREMAP
   { "mremap",       (sqlite3_syscall_ptr)mremap,          0 },
 #else
   { "mremap",       (sqlite3_syscall_ptr)0,               0 },
@@ -1124,7 +1135,6 @@ static int unixLogErrorAtLine(
   zErr = strerror(iErrno);
 #endif
 
-  assert( errcode!=SQLITE_OK );
   if( zPath==0 ) zPath = "";
   sqlite3_log(errcode,
       "os_unix.c:%d: (%d) %s(%s) - %s",
@@ -3619,7 +3629,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
     }
   }
 
-  if( pFile->mmapLimit>0 ){
+  if( pFile->mmapLimit>0 && nByte>pFile->mmapSize ){
     int rc;
     if( pFile->szChunk<=0 ){
       if( robust_ftruncate(pFile->h, nByte) ){
@@ -4518,6 +4528,104 @@ static void unixUnmapfile(unixFile *pFd){
   }
 }
 
+/*
+** Return the system page size.
+*/
+static int unixGetPagesize(void){
+#if HAVE_MREMAP
+  return 512;
+#elif _BSD_SOURCE
+  return getpagesize();
+#else
+  return (int)sysconf(_SC_PAGESIZE);
+#endif
+}
+
+/*
+** Attempt to set the size of the memory mapping maintained by file 
+** descriptor pFd to nNew bytes. Any existing mapping is discarded.
+**
+** If successful, this function sets the following variables:
+**
+**       unixFile.pMapRegion
+**       unixFile.mmapSize
+**       unixFile.mmapOrigsize
+**
+** If unsuccessful, an error message is logged via sqlite3_log() and
+** the three variables above are zeroed. In this case SQLite should
+** continue accessing the database using the xRead() and xWrite()
+** methods.
+*/
+static void unixRemapfile(
+  unixFile *pFd,                  /* File descriptor object */
+  i64 nNew                        /* Required mapping size */
+){
+  int h = pFd->h;                      /* File descriptor open on db file */
+  u8 *pOrig = (u8 *)pFd->pMapRegion;   /* Pointer to current file mapping */
+  i64 nOrig = pFd->mmapOrigsize;       /* Size of pOrig region in bytes */
+  u8 *pNew = 0;                        /* Location of new mapping */
+  int flags = PROT_READ;               /* Flags to pass to mmap() */
+
+  assert( pFd->nFetchOut==0 );
+  assert( nNew>pFd->mmapSize );
+  assert( nNew<=pFd->mmapLimit );
+  assert( nNew>0 );
+  assert( pFd->mmapOrigsize>=pFd->mmapSize );
+
+  if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
+
+  if( pOrig ){
+    const int szSyspage = unixGetPagesize();
+    i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
+    u8 *pReq = &pOrig[nReuse];
+
+    /* Unmap any pages of the existing mapping that cannot be reused. */
+    if( nReuse!=nOrig ){
+      osMunmap(pReq, nOrig-nReuse);
+    }
+
+#if HAVE_MREMAP
+    pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
+#else
+    pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
+    if( pNew!=MAP_FAILED ){
+      if( pNew!=pReq ){
+        osMunmap(pNew, nNew - nReuse);
+        pNew = MAP_FAILED;
+      }else{
+        pNew = pOrig;
+      }
+    }
+#endif
+
+    /* The attempt to extend the existing mapping failed. Free the existing
+    ** mapping and set pNew to NULL so that the code below will create a
+    ** new mapping from scratch.  */
+    if( pNew==MAP_FAILED ){
+      pNew = 0;
+      osMunmap(pOrig, nReuse);
+    }
+  }
+
+  /* If pNew is still NULL, try to create an entirely new mapping. */
+  if( pNew==0 ){
+    pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
+    if( pNew==MAP_FAILED ){
+      pNew = 0;
+      nNew = 0;
+      unixLogError(SQLITE_OK, "mmap", pFd->zPath);
+
+      /* If the mmap() above failed, assume that all subsequent mmap() calls
+      ** will probably fail too. Fall back to using xRead/xWrite exclusively
+      ** in this case.  */
+      pFd->mmapLimit = 0;
+    }
+  }
+
+  pFd->pMapRegion = (void *)pNew;
+  pFd->mmapSize = pFd->mmapOrigsize = nNew;
+}
+
 /*
 ** Memory map or remap the file opened by file-descriptor pFd (if the file
 ** is already mapped, the existing mapping is replaced by the new). Or, if 
@@ -4554,28 +4662,11 @@ static int unixMapfile(unixFile *pFd, i64 nByte){
   }
 
   if( nMap!=pFd->mmapSize ){
-    void *pNew = 0;
-
-#if defined(__linux__) && defined(_GNU_SOURCE)
-    if( pFd->pMapRegion && nMap>0 ){
-      pNew = osMremap(pFd->pMapRegion, pFd->mmapOrigsize, nMap, MREMAP_MAYMOVE);
-    }else
-#endif
-    {
+    if( nMap>0 ){
+      unixRemapfile(pFd, nMap);
+    }else{
       unixUnmapfile(pFd);
-      if( nMap>0 ){
-        int flags = PROT_READ;
-        if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
-        pNew = osMmap(0, nMap, flags, MAP_SHARED, pFd->h, 0);
-      }
-    }
-
-    if( pNew==MAP_FAILED ){
-      return SQLITE_IOERR_MMAP;
     }
-    pFd->pMapRegion = pNew;
-    pFd->mmapSize = nMap;
-    pFd->mmapOrigsize = nMap;
   }
 
   return SQLITE_OK;