/ Check-in [0d955c20]
Login

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

Overview
Comment:Hand merge the zone allocator for MacOS from the apple-osx branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0d955c20c02da29582b5cd8df2b7124fb9d12ebb
User & Date: drh 2011-12-08 20:41:33
Context
2011-12-09
05:52
The Windows OS flavor #ifdefs must be performed after the 'windows.h' file has been included. check-in: 3702a31e user: mistachkin tags: trunk
2011-12-08
21:08
Merge the latest trunk changes into the apple-osx branch. check-in: 59e0d4f3 user: drh tags: apple-osx
20:41
Hand merge the zone allocator for MacOS from the apple-osx branch. check-in: 0d955c20 user: drh tags: trunk
19:50
In persistent WAL mode, truncate the WAL file to the size specified by the journal_size_limit pragma when disconnecting from the WAL. check-in: 9687b305 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/mem1.c.

    22     22   /*
    23     23   ** This version of the memory allocator is the default.  It is
    24     24   ** used when no other memory allocator is specified using compile-time
    25     25   ** macros.
    26     26   */
    27     27   #ifdef SQLITE_SYSTEM_MALLOC
    28     28   
           29  +
           30  +#if defined(__APPLE__)
           31  +
           32  +/*
           33  +** Use the zone allocator available on apple products
           34  +*/
           35  +#include <sys/sysctl.h>
           36  +#include <malloc/malloc.h>
           37  +#include <libkern/OSAtomic.h>
           38  +static malloc_zone_t* _sqliteZone_;
           39  +#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
           40  +#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
           41  +#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
           42  +#define SQLITE_MALLOCSIZE(x) \
           43  +        (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
           44  +
           45  +#else /* if not __APPLE__ */
           46  +
           47  +/*
           48  +** Use standard C library malloc and free on non-Apple systems.
           49  +*/
           50  +#define SQLITE_MALLOC(x)    malloc(x)
           51  +#define SQLITE_FREE(x)      free(x)
           52  +#define SQLITE_REALLOC(x,y) realloc((x),(y))
           53  +
    29     54   #ifdef HAVE_MALLOC_USABLE_SIZE
    30     55   #include <malloc.h>
           56  +#define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
           57  +#else
           58  +#undef SQLITE_MALLOCSIZE
    31     59   #endif
           60  +
           61  +#endif /* __APPLE__ or not __APPLE__ */
    32     62   
    33     63   /*
    34     64   ** Like malloc(), but remember the size of the allocation
    35     65   ** so that we can find it later using sqlite3MemSize().
    36     66   **
    37     67   ** For this low-level routine, we are guaranteed that nByte>0 because
    38     68   ** cases of nByte<=0 will be intercepted and dealt with by higher level
    39     69   ** routines.
    40     70   */
    41     71   static void *sqlite3MemMalloc(int nByte){
    42         -#ifdef HAVE_MALLOC_USABLE_SIZE
    43         -  void *p = malloc( nByte );
           72  +#ifdef SQLITE_MALLOCSIZE
           73  +  void *p = SQLITE_MALLOC( nByte );
    44     74     if( p==0 ){
    45     75       testcase( sqlite3GlobalConfig.xLog!=0 );
    46     76       sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
    47     77     }
    48     78     return p;
    49     79   #else
    50     80     sqlite3_int64 *p;
    51     81     assert( nByte>0 );
    52     82     nByte = ROUND8(nByte);
    53         -  p = malloc( nByte+8 );
           83  +  p = SQLITE_MALLOC( nByte+8 );
    54     84     if( p ){
    55     85       p[0] = nByte;
    56     86       p++;
    57     87     }else{
    58     88       testcase( sqlite3GlobalConfig.xLog!=0 );
    59     89       sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
    60     90     }
................................................................................
    67     97   ** or sqlite3MemRealloc().
    68     98   **
    69     99   ** For this low-level routine, we already know that pPrior!=0 since
    70    100   ** cases where pPrior==0 will have been intecepted and dealt with
    71    101   ** by higher-level routines.
    72    102   */
    73    103   static void sqlite3MemFree(void *pPrior){
    74         -#if HAVE_MALLOC_USABLE_SIZE
    75         -  free(pPrior);
          104  +#ifdef SQLITE_MALLOCSIZE
          105  +  SQLITE_FREE(pPrior);
    76    106   #else
    77    107     sqlite3_int64 *p = (sqlite3_int64*)pPrior;
    78    108     assert( pPrior!=0 );
    79    109     p--;
    80         -  free(p);
          110  +  SQLITE_FREE(p);
    81    111   #endif
    82    112   }
    83    113   
    84    114   /*
    85    115   ** Report the allocated size of a prior return from xMalloc()
    86    116   ** or xRealloc().
    87    117   */
    88    118   static int sqlite3MemSize(void *pPrior){
    89         -#if HAVE_MALLOC_USABLE_SIZE
    90         -  return pPrior ? (int)malloc_usable_size(pPrior) : 0;
          119  +#ifdef SQLITE_MALLOCSIZE
          120  +  return pPrior ? (int)SQLITE_MALLOCSIZE(pPrior) : 0;
    91    121   #else
    92    122     sqlite3_int64 *p;
    93    123     if( pPrior==0 ) return 0;
    94    124     p = (sqlite3_int64*)pPrior;
    95    125     p--;
    96    126     return (int)p[0];
    97    127   #endif
................................................................................
   104    134   ** For this low-level interface, we know that pPrior!=0.  Cases where
   105    135   ** pPrior==0 while have been intercepted by higher-level routine and
   106    136   ** redirected to xMalloc.  Similarly, we know that nByte>0 becauses
   107    137   ** cases where nByte<=0 will have been intercepted by higher-level
   108    138   ** routines and redirected to xFree.
   109    139   */
   110    140   static void *sqlite3MemRealloc(void *pPrior, int nByte){
   111         -#if HAVE_MALLOC_USABLE_SIZE
   112         -  void *p = realloc(pPrior, nByte);
          141  +#ifdef SQLITE_MALLOCSIZE
          142  +  void *p = SQLITE_REALLOC(pPrior, nByte);
   113    143     if( p==0 ){
   114    144       testcase( sqlite3GlobalConfig.xLog!=0 );
   115    145       sqlite3_log(SQLITE_NOMEM,
   116    146         "failed memory resize %u to %u bytes",
   117         -      malloc_usable_size(pPrior), nByte);
          147  +      SQLITE_MALLOCSIZE(pPrior), nByte);
   118    148     }
   119    149     return p;
   120    150   #else
   121    151     sqlite3_int64 *p = (sqlite3_int64*)pPrior;
   122    152     assert( pPrior!=0 && nByte>0 );
   123    153     assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
   124    154     p--;
   125         -  p = realloc(p, nByte+8 );
          155  +  p = SQLITE_REALLOC(p, nByte+8 );
   126    156     if( p ){
   127    157       p[0] = nByte;
   128    158       p++;
   129    159     }else{
   130    160       testcase( sqlite3GlobalConfig.xLog!=0 );
   131    161       sqlite3_log(SQLITE_NOMEM,
   132    162         "failed memory resize %u to %u bytes",
................................................................................
   143    173     return ROUND8(n);
   144    174   }
   145    175   
   146    176   /*
   147    177   ** Initialize this module.
   148    178   */
   149    179   static int sqlite3MemInit(void *NotUsed){
          180  +#if defined(__APPLE__)
          181  +  int cpuCount;
          182  +  size_t len;
          183  +  if( _sqliteZone_ ){
          184  +    return SQLITE_OK;
          185  +  }
          186  +  len = sizeof(cpuCount);
          187  +  /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
          188  +  sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
          189  +  if( cpuCount>1 ){
          190  +    /* defer MT decisions to system malloc */
          191  +    _sqliteZone_ = malloc_default_zone();
          192  +  }else{
          193  +    /* only 1 core, use our own zone to contention over global locks, 
          194  +    ** e.g. we have our own dedicated locks */
          195  +    bool success;		
          196  +    malloc_zone_t* newzone = malloc_create_zone(4096, 0);
          197  +    malloc_set_zone_name(newzone, "Sqlite_Heap");
          198  +    do{
          199  +      success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone, 
          200  +                                 (void * volatile *)&_sqliteZone_);
          201  +    }while(!_sqliteZone_);
          202  +    if( !success ){	
          203  +      /* somebody registered a zone first */
          204  +      malloc_destroy_zone(newzone);
          205  +    }
          206  +  }
          207  +#endif
   150    208     UNUSED_PARAMETER(NotUsed);
   151    209     return SQLITE_OK;
   152    210   }
   153    211   
   154    212   /*
   155    213   ** Deinitialize this module.
   156    214   */