SQLite

Check-in [75c095ee46]
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
Timelines: family | ancestors | descendants | both | calloc
Files: files | file ages | folders
SHA1: 75c095ee463c0c76e9637edccd33e807f837eb4e
User & Date: dan 2012-07-18 11:28:51.265
Context
2012-07-18
16:07
Remove another branch from the DbMalloc() paths. (check-in: defd828e90 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: 75c095ee46 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: 8752237d12 user: dan tags: calloc)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/malloc.c.
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
  mem0.alarmArg = pArg;
}

/*
** Do a memory allocation with statistics and alarms.  Assume the
** lock is already held.
*/
static int mallocWithAlarm(
  void *(*xAlloc)(int),          /* Memory allocation function */
  int n,                         /* Bytes of memory to allocate */
  void **pp                      /* OUT: Pointer to allocation */
){
  int nFull;
  void *p;

  assert( sqlite3_mutex_held(mem0.mutex) );
  assert( xAlloc==sqlite3GlobalConfig.m.xMalloc 
       || xAlloc==sqlite3GlobalConfig.m.xCalloc 







|

|
<







255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
  mem0.alarmArg = pArg;
}

/*
** Do a memory allocation with statistics and alarms.  Assume the
** lock is already held.
*/
static void *mallocWithAlarm(
  void *(*xAlloc)(int),          /* Memory allocation function */
  int n                          /* Bytes of memory to allocate */

){
  int nFull;
  void *p;

  assert( sqlite3_mutex_held(mem0.mutex) );
  assert( xAlloc==sqlite3GlobalConfig.m.xMalloc 
       || xAlloc==sqlite3GlobalConfig.m.xCalloc 
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  }
#endif
  if( p ){
    nFull = sqlite3MallocSize(p);
    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
    sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
  }
  *pp = p;
  return nFull;
}

/*
** Use allocator function xAlloc to allocate n bytes of memory.
*/
static void *memAllocate(
  void *(*xAlloc)(int),           /* Memory allocation function */







|
|







289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  }
#endif
  if( p ){
    nFull = sqlite3MallocSize(p);
    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
    sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
  }

  return p;
}

/*
** Use allocator function xAlloc to allocate n bytes of memory.
*/
static void *memAllocate(
  void *(*xAlloc)(int),           /* Memory allocation function */
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
    ** signed integer value might cause an integer overflow inside of the
    ** xMalloc().  Hence we limit the maximum size to 0x7fffff00, giving
    ** 255 bytes of overhead.  SQLite itself will never use anything near
    ** this amount.  The only way to reach the limit is with sqlite3_malloc() */
    p = 0;
  }else if( sqlite3GlobalConfig.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    mallocWithAlarm(xAlloc, n, &p);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    p = xAlloc(n);
  }
  assert( EIGHT_BYTE_ALIGNMENT(p) );  /* IMP: R-04675-44850 */
  return p;
}







|







312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
    ** signed integer value might cause an integer overflow inside of the
    ** xMalloc().  Hence we limit the maximum size to 0x7fffff00, giving
    ** 255 bytes of overhead.  SQLite itself will never use anything near
    ** this amount.  The only way to reach the limit is with sqlite3_malloc() */
    p = 0;
  }else if( sqlite3GlobalConfig.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    p = mallocWithAlarm(xAlloc, n);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    p = xAlloc(n);
  }
  assert( EIGHT_BYTE_ALIGNMENT(p) );  /* IMP: R-04675-44850 */
  return p;
}
384
385
386
387
388
389
390
391


392

393
394
395
396
397
398
399
    mem0.nScratchFree--;
    sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
    sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    if( sqlite3GlobalConfig.bMemstat ){
      sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
      n = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n, &p);


      if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);

      sqlite3_mutex_leave(mem0.mutex);
    }else{
      sqlite3_mutex_leave(mem0.mutex);
      p = sqlite3GlobalConfig.m.xMalloc(n);
    }
    sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
  }







|
>
>
|
>







383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
    mem0.nScratchFree--;
    sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
    sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    if( sqlite3GlobalConfig.bMemstat ){
      sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
      p = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n);
      if( p ){
        n = sqlite3MallocSize(p);
        sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
      }
      sqlite3_mutex_leave(mem0.mutex);
    }else{
      sqlite3_mutex_leave(mem0.mutex);
      p = sqlite3GlobalConfig.m.xMalloc(n);
    }
    sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
  }
593
594
595
596
597
598
599































600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672




673
674















675
676
677
678
679
680
681
682
#ifndef SQLITE_OMIT_AUTOINIT
  if( sqlite3_initialize() ) return 0;
#endif
  return sqlite3Realloc(pOld, n);
}

/*































** Allocate and, if bZero is true, zero memory. If the allocation 
** fails, set the mallocFailed flag in the connection pointer.
**
** If db!=0 and db->mallocFailed is true (indicating a prior malloc
** failure on the same database connection) then always return 0.
** Hence for a particular database connection, once malloc starts
** failing, it fails consistently until mallocFailed is reset.
** This is an important assumption.  There are many places in the
** code that do things like this:
**
**         int *a = (int*)sqlite3DbMallocRaw(db, 100);
**         int *b = (int*)sqlite3DbMallocRaw(db, 200);
**         if( b ) a[10] = 9;
**
** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
** that all prior mallocs (ex: "a") worked too.
*/
static void *dbMalloc(sqlite3 *db, int n, int bZero){
  void *p;
  assert( db==0 || sqlite3_mutex_held(db->mutex) );
  assert( db==0 || db->pnBytesFreed==0 );
#ifndef SQLITE_OMIT_LOOKASIDE
  if( db ){
    LookasideSlot *pBuf;

    if( db->mallocFailed ){
      return 0;
    }
    if( db->lookaside.bEnabled ){
      if( n>db->lookaside.sz ){
        db->lookaside.anStat[1]++;
      }else if( (pBuf = db->lookaside.pFree)==0 ){
        db->lookaside.anStat[2]++;
      }else{
        db->lookaside.pFree = pBuf->pNext;
        db->lookaside.nOut++;
        db->lookaside.anStat[0]++;
        if( db->lookaside.nOut>db->lookaside.mxOut ){
          db->lookaside.mxOut = db->lookaside.nOut;
        }
        if( bZero ) memset(pBuf, 0, n);
        return (void*)pBuf;
      }
    }
  }
#else

  if( db && db->mallocFailed ){
    return 0;
  }
#endif
  if( bZero ){
    p = sqlite3MallocZero(n);
  }else{
    p = sqlite3Malloc(n);
  }
  if( !p && db ){
    db->mallocFailed = 1;
  }
  sqlite3MemdebugSetType(p, MEMTYPE_DB |
         ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
  return p;
} 

/*
** Allocate and zero memory. If the allocation fails, set the 
** mallocFailed flag in the connection pointer.
*/
void *sqlite3DbMallocZero(sqlite3 *db, int n){
  return dbMalloc(db, n, 1);
}

/*
** Allocate memory. If the allocation fails, make the mallocFailed 
** flag in the connection pointer.




*/
void *sqlite3DbMallocRaw(sqlite3 *db, int n){















  return dbMalloc(db, n, 0);
}

/*
** Resize the block of memory pointed to by p to n bytes. If the
** resize fails, set the mallocFailed flag in the connection object.
*/
void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|















|

<
<
<
|
<
>
|
|
<
<
<
<
<
<
|
<
|
<
<
<
<
|
<
<
<
<
|
>
|
<
|
<
<
<
<
<

<
<
|



<
<
<
<
<
<
<
<





>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651



652

653
654
655






656

657




658




659
660
661

662





663


664
665
666
667








668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
#ifndef SQLITE_OMIT_AUTOINIT
  if( sqlite3_initialize() ) return 0;
#endif
  return sqlite3Realloc(pOld, n);
}

/*
** Attempt to allocate an n byte block from the lookaside buffer of
** connection db. If successful, return a pointer to the new allocation.
** Otherwise, return a NULL pointer.
*/
#ifndef SQLITE_OMIT_LOOKASIDE
static void *lookasideAlloc(sqlite3 *db, int n){
  if( db->lookaside.bEnabled ){
    if( n>db->lookaside.sz ){
      db->lookaside.anStat[1]++;
    }else{
      LookasideSlot *pBuf;
      if( (pBuf = db->lookaside.pFree)==0 ){
        db->lookaside.anStat[2]++;
      }else{
        db->lookaside.pFree = pBuf->pNext;
        db->lookaside.nOut++;
        db->lookaside.anStat[0]++;
        if( db->lookaside.nOut>db->lookaside.mxOut ){
          db->lookaside.mxOut = db->lookaside.nOut;
        }
      }
      return (void*)pBuf;
    }
  }
  return 0;
}
#else
# define lookasideAlloc(x,y) 0
#endif

/*
** Allocate and zero memory. If the allocation fails, set the 
** mallocFailed flag in the connection pointer.
**
** If db!=0 and db->mallocFailed is true (indicating a prior malloc
** failure on the same database connection) then always return 0.
** Hence for a particular database connection, once malloc starts
** failing, it fails consistently until mallocFailed is reset.
** This is an important assumption.  There are many places in the
** code that do things like this:
**
**         int *a = (int*)sqlite3DbMallocRaw(db, 100);
**         int *b = (int*)sqlite3DbMallocRaw(db, 200);
**         if( b ) a[10] = 9;
**
** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
** that all prior mallocs (ex: "a") worked too.
*/
void *sqlite3DbMallocZero(sqlite3 *db, int n){
  void *p;



  if( db==0 ){

    p = memAllocate(sqlite3GlobalConfig.m.xCalloc, n);
  }else if( db->mallocFailed ){
    p = 0;






  }else{

    if( (p = lookasideAlloc(db, n)) ){




      memset(p, 0, n);




    }else{
      p = memAllocate(sqlite3GlobalConfig.m.xCalloc, n);
      if( !p ) db->mallocFailed = 1;

    }





  }



  sqlite3MemdebugSetType(p, MEMTYPE_DB |
         ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
  return p;








}

/*
** Allocate memory. If the allocation fails, make the mallocFailed 
** flag in the connection pointer.
**
** If db!=0 and db->mallocFailed is true (indicating a prior malloc
** failure on the same database connection) then always return 0.
** See also comments above sqlite3DbMallocZero() for details.
*/
void *sqlite3DbMallocRaw(sqlite3 *db, int n){
  void *p;
  if( db==0 ){
    p = memAllocate(sqlite3GlobalConfig.m.xMalloc, n);
  }else if( db->mallocFailed ){
    p = 0;
  }else{
    p = lookasideAlloc(db, n);
    if( !p ){
      p = memAllocate(sqlite3GlobalConfig.m.xMalloc, n);
      if( !p ) db->mallocFailed = 1;
    }
  }

  sqlite3MemdebugSetType(p, MEMTYPE_DB |
         ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
  return p;
}

/*
** Resize the block of memory pointed to by p to n bytes. If the
** resize fails, set the mallocFailed flag in the connection object.
*/
void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
Changes to src/mem1.c.
98
99
100
101
102
103
104
105


106



107


108
109
110
111
112
113

114
115
116
117

118






119
120

121








122

123


124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#else
# undef SQLITE_MALLOCSIZE
#endif

#endif /* __APPLE__ or not __APPLE__ */

/*
** Like malloc() (if bZero==0) or calloc() (if bZero!=0), except remember 


** the size of the allocation so that we can find it later using 



** sqlite3MemSize().


**
** For this low-level routine, we are guaranteed that nByte>0 because
** cases of nByte<=0 will be intercepted and dealt with by higher level
** routines.
*/
static void *memMalloc(int nByte, int bZero){

#ifdef SQLITE_MALLOCSIZE
  void *p = (bZero ? SQLITE_CALLOC( nByte ) : SQLITE_MALLOC( nByte ));
  if( p==0 ){
    testcase( sqlite3GlobalConfig.xLog!=0 );

    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);






  }
  return p;

#else








  sqlite3_int64 *p;

  assert( nByte>0 );


  nByte = ROUND8(nByte);
  p = (bZero ? SQLITE_CALLOC( nByte+8 ) : SQLITE_MALLOC( nByte+8 ));
  if( p ){
    p[0] = nByte;
    p++;
  }else{
    testcase( sqlite3GlobalConfig.xLog!=0 );
    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
  }
  return (void *)p;
#endif
}

static void *sqlite3MemMalloc(int nByte){
  return memMalloc(nByte, 0);
}
static void *sqlite3MemCalloc(int nByte){
  return memMalloc(nByte, 1);
}

/*
** Like free() but works for allocations obtained from sqlite3MemMalloc()
** or sqlite3MemRealloc().
**
** For this low-level routine, we already know that pPrior!=0 since







|
>
>
|
>
>
>
|
>
>





|
>

|

<
>
|
>
>
>
>
>
>

|
>
|
>
>
>
>
>
>
>
>
|
>
|
>
>

|

|
<

<
<
<
<

<
|
<
<
|
<
|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

154




155

156


157

158
159
160
161
162
163
164
165
#else
# undef SQLITE_MALLOCSIZE
#endif

#endif /* __APPLE__ or not __APPLE__ */

/*
** A memory allocation of nByte bytes has failed. Log an error message
** using sqlite3_log().
*/
static void logAllocationError(int nByte){
  testcase( sqlite3GlobalConfig.xLog!=0 );
  sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
}

/*
** Allocate nByte bytes of memory.
**
** For this low-level routine, we are guaranteed that nByte>0 because
** cases of nByte<=0 will be intercepted and dealt with by higher level
** routines.
*/
static void *sqlite3MemMalloc(int nByte){
  i64 *p;
#ifdef SQLITE_MALLOCSIZE
  p = SQLITE_MALLOC(nByte);
  if( p==0 ){

#else
  nByte = ROUND8(nByte);
  p = SQLITE_MALLOC(nByte+8);
  if( p ){
    *(p++) = (i64)nByte;
  }else{
#endif
    logAllocationError(nByte);
  }
  return (void *)p;
}

/*
** Allocate and zero nByte bytes of memory.
**
** For this low-level routine, we are guaranteed that nByte>0 because
** cases of nByte<=0 will be intercepted and dealt with by higher level
** routines.
*/
static void *sqlite3MemCalloc(int nByte){
  i64 *p;
#ifdef SQLITE_MALLOCSIZE
  p = SQLITE_CALLOC(nByte);
  if( p==0 ){
#else
  nByte = ROUND8(nByte);
  p = SQLITE_CALLOC(nByte+8);
  if( p ){
    *(p++) = (i64)nByte;

  }else{




#endif

    logAllocationError(nByte);


  }

  return (void *)p;
}

/*
** Like free() but works for allocations obtained from sqlite3MemMalloc()
** or sqlite3MemRealloc().
**
** For this low-level routine, we already know that pPrior!=0 since