/ Check-in [192bc192]
Login

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

Overview
Comment:Add mem6.c, a new allocator. More to come. (CVS 5467)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 192bc192185a7b475ef9331e2a4a0dc68083ec03
User & Date: danielk1977 2008-07-24 08:20:40
Context
2008-07-24
10:11
Add a mutex to mem6.c to make it threadsafe. (CVS 5468) check-in: 9b97ce60 user: danielk1977 tags: trunk
08:20
Add mem6.c, a new allocator. More to come. (CVS 5467) check-in: 192bc192 user: danielk1977 tags: trunk
2008-07-23
21:07
Error messages from virtual tables store on the sqlite3_vtab->zErrMsg field are reported back up to the application interface and memory is reclaimed. (CVS 5466) check-in: 4a9dd5e7 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.mk.

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
110
111
112
113
114
115
116

117
118
119
120
121
122
123
TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) -I$(TOP)/ext/rtree

# Object files for the SQLite library.
#
LIBOBJ+= alter.o analyze.o attach.o auth.o bitvec.o btmutex.o btree.o build.o \
         callback.o complete.o date.o delete.o \
         expr.o fault.o func.o global.o hash.o insert.o journal.o loadext.o \
         main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o \
         mutex.o mutex_os2.o mutex_unix.o mutex_w32.o \
         opcodes.o os.o os_os2.o os_unix.o os_win.o \
         pager.o parse.o pragma.o prepare.o printf.o random.o \
         select.o status.o table.o $(TCLOBJ) tokenize.o trigger.o \
         update.o util.o vacuum.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \
         where.o utf.o legacy.o vtab.o rtree.o
................................................................................
  $(TOP)/src/main.c \
  $(TOP)/src/malloc.c \
  $(TOP)/src/mem1.c \
  $(TOP)/src/mem2.c \
  $(TOP)/src/mem3.c \
  $(TOP)/src/mem4.c \
  $(TOP)/src/mem5.c \

  $(TOP)/src/mutex.c \
  $(TOP)/src/mutex.h \
  $(TOP)/src/mutex_os2.c \
  $(TOP)/src/mutex_unix.c \
  $(TOP)/src/mutex_w32.c \
  $(TOP)/src/os.c \
  $(TOP)/src/os.h \







|







 







>







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) -I$(TOP)/ext/rtree

# Object files for the SQLite library.
#
LIBOBJ+= alter.o analyze.o attach.o auth.o bitvec.o btmutex.o btree.o build.o \
         callback.o complete.o date.o delete.o \
         expr.o fault.o func.o global.o hash.o insert.o journal.o loadext.o \
         main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o mem6.o \
         mutex.o mutex_os2.o mutex_unix.o mutex_w32.o \
         opcodes.o os.o os_os2.o os_unix.o os_win.o \
         pager.o parse.o pragma.o prepare.o printf.o random.o \
         select.o status.o table.o $(TCLOBJ) tokenize.o trigger.o \
         update.o util.o vacuum.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \
         where.o utf.o legacy.o vtab.o rtree.o
................................................................................
  $(TOP)/src/main.c \
  $(TOP)/src/malloc.c \
  $(TOP)/src/mem1.c \
  $(TOP)/src/mem2.c \
  $(TOP)/src/mem3.c \
  $(TOP)/src/mem4.c \
  $(TOP)/src/mem5.c \
  $(TOP)/src/mem6.c \
  $(TOP)/src/mutex.c \
  $(TOP)/src/mutex.h \
  $(TOP)/src/mutex_os2.c \
  $(TOP)/src/mutex_unix.c \
  $(TOP)/src/mutex_w32.c \
  $(TOP)/src/os.c \
  $(TOP)/src/os.h \

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
262
263
264
265
266
267
268







269
270
271
272
273
274
275
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.480 2008/07/22 05:13:30 shane Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif
................................................................................
#ifdef SQLITE_ENABLE_MEMSYS5
        sqlite3Config.m = *sqlite3MemGetMemsys5();
#endif
      }
      break;
    }
#endif








    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);







|







 







>
>
>
>
>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.481 2008/07/24 08:20:40 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif
................................................................................
#ifdef SQLITE_ENABLE_MEMSYS5
        sqlite3Config.m = *sqlite3MemGetMemsys5();
#endif
      }
      break;
    }
#endif

#if defined(SQLITE_ENABLE_MEMSYS6)
    case SQLITE_CONFIG_CHUNKALLOC: {
      sqlite3Config.m = *sqlite3MemGetMemsys6();
      break;
    }
#endif

    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);

Changes to src/mem1.c.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...
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
** This file contains low-level memory allocation drivers for when
** SQLite will use the standard C-library malloc/realloc/free interface
** to obtain the memory it needs.
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
** $Id: mem1.c,v 1.23 2008/06/23 15:10:25 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is the default.  It is
** used when no other memory allocator is specified using compile-time
** macros.
................................................................................
/*
** Deinitialize this module.
*/
static void sqlite3MemShutdown(void *NotUsed){
  return;
}

/*
** This routine is the only routine in this file with external linkage.
**
** Populate the low-level memory allocation function pointers in
** sqlite3Config.m with pointers to the routines in this file.
*/
void sqlite3MemSetDefault(void){
  static const sqlite3_mem_methods defaultMethods = {
     sqlite3MemMalloc,
     sqlite3MemFree,
     sqlite3MemRealloc,
     sqlite3MemSize,
     sqlite3MemRoundup,
     sqlite3MemInit,
     sqlite3MemShutdown,
     0
  };










  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
}

#endif /* SQLITE_SYSTEM_MALLOC */







|







 







|
<
<
<
<
<
<










>
>
>
>
>
>
>
>
>
>
|



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...
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
** This file contains low-level memory allocation drivers for when
** SQLite will use the standard C-library malloc/realloc/free interface
** to obtain the memory it needs.
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
** $Id: mem1.c,v 1.24 2008/07/24 08:20:40 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is the default.  It is
** used when no other memory allocator is specified using compile-time
** macros.
................................................................................
/*
** Deinitialize this module.
*/
static void sqlite3MemShutdown(void *NotUsed){
  return;
}

sqlite3_mem_methods *sqlite3MemGetDefault(void){






  static const sqlite3_mem_methods defaultMethods = {
     sqlite3MemMalloc,
     sqlite3MemFree,
     sqlite3MemRealloc,
     sqlite3MemSize,
     sqlite3MemRoundup,
     sqlite3MemInit,
     sqlite3MemShutdown,
     0
  };
  return &defaultMethods;
}

/*
** This routine is the only routine in this file with external linkage.
**
** Populate the low-level memory allocation function pointers in
** sqlite3Config.m with pointers to the routines in this file.
*/
void sqlite3MemSetDefault(void){
  sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault());
}

#endif /* SQLITE_SYSTEM_MALLOC */

Changes to src/mem2.c.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321








322
323
324
325
326
327
328
329
** to obtain the memory it needs while adding lots of additional debugging
** information to each allocation in order to help detect and fix memory
** leaks and memory usage errors.
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
** $Id: mem2.c,v 1.34 2008/07/10 18:13:42 drh Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is used only if the
** SQLITE_MEMDEBUG macro is defined
*/
................................................................................
    }
    sqlite3MemFree(pPrior);
  }
  return pNew;
}


/*
** Populate the low-level memory allocation function pointers in
** sqlite3Config.m with pointers to the routines in this file.
*/
void sqlite3MemSetDefault(void){
  static const sqlite3_mem_methods defaultMethods = {
     sqlite3MemMalloc,
     sqlite3MemFree,
     sqlite3MemRealloc,
     sqlite3MemSize,
     sqlite3MemRoundup,
     sqlite3MemInit,
     sqlite3MemShutdown,
     0
  };








  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
}

/*
** Set the number of backtrace levels kept for each allocation.
** A value of zero turns off backtracing.  The number is always rounded
** up to a multiple of 2.
*/







|







 







|
<
<
<
<










>
>
>
>
>
>
>
>
|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
300
301
302
303
304
305
306
307




308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
** to obtain the memory it needs while adding lots of additional debugging
** information to each allocation in order to help detect and fix memory
** leaks and memory usage errors.
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
** $Id: mem2.c,v 1.35 2008/07/24 08:20:40 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is used only if the
** SQLITE_MEMDEBUG macro is defined
*/
................................................................................
    }
    sqlite3MemFree(pPrior);
  }
  return pNew;
}


sqlite3_mem_methods *sqlite3MemGetDefault(void){




  static const sqlite3_mem_methods defaultMethods = {
     sqlite3MemMalloc,
     sqlite3MemFree,
     sqlite3MemRealloc,
     sqlite3MemSize,
     sqlite3MemRoundup,
     sqlite3MemInit,
     sqlite3MemShutdown,
     0
  };
  return &defaultMethods;
}

/*
** Populate the low-level memory allocation function pointers in
** sqlite3Config.m with pointers to the routines in this file.
*/
void sqlite3MemSetDefault(void){
  sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault());
}

/*
** Set the number of backtrace levels kept for each allocation.
** A value of zero turns off backtracing.  The number is always rounded
** up to a multiple of 2.
*/

Added src/mem6.c.





















































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/*
** 2008 July 24
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** $Id: mem6.c,v 1.1 2008/07/24 08:20:40 danielk1977 Exp $
*/

#ifdef SQLITE_ENABLE_MEMSYS6

/*
** Maximum size of any allocation is ((1<<LOGMAX)*Mem6Chunk.nAtom). Since
** Mem6Chunk.nAtom is always at least 8, this is not really a practical
** limitation.
*/
#define LOGMAX 30

#include "sqliteInt.h"

typedef struct Mem6Chunk Mem6Chunk;
typedef struct Mem6Link Mem6Link;

/*
** A minimum allocation is an instance of the following structure.
** Larger allocations are an array of these structures where the
** size of the array is a power of 2.
*/
struct Mem6Link {
  int next;       /* Index of next free chunk */
  int prev;       /* Index of previous free chunk */
};

/*
** Masks used for mem5.aCtrl[] elements.
*/
#define CTRL_LOGSIZE  0x1f    /* Log2 Size of this block relative to POW2_MIN */
#define CTRL_FREE     0x20    /* True if not checked out */

struct Mem6Chunk {
  Mem6Chunk *pNext;

  /*
  ** Lists of free blocks of various sizes.
  */
  int aiFreelist[LOGMAX+1];

  int nCheckedOut; /* Number of currently outstanding allocations */

  /*
  ** Space for tracking which blocks are checked out and the size
  ** of each block. One byte per block.
  */
  u8 *aCtrl;

  /*
  ** Memory available for allocation
  */
  int nAtom;       /* Smallest possible allocation in bytes */
  int nBlock;      /* Number of nAtom sized blocks in zPool */
  u8 *zPool;       /* Pointer to memory chunk from which allocations are made */
};

#define MEM6LINK(idx) ((Mem6Link *)(&pChunk->zPool[(idx)*pChunk->nAtom]))

/*
** Unlink the chunk at pChunk->aPool[i] from list it is currently
** on.  It should be found on pChunk->aiFreelist[iLogsize].
*/
static void memsys6Unlink(Mem6Chunk *pChunk, int i, int iLogsize){
  int next, prev;
  assert( i>=0 && i<pChunk->nBlock );
  assert( iLogsize>=0 && iLogsize<=LOGMAX );
  assert( (pChunk->aCtrl[i] & CTRL_LOGSIZE)==iLogsize );

  next = MEM6LINK(i)->next;
  prev = MEM6LINK(i)->prev;
  if( prev<0 ){
    pChunk->aiFreelist[iLogsize] = next;
  }else{
    MEM6LINK(prev)->next = next;
  }
  if( next>=0 ){
    MEM6LINK(next)->prev = prev;
  }
}

/*
** Link the chunk at mem5.aPool[i] so that is on the iLogsize
** free list.
*/
static void memsys6Link(Mem6Chunk *pChunk, int i, int iLogsize){
  int x;
  assert( i>=0 && i<pChunk->nBlock );
  assert( iLogsize>=0 && iLogsize<=LOGMAX );
  assert( (pChunk->aCtrl[i] & CTRL_LOGSIZE)==iLogsize );

  x = MEM6LINK(i)->next = pChunk->aiFreelist[iLogsize];
  MEM6LINK(i)->prev = -1;
  if( x>=0 ){
    assert( x<pChunk->nBlock );
    MEM6LINK(x)->prev = i;
  }
  pChunk->aiFreelist[iLogsize] = i;
}


/*
** Find the first entry on the freelist iLogsize.  Unlink that
** entry and return its index. 
*/
static int memsys6UnlinkFirst(Mem6Chunk *pChunk, int iLogsize){
  int i;
  int iFirst;

  assert( iLogsize>=0 && iLogsize<=LOGMAX );
  i = iFirst = pChunk->aiFreelist[iLogsize];
  assert( iFirst>=0 );
  while( i>0 ){
    if( i<iFirst ) iFirst = i;
    i = MEM6LINK(i)->next;
  }
  memsys6Unlink(pChunk, iFirst, iLogsize);
  return iFirst;
}

/*
** Allocate and return a block of nByte bytes from chunk pChunk. If the
** allocation request cannot be satisfied, return 0.
*/
static void *chunkMalloc(Mem6Chunk *pChunk, int nByte){
  int i;           /* Index of a mem5.aPool[] slot */
  int iBin;        /* Index into mem5.aiFreelist[] */
  int iFullSz;     /* Size of allocation rounded up to power of 2 */
  int iLogsize;    /* Log2 of iFullSz/POW2_MIN */

  /* Round nByte up to the next valid power of two */
  if( nByte>(pChunk->nBlock*pChunk->nAtom) ) return 0;
  for(iFullSz=pChunk->nAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}

  /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
  ** block.  If not, then split a block of the next larger power of
  ** two in order to create a new free block of size iLogsize.
  */
  for(iBin=iLogsize; pChunk->aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
  if( iBin>LOGMAX ) return 0;
  i = memsys6UnlinkFirst(pChunk, iBin);
  while( iBin>iLogsize ){
    int newSize;

    iBin--;
    newSize = 1 << iBin;
    pChunk->aCtrl[i+newSize] = CTRL_FREE | iBin;
    memsys6Link(pChunk, i+newSize, iBin);
  }
  pChunk->aCtrl[i] = iLogsize;

  /* Return a pointer to the allocated memory. */
  pChunk->nCheckedOut++;
  return (void*)&pChunk->zPool[i*pChunk->nAtom];
}

/*
** Free the allocation pointed to by p, which is guaranteed to be non-zero
** and a part of chunk object pChunk.
*/
static void chunkFree(Mem6Chunk *pChunk, void *pOld){
  u32 size, iLogsize;
  int iBlock;             

  /* Set iBlock to the index of the block pointed to by pOld in 
  ** the array of pChunk->nAtom byte blocks pointed to by pChunk->zPool.
  */
  iBlock = ((u8 *)pOld-pChunk->zPool)/pChunk->nAtom;

  /* Check that the pointer pOld points to a valid, non-free block. */
  assert( iBlock>=0 && iBlock<pChunk->nBlock );
  assert( ((u8 *)pOld-pChunk->zPool)%pChunk->nAtom==0 );
  assert( (pChunk->aCtrl[iBlock] & CTRL_FREE)==0 );

  iLogsize = pChunk->aCtrl[iBlock] & CTRL_LOGSIZE;
  size = 1<<iLogsize;
  assert( iBlock+size-1<pChunk->nBlock );

  pChunk->aCtrl[iBlock] |= CTRL_FREE;
  pChunk->aCtrl[iBlock+size-1] |= CTRL_FREE;

  pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize;
  while( iLogsize<LOGMAX ){
    int iBuddy;
    if( (iBlock>>iLogsize) & 1 ){
      iBuddy = iBlock - size;
    }else{
      iBuddy = iBlock + size;
    }
    assert( iBuddy>=0 );
    if( (iBuddy+(1<<iLogsize))>pChunk->nBlock ) break;
    if( pChunk->aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
    memsys6Unlink(pChunk, iBuddy, iLogsize);
    iLogsize++;
    if( iBuddy<iBlock ){
      pChunk->aCtrl[iBuddy] = CTRL_FREE | iLogsize;
      pChunk->aCtrl[iBlock] = 0;
      iBlock = iBuddy;
    }else{
      pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize;
      pChunk->aCtrl[iBuddy] = 0;
    }
    size *= 2;
  }
  pChunk->nCheckedOut--;
  memsys6Link(pChunk, iBlock, iLogsize);
}

/*
** Return the actual size of the block pointed to by p, which is guaranteed
** to have been allocated from chunk pChunk.
*/
static int chunkSize(Mem6Chunk *pChunk, void *p){
  int iSize = 0;
  if( p ){
    int i = ((u8 *)p-pChunk->zPool)/pChunk->nAtom;
    assert( i>=0 && i<pChunk->nBlock );
    iSize = pChunk->nAtom * (1 << (pChunk->aCtrl[i]&CTRL_LOGSIZE));
  }
  return iSize;
}

/*
** Return true if there are currently no outstanding allocations.
*/
static int chunkIsEmpty(Mem6Chunk *pChunk){
  return (pChunk->nCheckedOut==0);
}

/*
** Initialize the buffer zChunk, which is nChunk bytes in size, as
** an Mem6Chunk object. Return a copy of the zChunk pointer.
*/
static Mem6Chunk *chunkInit(u8 *zChunk, int nChunk, int nMinAlloc){
  int ii;
  int iOffset;
  Mem6Chunk *pChunk = (Mem6Chunk *)zChunk;

  assert( nChunk>sizeof(Mem6Chunk) );
  assert( nMinAlloc>sizeof(Mem6Link) );

  memset(pChunk, 0, sizeof(Mem6Chunk));
  pChunk->nAtom = nMinAlloc;
  pChunk->nBlock = ((nChunk-sizeof(Mem6Chunk)) / (pChunk->nAtom+sizeof(u8)));

  pChunk->zPool = (u8 *)&pChunk[1];
  pChunk->aCtrl = &pChunk->zPool[pChunk->nBlock*pChunk->nAtom];

  for(ii=0; ii<=LOGMAX; ii++){
    pChunk->aiFreelist[ii] = -1;
  }

  iOffset = 0;
  for(ii=LOGMAX; ii>=0; ii--){
    int nAlloc = (1<<ii);
    if( (iOffset+nAlloc)<=pChunk->nBlock ){
      pChunk->aCtrl[iOffset] = ii | CTRL_FREE;
      memsys6Link(pChunk, iOffset, ii);
      iOffset += nAlloc;
    }
    assert((iOffset+nAlloc)>pChunk->nBlock);
  }

  return pChunk;
}

struct Mem6Global {
  sqlite3_mem_methods parent;     /* Used to allocate chunks */
  int nChunkSize;                 /* Size of each chunk, in bytes. */
  int nMinAlloc;                  /* Minimum allowed allocation size */

  /* This data structure will be fixed... */
  Mem6Chunk *pChunk;              /* Singly linked list of all memory chunks */
} mem6;

/*
** The argument is a pointer that may or may not have been allocated from
** one of the Mem6Chunk objects managed within mem6. If it is, return
** a pointer to the owner chunk. If not, return 0.
*/
static Mem6Chunk *findChunk(u8 *p){
  Mem6Chunk *pChunk;
  for(pChunk=mem6.pChunk; pChunk; pChunk=pChunk->pNext){
    if( p>=pChunk->zPool && p<=&pChunk->zPool[pChunk->nBlock*pChunk->nAtom] ){
      return pChunk;
    }
  }
  return 0;
}

static void freeChunk(Mem6Chunk *pChunk){
  Mem6Chunk **pp = &mem6.pChunk;
  for( pp=&mem6.pChunk; *pp!=pChunk; pp = &(*pp)->pNext );
  *pp = (*pp)->pNext;
  mem6.parent.xFree(pChunk);
}

static void *memsys6Malloc(int nByte){
  Mem6Chunk *pChunk;
  void *p;
  if( nByte>=mem6.nChunkSize/3 ){
    return mem6.parent.xMalloc(nByte);
  }
  for(pChunk=mem6.pChunk; pChunk; pChunk=pChunk->pNext){
    p = chunkMalloc(pChunk, nByte);
    if( p ){
      return p;
    }
  }

  p = mem6.parent.xMalloc(mem6.nChunkSize);
  if( p ){
    pChunk = chunkInit((u8 *)p, mem6.nChunkSize, mem6.nMinAlloc);
    pChunk->pNext = mem6.pChunk;
    mem6.pChunk = pChunk;
    p = chunkMalloc(pChunk, nByte);
    assert(p);
  }

  return p;
}

static int memsys6Size(void *p){
  Mem6Chunk *pChunk = findChunk(p);
  return (pChunk ? chunkSize(pChunk, p) : mem6.parent.xSize(p));
}

static void memsys6Free(void *p){
  Mem6Chunk *pChunk = findChunk(p);
  if( pChunk ){
    chunkFree(pChunk, p);
    if( chunkIsEmpty(pChunk) ){
      freeChunk(pChunk);
    }
  }else{
    mem6.parent.xFree(p);
  }
}

static void *memsys6Realloc(void *p, int nByte){
  Mem6Chunk *pChunk = findChunk(p);
  void *p2;

  if( !pChunk ){
    return mem6.parent.xRealloc(p, nByte);
  }

  p2 = memsys6Malloc(nByte);
  if( p2 ){
    assert( memsys6Size(p)<nByte );
    memcpy(p2, p, memsys6Size(p));
    memsys6Free(p);
  }
  return p2;
}


static int memsys6Roundup(int n){
  int iFullSz;
  for(iFullSz=mem6.nMinAlloc; iFullSz<n; iFullSz *= 2);
  return iFullSz;
}

static int memsys6Init(void *pCtx){
  mem6.parent = *sqlite3MemGetDefault();
  mem6.nChunkSize = (1<<16);
  mem6.nMinAlloc = 16;
  mem6.pChunk = 0;

  /* Initialize the parent allocator. */
  mem6.parent.xInit(mem6.parent.pAppData);

  return SQLITE_OK;
}

static void memsys6Shutdown(void *pCtx){
}

/*
** This routine is the only routine in this file with external 
** linkage. It returns a pointer to a static sqlite3_mem_methods
** struct populated with the memsys6 methods.
*/
const sqlite3_mem_methods *sqlite3MemGetMemsys6(void){
  static const sqlite3_mem_methods memsys6Methods = {
     memsys6Malloc,
     memsys6Free,
     memsys6Realloc,
     memsys6Size,
     memsys6Roundup,
     memsys6Init,
     memsys6Shutdown,
     0
  };
  return &memsys6Methods;
}

#endif

Changes to src/sqlite.h.in.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
1153
1154
1155
1156
1157
1158
1159


1160
1161
1162
1163
1164
1165
1166
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.377 2008/07/23 18:25:56 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
#define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_SCRATCH       6  /* void*, int sz, int N */
#define SQLITE_CONFIG_PAGECACHE     7  /* void*, int sz, int N */
#define SQLITE_CONFIG_HEAP          8  /* void*, int nByte, int min */
#define SQLITE_CONFIG_MEMSTATUS     9  /* boolean */
#define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */




/*
** CAPI3REF: Enable Or Disable Extended Result Codes {H12200} <S10700>
**
** The sqlite3_extended_result_codes() routine enables or disables the
** [extended result codes] feature of SQLite. The extended result







|







 







>
>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.378 2008/07/24 08:20:40 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
#define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_SCRATCH       6  /* void*, int sz, int N */
#define SQLITE_CONFIG_PAGECACHE     7  /* void*, int sz, int N */
#define SQLITE_CONFIG_HEAP          8  /* void*, int nByte, int min */
#define SQLITE_CONFIG_MEMSTATUS     9  /* boolean */
#define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */

#define SQLITE_CONFIG_CHUNKALLOC   12  /* nil */


/*
** CAPI3REF: Enable Or Disable Extended Result Codes {H12200} <S10700>
**
** The sqlite3_extended_result_codes() routine enables or disables the
** [extended result codes] feature of SQLite. The extended result

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1837
1838
1839
1840
1841
1842
1843

1844
1845

1846
1847
1848
1849
1850
1851
1852
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.743 2008/07/23 18:17:32 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
void *sqlite3DbRealloc(sqlite3 *, void *, int);
int sqlite3MallocSize(void *);
void *sqlite3ScratchMalloc(int);
void sqlite3ScratchFree(void*);
void *sqlite3PageMalloc(int);
void sqlite3PageFree(void*);
void sqlite3MemSetDefault(void);

const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);

void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));

#ifndef SQLITE_MUTEX_NOOP
  sqlite3_mutex_methods *sqlite3DefaultMutex(void);
  sqlite3_mutex *sqlite3MutexAlloc(int);
  int sqlite3MutexInit(void);
  int sqlite3MutexEnd(void);







|







 







>


>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.744 2008/07/24 08:20:40 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
void *sqlite3DbRealloc(sqlite3 *, void *, int);
int sqlite3MallocSize(void *);
void *sqlite3ScratchMalloc(int);
void sqlite3ScratchFree(void*);
void *sqlite3PageMalloc(int);
void sqlite3PageFree(void*);
void sqlite3MemSetDefault(void);
sqlite3_mem_methods *sqlite3MemGetDefault(void);
const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
const sqlite3_mem_methods *sqlite3MemGetMemsys6(void);
void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));

#ifndef SQLITE_MUTEX_NOOP
  sqlite3_mutex_methods *sqlite3DefaultMutex(void);
  sqlite3_mutex *sqlite3MutexAlloc(int);
  int sqlite3MutexInit(void);
  int sqlite3MutexEnd(void);

Changes to src/test_malloc.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
951
952
953
954
955
956
957




















958
959
960
961
962
963
964
....
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
** $Id: test_malloc.c,v 1.38 2008/07/16 12:25:32 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

................................................................................
    return TCL_ERROR;
  }
  if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR;
  rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return TCL_OK;
}





















/*
** Usage:
**
**   sqlite3_config_heap NBYTE NMINALLOC
*/
static int test_config_heap(
................................................................................
     { "sqlite3_memdebug_log",       test_memdebug_log             ,0 },
     { "sqlite3_config_scratch",     test_config_scratch           ,0 },
     { "sqlite3_config_pagecache",   test_config_pagecache         ,0 },
     { "sqlite3_status",             test_status                   ,0 },
     { "install_malloc_faultsim",    test_install_malloc_faultsim  ,0 },
     { "sqlite3_config_heap",        test_config_heap              ,0 },
     { "sqlite3_config_memstatus",   test_config_memstatus         ,0 },

     { "sqlite3_dump_memsys3",       test_dump_memsys3             ,3 },
     { "sqlite3_dump_memsys5",       test_dump_memsys3             ,5 }
  };
  int i;
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    ClientData c = (ClientData)aObjCmd[i].clientData;
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0);
  }
  return TCL_OK;
}
#endif







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>











9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
....
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
** $Id: test_malloc.c,v 1.39 2008/07/24 08:20:40 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

................................................................................
    return TCL_ERROR;
  }
  if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR;
  rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return TCL_OK;
}

/*
** Usage:    sqlite3_config_chunkalloc 
**
*/
static int test_config_chunkalloc(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc;
  if( objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }
  rc = sqlite3_config(SQLITE_CONFIG_CHUNKALLOC);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
  return TCL_OK;
}

/*
** Usage:
**
**   sqlite3_config_heap NBYTE NMINALLOC
*/
static int test_config_heap(
................................................................................
     { "sqlite3_memdebug_log",       test_memdebug_log             ,0 },
     { "sqlite3_config_scratch",     test_config_scratch           ,0 },
     { "sqlite3_config_pagecache",   test_config_pagecache         ,0 },
     { "sqlite3_status",             test_status                   ,0 },
     { "install_malloc_faultsim",    test_install_malloc_faultsim  ,0 },
     { "sqlite3_config_heap",        test_config_heap              ,0 },
     { "sqlite3_config_memstatus",   test_config_memstatus         ,0 },
     { "sqlite3_config_chunkalloc",  test_config_chunkalloc        ,0 },
     { "sqlite3_dump_memsys3",       test_dump_memsys3             ,3 },
     { "sqlite3_dump_memsys5",       test_dump_memsys3             ,5 }
  };
  int i;
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    ClientData c = (ClientData)aObjCmd[i].clientData;
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0);
  }
  return TCL_OK;
}
#endif

Changes to test/permutations.test.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
434
435
436
437
438
439
440





















441
442
443
444
445
446
447
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# $Id: permutations.test,v 1.13 2008/07/16 12:25:32 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Argument processing.
#
set ::testmode [lindex $argv 0]
................................................................................
    set ::disable_mutex_try 1
  } -shutdown {
    catch {db close}
    sqlite3_shutdown
    install_mutex_counters 0
  }
}






















# run_tests "crash_safe_append" -description {
#   Run crash.test with persistent journals on a SAFE_APPEND file-system.
# } -initialize {
#   rename crashsql sa_crashsql
#   proc crashsql {args} {
#     set options [lrange $args 0 [expr {[llength $args]-2}]]







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# $Id: permutations.test,v 1.14 2008/07/24 08:20:40 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Argument processing.
#
set ::testmode [lindex $argv 0]
................................................................................
    set ::disable_mutex_try 1
  } -shutdown {
    catch {db close}
    sqlite3_shutdown
    install_mutex_counters 0
  }
}

  run_tests "memsys6" -description {
    Run tests using the allocator in mem6.c.
  } -include {
    select1.test 
  } -initialize {
    catch {db close}
    sqlite3_reset_auto_extension
    sqlite3_shutdown
    sqlite3_config_chunkalloc
    install_malloc_faultsim 1 
    sqlite3_initialize
    autoinstall_test_functions
  } -shutdown {
    catch {db close}
    sqlite3_reset_auto_extension
    sqlite3_shutdown
    sqlite3_config_heap 0 0
    install_malloc_faultsim 1 
    sqlite3_initialize
  }

# run_tests "crash_safe_append" -description {
#   Run crash.test with persistent journals on a SAFE_APPEND file-system.
# } -initialize {
#   rename crashsql sa_crashsql
#   proc crashsql {args} {
#     set options [lrange $args 0 [expr {[llength $args]-2}]]