/ Check-in [bf3d0ab5]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Experimental work to allow SQLite to use the native Win32 heap API.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | winNativeHeap
Files: files | file ages | folders
SHA1: bf3d0ab53829350637283442f75071fe6d925245
User & Date: mistachkin 2011-08-24 16:13:57
Context
2011-08-24
17:42
Add error logging to native Win32 heap support. check-in: 7fca5a28 user: mistachkin tags: winNativeHeap
16:13
Experimental work to allow SQLite to use the native Win32 heap API. check-in: bf3d0ab5 user: mistachkin tags: winNativeHeap
15:18
Updates to the sqlite3_mem_methods documentation. check-in: 988998fe user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.msc.

    44     44   TCC = $(TCC) -DNDEBUG
    45     45   
    46     46   #
    47     47   # Prevent warnings about "insecure" runtime library functions being used.
    48     48   #
    49     49   TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
    50     50   
           51  +#
           52  +# Use native Win32 heap.
           53  +#
           54  +TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
           55  +
    51     56   # The locations of the Tcl header and library files.  Also, the library that
    52     57   # non-stubs enabled programs using Tcl must link against.  These variables
    53     58   # (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
    54     59   # prior to running nmake in order to match the actual installed location and
    55     60   # version on this machine.
    56     61   #
    57     62   !if "$(TCLINCDIR)" == ""

Changes to src/os_win.c.

   115    115     HANDLE hMutex;          /* Mutex used to control access to shared lock */  
   116    116     HANDLE hShared;         /* Shared memory segment used for locking */
   117    117     winceLock local;        /* Locks obtained by this instance of winFile */
   118    118     winceLock *shared;      /* Global shared lock memory for the file  */
   119    119   #endif
   120    120   };
   121    121   
          122  +/*
          123  + * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
          124  + * various Win32 API heap functions instead of our own.
          125  + */
          126  +#ifdef SQLITE_WIN32_MALLOC
          127  +/*
          128  + * The initial size of the Win32-specific heap.  This value may be zero.
          129  + */
          130  +#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
          131  +#  define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
          132  +                                       (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
          133  +#endif
          134  +
          135  +/*
          136  + * The maximum size of the Win32-specific heap.  This value may be zero.
          137  + */
          138  +#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
          139  +#  define SQLITE_WIN32_HEAP_MAX_SIZE  (0)
          140  +#endif
          141  +
          142  +/*
          143  +** The winMemData structure stores information required by the Win32-specific
          144  +** sqlite3_mem_methods implementation.
          145  +*/
          146  +typedef struct winMemData winMemData;
          147  +struct winMemData {
          148  +  u32 magic;    /* Magic number to detect structure corruption. */
          149  +  HANDLE hHeap; /* The handle to our heap. */
          150  +  BOOL bOwned;  /* Do we own the heap (i.e. destroy it on shutdown)? */
          151  +};
          152  +
          153  +#define WINMEM_MAGIC     0x42b2830b
          154  +
          155  +static struct winMemData win_mem_data = { WINMEM_MAGIC, NULL, FALSE };
          156  +
          157  +static void *winMemMalloc(int nBytes);
          158  +static void winMemFree(void *pPrior);
          159  +static void *winMemRealloc(void *pPrior, int nBytes);
          160  +static int winMemSize(void *p);
          161  +static int winMemRoundup(int n);
          162  +static int winMemInit(void *pAppData);
          163  +static void winMemShutdown(void *pAppData);
          164  +
          165  +const sqlite3_mem_methods *sqlite3MemGetWin32(void);
          166  +#endif /* SQLITE_WIN32_MALLOC */
   122    167   
   123    168   /*
   124    169   ** Forward prototypes.
   125    170   */
   126    171   static int getSectorSize(
   127    172       sqlite3_vfs *pVfs,
   128    173       const char *zRelative     /* UTF-8 file name */
................................................................................
   167    212         GetVersionEx(&sInfo);
   168    213         sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
   169    214       }
   170    215       return sqlite3_os_type==2;
   171    216     }
   172    217   #endif /* SQLITE_OS_WINCE */
   173    218   
          219  +#ifdef SQLITE_WIN32_MALLOC
          220  +/*
          221  +** Allocate nBytes of memory.
          222  +*/
          223  +static void *winMemMalloc(int nBytes){
          224  +  HANDLE hHeap;
          225  +
          226  +  assert( win_mem_data.magic==WINMEM_MAGIC );
          227  +  hHeap = win_mem_data.hHeap;
          228  +  assert( hHeap!=0 );
          229  +  assert( hHeap!=INVALID_HANDLE_VALUE );
          230  +#ifdef SQLITE_WIN32_MALLOC_VALIDATE
          231  +  assert ( HeapValidate(hHeap, 0, NULL) );
          232  +#endif
          233  +  assert( nBytes>=0 );
          234  +  return HeapAlloc(hHeap, 0, (SIZE_T)nBytes);
          235  +}
          236  +
          237  +/*
          238  +** Free memory.
          239  +*/
          240  +static void winMemFree(void *pPrior){
          241  +  HANDLE hHeap;
          242  +
          243  +  assert( win_mem_data.magic==WINMEM_MAGIC );
          244  +  hHeap = win_mem_data.hHeap;
          245  +  assert( hHeap!=0 );
          246  +  assert( hHeap!=INVALID_HANDLE_VALUE );
          247  +#ifdef SQLITE_WIN32_MALLOC_VALIDATE
          248  +  assert ( HeapValidate(hHeap, 0, pPrior) );
          249  +#endif
          250  +  if (!pPrior) return; /* Passing NULL to HeapFree is undefined. */
          251  +  HeapFree(hHeap, 0, pPrior);
          252  +}
          253  +
          254  +/*
          255  +** Change the size of an existing memory allocation
          256  +*/
          257  +static void *winMemRealloc(void *pPrior, int nBytes){
          258  +  HANDLE hHeap;
          259  +
          260  +  assert( win_mem_data.magic==WINMEM_MAGIC );
          261  +  hHeap = win_mem_data.hHeap;
          262  +  assert( hHeap!=0 );
          263  +  assert( hHeap!=INVALID_HANDLE_VALUE );
          264  +#ifdef SQLITE_WIN32_MALLOC_VALIDATE
          265  +  assert ( HeapValidate(hHeap, 0, pPrior) );
          266  +#endif
          267  +  assert( nBytes>=0 );
          268  +  if (!pPrior) return HeapAlloc(hHeap, 0, (SIZE_T)nBytes);
          269  +  return HeapReAlloc(hHeap, 0, pPrior, (SIZE_T)nBytes);
          270  +}
          271  +
          272  +/*
          273  +** Return the size of an outstanding allocation, in bytes.
          274  +*/
          275  +static int winMemSize(void *p){
          276  +  HANDLE hHeap;
          277  +  SIZE_T n;
          278  +
          279  +  assert( win_mem_data.magic==WINMEM_MAGIC );
          280  +  hHeap = win_mem_data.hHeap;
          281  +  assert( hHeap!=0 );
          282  +  assert( hHeap!=INVALID_HANDLE_VALUE );
          283  +#ifdef SQLITE_WIN32_MALLOC_VALIDATE
          284  +  assert ( HeapValidate(hHeap, 0, NULL) );
          285  +#endif
          286  +  if (!p) return 0;
          287  +  n = HeapSize(hHeap, 0, p);
          288  +  assert( n<=INT_MAX );
          289  +  return (int)n;
          290  +}
          291  +
          292  +/*
          293  +** Round up a request size to the next valid allocation size.
          294  +*/
          295  +static int winMemRoundup(int n){
          296  +  return n;
          297  +}
          298  +
          299  +/*
          300  +** Initialize this module.
          301  +*/
          302  +static int winMemInit(void *pAppData){
          303  +  winMemData *pWinMemData = (winMemData *)pAppData;
          304  +
          305  +  if (!pWinMemData) return SQLITE_ERROR;
          306  +  assert( pWinMemData->magic==WINMEM_MAGIC );
          307  +  if (!pWinMemData->hHeap){
          308  +    pWinMemData->hHeap = HeapCreate(0, SQLITE_WIN32_HEAP_INIT_SIZE,
          309  +                                    SQLITE_WIN32_HEAP_MAX_SIZE);
          310  +    if (!pWinMemData->hHeap){
          311  +      return SQLITE_NOMEM;
          312  +    }
          313  +    pWinMemData->bOwned = TRUE;
          314  +  }
          315  +  assert( pWinMemData->hHeap!=0 );
          316  +  assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
          317  +#ifdef SQLITE_WIN32_MALLOC_VALIDATE
          318  +  assert( HeapValidate(pWinMemData->hHeap, 0, NULL) );
          319  +#endif
          320  +  return SQLITE_OK;
          321  +}
          322  +
          323  +/*
          324  +** Deinitialize this module.
          325  +*/
          326  +static void winMemShutdown(void *pAppData){
          327  +  winMemData *pWinMemData = (winMemData *)pAppData;
          328  +
          329  +  if (!pWinMemData) return;
          330  +  if (pWinMemData->hHeap){
          331  +    assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
          332  +#ifdef SQLITE_WIN32_MALLOC_VALIDATE
          333  +    assert( HeapValidate(pWinMemData->hHeap, 0, NULL) );
          334  +#endif
          335  +    if (pWinMemData->bOwned){
          336  +      if (!HeapDestroy(pWinMemData->hHeap)){
          337  +        /* TODO: Log this? */
          338  +      }
          339  +      pWinMemData->bOwned = FALSE;
          340  +    }
          341  +    pWinMemData->hHeap = NULL;
          342  +  }
          343  +}
          344  +
          345  +/*
          346  +** Populate the low-level memory allocation function pointers in
          347  +** sqlite3GlobalConfig.m with pointers to the routines in this file. The
          348  +** arguments specify the block of memory to manage.
          349  +**
          350  +** This routine is only called by sqlite3_config(), and therefore
          351  +** is not required to be threadsafe (it is not).
          352  +*/
          353  +const sqlite3_mem_methods *sqlite3MemGetWin32(void){
          354  +  static const sqlite3_mem_methods winMemMethods = {
          355  +    winMemMalloc,
          356  +    winMemFree,
          357  +    winMemRealloc,
          358  +    winMemSize,
          359  +    winMemRoundup,
          360  +    winMemInit,
          361  +    winMemShutdown,
          362  +    &win_mem_data
          363  +  };
          364  +  return &winMemMethods;
          365  +}
          366  +
          367  +void sqlite3MemSetDefault(void){
          368  +  sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
          369  +}
          370  +#endif /* SQLITE_WIN32_MALLOC */
          371  +
   174    372   /*
   175    373   ** Convert a UTF-8 string to microsoft unicode (UTF-16?). 
   176    374   **
   177    375   ** Space to hold the returned string is obtained from malloc.
   178    376   */
   179    377   static WCHAR *utf8ToUnicode(const char *zFilename){
   180    378     int nChar;

Changes to src/sqliteInt.h.

   143    143   #endif
   144    144   
   145    145   /*
   146    146   ** Exactly one of the following macros must be defined in order to
   147    147   ** specify which memory allocation subsystem to use.
   148    148   **
   149    149   **     SQLITE_SYSTEM_MALLOC          // Use normal system malloc()
          150  +**     SQLITE_WIN32_MALLOC           // Use Win32 native heap API
   150    151   **     SQLITE_MEMDEBUG               // Debugging version of system malloc()
   151    152   **
   152    153   ** (Historical note:  There used to be several other options, but we've
   153    154   ** pared it down to just these two.)
   154    155   **
   155    156   ** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
   156    157   ** the default.
   157    158   */
   158         -#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1
          159  +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1
   159    160   # error "At most one of the following compile-time configuration options\
   160    161    is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
   161    162   #endif
   162         -#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0
          163  +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0
   163    164   # define SQLITE_SYSTEM_MALLOC 1
   164    165   #endif
   165    166   
   166    167   /*
   167    168   ** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
   168    169   ** sizes of memory allocations below this value where possible.
   169    170   */