/ Check-in [75c095ee]
Login

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

Overview
Comment:Reorganize code to remove a few of the branches introduced into the critical sqlite3DbMallocXXX() path by the previous commit.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | calloc
Files: files | file ages | folders
SHA1:75c095ee463c0c76e9637edccd33e807f837eb4e
User & Date: dan 2012-07-18 11:28:51
Context
2012-07-18
16:07
Remove another branch from the DbMalloc() paths. check-in: defd828e user: dan tags: calloc
11:28
Reorganize code to remove a few of the branches introduced into the critical sqlite3DbMallocXXX() path by the previous commit. check-in: 75c095ee user: dan tags: calloc
2012-07-17
19:32
Enhance the custom memory allocation interface to allow the user to specify a calloc() function. check-in: 8752237d user: dan tags: calloc
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/malloc.c.

   255    255     mem0.alarmArg = pArg;
   256    256   }
   257    257   
   258    258   /*
   259    259   ** Do a memory allocation with statistics and alarms.  Assume the
   260    260   ** lock is already held.
   261    261   */
   262         -static int mallocWithAlarm(
          262  +static void *mallocWithAlarm(
   263    263     void *(*xAlloc)(int),          /* Memory allocation function */
   264         -  int n,                         /* Bytes of memory to allocate */
   265         -  void **pp                      /* OUT: Pointer to allocation */
          264  +  int n                          /* Bytes of memory to allocate */
   266    265   ){
   267    266     int nFull;
   268    267     void *p;
   269    268   
   270    269     assert( sqlite3_mutex_held(mem0.mutex) );
   271    270     assert( xAlloc==sqlite3GlobalConfig.m.xMalloc 
   272    271          || xAlloc==sqlite3GlobalConfig.m.xCalloc 
................................................................................
   290    289     }
   291    290   #endif
   292    291     if( p ){
   293    292       nFull = sqlite3MallocSize(p);
   294    293       sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
   295    294       sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
   296    295     }
   297         -  *pp = p;
   298         -  return nFull;
          296  +
          297  +  return p;
   299    298   }
   300    299   
   301    300   /*
   302    301   ** Use allocator function xAlloc to allocate n bytes of memory.
   303    302   */
   304    303   static void *memAllocate(
   305    304     void *(*xAlloc)(int),           /* Memory allocation function */
................................................................................
   313    312       ** signed integer value might cause an integer overflow inside of the
   314    313       ** xMalloc().  Hence we limit the maximum size to 0x7fffff00, giving
   315    314       ** 255 bytes of overhead.  SQLite itself will never use anything near
   316    315       ** this amount.  The only way to reach the limit is with sqlite3_malloc() */
   317    316       p = 0;
   318    317     }else if( sqlite3GlobalConfig.bMemstat ){
   319    318       sqlite3_mutex_enter(mem0.mutex);
   320         -    mallocWithAlarm(xAlloc, n, &p);
          319  +    p = mallocWithAlarm(xAlloc, n);
   321    320       sqlite3_mutex_leave(mem0.mutex);
   322    321     }else{
   323    322       p = xAlloc(n);
   324    323     }
   325    324     assert( EIGHT_BYTE_ALIGNMENT(p) );  /* IMP: R-04675-44850 */
   326    325     return p;
   327    326   }
................................................................................
   384    383       mem0.nScratchFree--;
   385    384       sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
   386    385       sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
   387    386       sqlite3_mutex_leave(mem0.mutex);
   388    387     }else{
   389    388       if( sqlite3GlobalConfig.bMemstat ){
   390    389         sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
   391         -      n = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n, &p);
   392         -      if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
          390  +      p = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n);
          391  +      if( p ){
          392  +        n = sqlite3MallocSize(p);
          393  +        sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
          394  +      }
   393    395         sqlite3_mutex_leave(mem0.mutex);
   394    396       }else{
   395    397         sqlite3_mutex_leave(mem0.mutex);
   396    398         p = sqlite3GlobalConfig.m.xMalloc(n);
   397    399       }
   398    400       sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
   399    401     }
................................................................................
   593    595   #ifndef SQLITE_OMIT_AUTOINIT
   594    596     if( sqlite3_initialize() ) return 0;
   595    597   #endif
   596    598     return sqlite3Realloc(pOld, n);
   597    599   }
   598    600   
   599    601   /*
   600         -** Allocate and, if bZero is true, zero memory. If the allocation 
   601         -** fails, set the mallocFailed flag in the connection pointer.
          602  +** Attempt to allocate an n byte block from the lookaside buffer of
          603  +** connection db. If successful, return a pointer to the new allocation.
          604  +** Otherwise, return a NULL pointer.
          605  +*/
          606  +#ifndef SQLITE_OMIT_LOOKASIDE
          607  +static void *lookasideAlloc(sqlite3 *db, int n){
          608  +  if( db->lookaside.bEnabled ){
          609  +    if( n>db->lookaside.sz ){
          610  +      db->lookaside.anStat[1]++;
          611  +    }else{
          612  +      LookasideSlot *pBuf;
          613  +      if( (pBuf = db->lookaside.pFree)==0 ){
          614  +        db->lookaside.anStat[2]++;
          615  +      }else{
          616  +        db->lookaside.pFree = pBuf->pNext;
          617  +        db->lookaside.nOut++;
          618  +        db->lookaside.anStat[0]++;
          619  +        if( db->lookaside.nOut>db->lookaside.mxOut ){
          620  +          db->lookaside.mxOut = db->lookaside.nOut;
          621  +        }
          622  +      }
          623  +      return (void*)pBuf;
          624  +    }
          625  +  }
          626  +  return 0;
          627  +}
          628  +#else
          629  +# define lookasideAlloc(x,y) 0
          630  +#endif
          631  +
          632  +/*
          633  +** Allocate and zero memory. If the allocation fails, set the 
          634  +** mallocFailed flag in the connection pointer.
   602    635   **
   603    636   ** If db!=0 and db->mallocFailed is true (indicating a prior malloc
   604    637   ** failure on the same database connection) then always return 0.
   605    638   ** Hence for a particular database connection, once malloc starts
   606    639   ** failing, it fails consistently until mallocFailed is reset.
   607    640   ** This is an important assumption.  There are many places in the
   608    641   ** code that do things like this:
................................................................................
   610    643   **         int *a = (int*)sqlite3DbMallocRaw(db, 100);
   611    644   **         int *b = (int*)sqlite3DbMallocRaw(db, 200);
   612    645   **         if( b ) a[10] = 9;
   613    646   **
   614    647   ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
   615    648   ** that all prior mallocs (ex: "a") worked too.
   616    649   */
   617         -static void *dbMalloc(sqlite3 *db, int n, int bZero){
          650  +void *sqlite3DbMallocZero(sqlite3 *db, int n){
   618    651     void *p;
   619         -  assert( db==0 || sqlite3_mutex_held(db->mutex) );
   620         -  assert( db==0 || db->pnBytesFreed==0 );
   621         -#ifndef SQLITE_OMIT_LOOKASIDE
   622         -  if( db ){
   623         -    LookasideSlot *pBuf;
   624         -    if( db->mallocFailed ){
   625         -      return 0;
   626         -    }
   627         -    if( db->lookaside.bEnabled ){
   628         -      if( n>db->lookaside.sz ){
   629         -        db->lookaside.anStat[1]++;
   630         -      }else if( (pBuf = db->lookaside.pFree)==0 ){
   631         -        db->lookaside.anStat[2]++;
   632         -      }else{
   633         -        db->lookaside.pFree = pBuf->pNext;
   634         -        db->lookaside.nOut++;
   635         -        db->lookaside.anStat[0]++;
   636         -        if( db->lookaside.nOut>db->lookaside.mxOut ){
   637         -          db->lookaside.mxOut = db->lookaside.nOut;
   638         -        }
   639         -        if( bZero ) memset(pBuf, 0, n);
   640         -        return (void*)pBuf;
   641         -      }
          652  +  if( db==0 ){
          653  +    p = memAllocate(sqlite3GlobalConfig.m.xCalloc, n);
          654  +  }else if( db->mallocFailed ){
          655  +    p = 0;
          656  +  }else{
          657  +    if( (p = lookasideAlloc(db, n)) ){
          658  +      memset(p, 0, n);
          659  +    }else{
          660  +      p = memAllocate(sqlite3GlobalConfig.m.xCalloc, n);
          661  +      if( !p ) db->mallocFailed = 1;
   642    662       }
   643    663     }
   644         -#else
   645         -  if( db && db->mallocFailed ){
   646         -    return 0;
   647         -  }
   648         -#endif
   649         -  if( bZero ){
   650         -    p = sqlite3MallocZero(n);
   651         -  }else{
   652         -    p = sqlite3Malloc(n);
   653         -  }
   654         -  if( !p && db ){
   655         -    db->mallocFailed = 1;
   656         -  }
          664  +
   657    665     sqlite3MemdebugSetType(p, MEMTYPE_DB |
   658    666            ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
   659    667     return p;
   660         -} 
   661         -
   662         -/*
   663         -** Allocate and zero memory. If the allocation fails, set the 
   664         -** mallocFailed flag in the connection pointer.
   665         -*/
   666         -void *sqlite3DbMallocZero(sqlite3 *db, int n){
   667         -  return dbMalloc(db, n, 1);
   668    668   }
   669    669   
   670    670   /*
   671    671   ** Allocate memory. If the allocation fails, make the mallocFailed 
   672    672   ** flag in the connection pointer.
          673  +**
          674  +** If db!=0 and db->mallocFailed is true (indicating a prior malloc
          675  +** failure on the same database connection) then always return 0.
          676  +** See also comments above sqlite3DbMallocZero() for details.
   673    677   */
   674    678   void *sqlite3DbMallocRaw(sqlite3 *db, int n){
   675         -  return dbMalloc(db, n, 0);
          679  +  void *p;
          680  +  if( db==0 ){
          681  +    p = memAllocate(sqlite3GlobalConfig.m.xMalloc, n);
          682  +  }else if( db->mallocFailed ){
          683  +    p = 0;
          684  +  }else{
          685  +    p = lookasideAlloc(db, n);
          686  +    if( !p ){
          687  +      p = memAllocate(sqlite3GlobalConfig.m.xMalloc, n);
          688  +      if( !p ) db->mallocFailed = 1;
          689  +    }
          690  +  }
          691  +
          692  +  sqlite3MemdebugSetType(p, MEMTYPE_DB |
          693  +         ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
          694  +  return p;
   676    695   }
   677    696   
   678    697   /*
   679    698   ** Resize the block of memory pointed to by p to n bytes. If the
   680    699   ** resize fails, set the mallocFailed flag in the connection object.
   681    700   */
   682    701   void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){

Changes to src/mem1.c.

    98     98   #else
    99     99   # undef SQLITE_MALLOCSIZE
   100    100   #endif
   101    101   
   102    102   #endif /* __APPLE__ or not __APPLE__ */
   103    103   
   104    104   /*
   105         -** Like malloc() (if bZero==0) or calloc() (if bZero!=0), except remember 
   106         -** the size of the allocation so that we can find it later using 
   107         -** sqlite3MemSize().
          105  +** A memory allocation of nByte bytes has failed. Log an error message
          106  +** using sqlite3_log().
          107  +*/
          108  +static void logAllocationError(int nByte){
          109  +  testcase( sqlite3GlobalConfig.xLog!=0 );
          110  +  sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
          111  +}
          112  +
          113  +/*
          114  +** Allocate nByte bytes of memory.
          115  +**
          116  +** For this low-level routine, we are guaranteed that nByte>0 because
          117  +** cases of nByte<=0 will be intercepted and dealt with by higher level
          118  +** routines.
          119  +*/
          120  +static void *sqlite3MemMalloc(int nByte){
          121  +  i64 *p;
          122  +#ifdef SQLITE_MALLOCSIZE
          123  +  p = SQLITE_MALLOC(nByte);
          124  +  if( p==0 ){
          125  +#else
          126  +  nByte = ROUND8(nByte);
          127  +  p = SQLITE_MALLOC(nByte+8);
          128  +  if( p ){
          129  +    *(p++) = (i64)nByte;
          130  +  }else{
          131  +#endif
          132  +    logAllocationError(nByte);
          133  +  }
          134  +  return (void *)p;
          135  +}
          136  +
          137  +/*
          138  +** Allocate and zero nByte bytes of memory.
   108    139   **
   109    140   ** For this low-level routine, we are guaranteed that nByte>0 because
   110    141   ** cases of nByte<=0 will be intercepted and dealt with by higher level
   111    142   ** routines.
   112    143   */
   113         -static void *memMalloc(int nByte, int bZero){
          144  +static void *sqlite3MemCalloc(int nByte){
          145  +  i64 *p;
   114    146   #ifdef SQLITE_MALLOCSIZE
   115         -  void *p = (bZero ? SQLITE_CALLOC( nByte ) : SQLITE_MALLOC( nByte ));
          147  +  p = SQLITE_CALLOC(nByte);
   116    148     if( p==0 ){
   117         -    testcase( sqlite3GlobalConfig.xLog!=0 );
   118         -    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
   119         -  }
   120         -  return p;
   121    149   #else
   122         -  sqlite3_int64 *p;
   123         -  assert( nByte>0 );
   124    150     nByte = ROUND8(nByte);
   125         -  p = (bZero ? SQLITE_CALLOC( nByte+8 ) : SQLITE_MALLOC( nByte+8 ));
          151  +  p = SQLITE_CALLOC(nByte+8);
   126    152     if( p ){
   127         -    p[0] = nByte;
   128         -    p++;
          153  +    *(p++) = (i64)nByte;
   129    154     }else{
   130         -    testcase( sqlite3GlobalConfig.xLog!=0 );
   131         -    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
          155  +#endif
          156  +    logAllocationError(nByte);
   132    157     }
   133    158     return (void *)p;
   134         -#endif
   135         -}
   136         -
   137         -static void *sqlite3MemMalloc(int nByte){
   138         -  return memMalloc(nByte, 0);
   139         -}
   140         -static void *sqlite3MemCalloc(int nByte){
   141         -  return memMalloc(nByte, 1);
   142    159   }
   143    160   
   144    161   /*
   145    162   ** Like free() but works for allocations obtained from sqlite3MemMalloc()
   146    163   ** or sqlite3MemRealloc().
   147    164   **
   148    165   ** For this low-level routine, we already know that pPrior!=0 since