/ Check-in [4651f590]
Login

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

Overview
Comment:Remove the vestigial mem4 and mem6 memory allocators. Add the SQLITE_ZERO_MALLOC compile-time option and the mem0.c module to handle memory allocation for that case. (CVS 5848)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:4651f590f0b8bf13938b2b15d5082136e763af8d
User & Date: drh 2008-10-28 18:58:20
Context
2008-10-29
07:01
If a hot-journal file is detected but the application does not have the required read/write permissions, return SQLITE_CANTOPEN. Prior to this change, SQLITE_BUSY was returned. Ticket #3457. (CVS 5849) check-in: dc5308c7 user: danielk1977 tags: trunk
2008-10-28
18:58
Remove the vestigial mem4 and mem6 memory allocators. Add the SQLITE_ZERO_MALLOC compile-time option and the mem0.c module to handle memory allocation for that case. (CVS 5848) check-in: 4651f590 user: drh tags: trunk
18:12
Add data structure description comments to memjournal.c. (CVS 5847) check-in: e9c2adbc user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.in.

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224
225
226
227
228
229
...
554
555
556
557
558
559
560



561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585

# Object files for the SQLite library (non-amalgamation).
#
OBJS0 = alter.lo analyze.lo attach.lo auth.lo bitvec.lo btmutex.lo \
        btree.lo build.lo callback.lo complete.lo date.lo \
        delete.lo expr.lo fault.lo func.lo global.lo \
        hash.lo journal.lo insert.lo legacy.lo loadext.lo \
        main.lo malloc.lo mem1.lo mem2.lo mem3.lo mem4.lo mem5.lo mem6.lo \
        memjournal.o \
        mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \
        opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
        pager.lo parse.lo pcache.lo pragma.lo prepare.lo printf.lo random.lo \
        resolve.lo select.lo status.lo \
        table.lo tokenize.lo trigger.lo update.lo \
        util.lo vacuum.lo \
................................................................................
  $(TOP)/src/hwtime.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/journal.c \
  $(TOP)/src/legacy.c \
  $(TOP)/src/loadext.c \
  $(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/memjournal.c \
  $(TOP)/src/mutex.c \
  $(TOP)/src/mutex.h \
  $(TOP)/src/mutex_noop.c \
  $(TOP)/src/mutex_os2.c \
  $(TOP)/src/mutex_unix.c \
  $(TOP)/src/mutex_w32.c \
................................................................................

main.lo:	$(TOP)/src/main.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.c

malloc.lo:	$(TOP)/src/malloc.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/malloc.c




mem1.lo:	$(TOP)/src/mem1.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem1.c

mem2.lo:	$(TOP)/src/mem2.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem2.c

mem3.lo:	$(TOP)/src/mem3.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem3.c

mem4.lo:	$(TOP)/src/mem4.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem4.c

mem5.lo:	$(TOP)/src/mem5.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem5.c

mem6.lo:	$(TOP)/src/mem6.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem6.c

memjournal.lo:	$(TOP)/src/memjournal.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/memjournal.c

mutex.lo:	$(TOP)/src/mutex.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex.c

mutex_noop.lo:	$(TOP)/src/mutex_noop.c $(HDR)







|







 







>



<

<







 







>
>
>









<
<
<



<
<
<







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
210
211
212
213
214
215
216
217
218
219
220

221

222
223
224
225
226
227
228
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571



572
573
574



575
576
577
578
579
580
581

# Object files for the SQLite library (non-amalgamation).
#
OBJS0 = alter.lo analyze.lo attach.lo auth.lo bitvec.lo btmutex.lo \
        btree.lo build.lo callback.lo complete.lo date.lo \
        delete.lo expr.lo fault.lo func.lo global.lo \
        hash.lo journal.lo insert.lo legacy.lo loadext.lo \
        main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
        memjournal.o \
        mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \
        opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
        pager.lo parse.lo pcache.lo pragma.lo prepare.lo printf.lo random.lo \
        resolve.lo select.lo status.lo \
        table.lo tokenize.lo trigger.lo update.lo \
        util.lo vacuum.lo \
................................................................................
  $(TOP)/src/hwtime.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/journal.c \
  $(TOP)/src/legacy.c \
  $(TOP)/src/loadext.c \
  $(TOP)/src/main.c \
  $(TOP)/src/malloc.c \
  $(TOP)/src/mem0.c \
  $(TOP)/src/mem1.c \
  $(TOP)/src/mem2.c \
  $(TOP)/src/mem3.c \

  $(TOP)/src/mem5.c \

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

main.lo:	$(TOP)/src/main.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.c

malloc.lo:	$(TOP)/src/malloc.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/malloc.c

mem0.lo:	$(TOP)/src/mem0.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem0.c

mem1.lo:	$(TOP)/src/mem1.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem1.c

mem2.lo:	$(TOP)/src/mem2.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem2.c

mem3.lo:	$(TOP)/src/mem3.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem3.c




mem5.lo:	$(TOP)/src/mem5.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem5.c




memjournal.lo:	$(TOP)/src/memjournal.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/memjournal.c

mutex.lo:	$(TOP)/src/mutex.c $(HDR)
	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex.c

mutex_noop.lo:	$(TOP)/src/mutex_noop.c $(HDR)

Changes to main.mk.

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110
111
112
113
114
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 \
         fts3.o fts3_hash.o fts3_icu.o fts3_porter.o \
         fts3_tokenizer.o fts3_tokenizer1.o \
         func.o global.o hash.o \
         icu.o insert.o journal.o legacy.o loadext.o \
         main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o mem6.o \
         memjournal.o \
         mutex.o mutex_noop.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 pcache.o pragma.o prepare.o printf.o \
         random.o resolve.o rtree.o select.o status.o \
         table.o tokenize.o trigger.o \
         update.o util.o vacuum.o \
................................................................................
  $(TOP)/src/hwtime.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/journal.c \
  $(TOP)/src/legacy.c \
  $(TOP)/src/loadext.c \
  $(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/memjournal.c \
  $(TOP)/src/mutex.c \
  $(TOP)/src/mutex.h \
  $(TOP)/src/mutex_noop.c \
  $(TOP)/src/mutex_os2.c \
  $(TOP)/src/mutex_unix.c \
  $(TOP)/src/mutex_w32.c \







|







 







>



<

<







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
95
96
97
98
99
100
101
102
103
104
105

106

107
108
109
110
111
112
113
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 \
         fts3.o fts3_hash.o fts3_icu.o fts3_porter.o \
         fts3_tokenizer.o fts3_tokenizer1.o \
         func.o global.o hash.o \
         icu.o insert.o journal.o legacy.o loadext.o \
         main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
         memjournal.o \
         mutex.o mutex_noop.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 pcache.o pragma.o prepare.o printf.o \
         random.o resolve.o rtree.o select.o status.o \
         table.o tokenize.o trigger.o \
         update.o util.o vacuum.o \
................................................................................
  $(TOP)/src/hwtime.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/journal.c \
  $(TOP)/src/legacy.c \
  $(TOP)/src/loadext.c \
  $(TOP)/src/main.c \
  $(TOP)/src/malloc.c \
  $(TOP)/src/mem0.c \
  $(TOP)/src/mem1.c \
  $(TOP)/src/mem2.c \
  $(TOP)/src/mem3.c \

  $(TOP)/src/mem5.c \

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

Added src/mem0.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
/*
** 2008 October 28
**
** 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.
**
*************************************************************************
**
** This file contains a no-op memory allocation drivers for use when
** SQLITE_ZERO_MALLOC is defined.  The allocation drivers implemented
** here always fail.  SQLite will not operate with these drivers.  These
** are merely placeholders.  Real drivers must be substituted using
** sqlite3_config() before SQLite will operate.
**
** $Id: mem0.c,v 1.1 2008/10/28 18:58:20 drh 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.
*/
#ifdef SQLITE_ZERO_MALLOC

/*
** No-op versions of all memory allocation routines
*/
static void *sqlite3MemMalloc(int nByte){ return 0; }
static void sqlite3MemFree(void *pPrior){ return; }
static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
static int sqlite3MemSize(void *pPrior){ return 0; }
static int sqlite3MemRoundup(int n){ return n; }
static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
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
** sqlite3GlobalConfig.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_ZERO_MALLOC */

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
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.26 2008/09/01 18:34:20 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;
}

const 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
** sqlite3GlobalConfig.m with pointers to the routines in this file.
*/
void sqlite3MemSetDefault(void){
  sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault());
}

#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
** 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.27 2008/10/28 18:58:20 drh 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
** sqlite3GlobalConfig.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 */

Changes to src/mem2.c.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
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
** 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.39 2008/09/01 18:34:20 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is used only if the
** SQLITE_MEMDEBUG macro is defined
*/
................................................................................
      memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize);
    }
    sqlite3MemFree(pPrior);
  }
  return pNew;
}



const 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
** sqlite3GlobalConfig.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.
*/







|







 







<
>
|
>
>
>










<
<
<
<
<
<
<
<
|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
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
** 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.40 2008/10/28 18:58:20 drh Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is used only if the
** SQLITE_MEMDEBUG macro is defined
*/
................................................................................
      memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize);
    }
    sqlite3MemFree(pPrior);
  }
  return pNew;
}


/*
** Populate the low-level memory allocation function pointers in
** sqlite3GlobalConfig.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.
*/

Deleted src/mem4.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
/*
** 2007 August 14
**
** 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.
**
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.  
**
** $Id: mem4.c,v 1.3 2008/06/18 17:09:10 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator attempts to obtain memory
** from mmap() if the size of the allocation is close to the size
** of a virtual memory page.  If the size of the allocation is different
** from the virtual memory page size, then ordinary malloc() is used.
** Ordinary malloc is also used if space allocated to mmap() is
** exhausted.
**
** Enable this memory allocation by compiling with -DSQLITE_MMAP_HEAP_SIZE=nnn
** where nnn is the maximum number of bytes of mmap-ed memory you want 
** to support.   This module may choose to use less memory than requested.
**
*/
#ifdef SQLITE_MMAP_HEAP_SIZE

/*
** This is a test version of the memory allocator that attempts to
** use mmap() and madvise() for allocations and frees of approximately
** the virtual memory page size.
*/
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <unistd.h>


/*
** All of the static variables used by this module are collected
** into a single structure named "mem".  This is to keep the
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
static struct {
  /*
  ** The alarm callback and its arguments.  The mem.mutex lock will
  ** be held while the callback is running.  Recursive calls into
  ** the memory subsystem are allowed, but no new callbacks will be
  ** issued.  The alarmBusy variable is set to prevent recursive
  ** callbacks.
  */
  sqlite3_int64 alarmThreshold;
  void (*alarmCallback)(void*, sqlite3_int64,int);
  void *alarmArg;
  int alarmBusy;
  
  /*
  ** Mutex to control access to the memory allocation subsystem.
  */
  sqlite3_mutex *mutex;
  
  /*
  ** Current allocation and high-water mark.
  */
  sqlite3_int64 nowUsed;
  sqlite3_int64 mxUsed;

  /*
  ** Current allocation and high-water marks for mmap allocated memory.
  */
  sqlite3_int64 nowUsedMMap;
  sqlite3_int64 mxUsedMMap;

  /*
  ** Size of a single mmap page.  Obtained from sysconf().
  */
  int szPage;
  int mnPage;

  /*
  ** The number of available mmap pages.
  */
  int nPage;

  /*
  ** Index of the first free page.  0 means no pages have been freed.
  */
  int firstFree;

  /* First unused page on the top of the heap.
  */
  int firstUnused;

  /*
  ** Bulk memory obtained from from mmap().
  */
  char *mmapHeap;   /* first byte of the heap */ 

} mem;


/*
** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
** The mmap() region is initialized the first time this routine is called.
*/
static void memsys4Enter(void){
  if( mem.mutex==0 ){
    mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
  }
  sqlite3_mutex_enter(mem.mutex);
}

/*
** Attempt to free memory to the mmap heap.  This only works if
** the pointer p is within the range of memory addresses that
** comprise the mmap heap.  Return 1 if the memory was freed
** successfully.  Return 0 if the pointer is out of range.
*/
static int mmapFree(void *p){
  char *z;
  int idx, *a;
  if( mem.mmapHeap==MAP_FAILED || mem.nPage==0 ){
    return 0;
  }
  z = (char*)p;
  idx = (z - mem.mmapHeap)/mem.szPage;
  if( idx<1 || idx>=mem.nPage ){
    return 0;
  }
  a = (int*)mem.mmapHeap;
  a[idx] = a[mem.firstFree];
  mem.firstFree = idx;
  mem.nowUsedMMap -= mem.szPage;
  madvise(p, mem.szPage, MADV_DONTNEED);
  return 1;
}

/*
** Attempt to allocate nBytes from the mmap heap.  Return a pointer
** to the allocated page.  Or, return NULL if the allocation fails.
** 
** The allocation will fail if nBytes is not the right size.
** Or, the allocation will fail if the mmap heap has been exhausted.
*/
static void *mmapAlloc(int nBytes){
  int idx = 0;
  if( nBytes>mem.szPage || nBytes<mem.mnPage ){
    return 0;
  }
  if( mem.nPage==0 ){
    mem.szPage = sysconf(_SC_PAGE_SIZE);
    mem.mnPage = mem.szPage - mem.szPage/10;
    mem.nPage = SQLITE_MMAP_HEAP_SIZE/mem.szPage;
    if( mem.nPage * sizeof(int) > mem.szPage ){
      mem.nPage = mem.szPage/sizeof(int);
    }
    mem.mmapHeap =  mmap(0, mem.szPage*mem.nPage, PROT_WRITE|PROT_READ,
                         MAP_ANONYMOUS|MAP_SHARED, -1, 0);
    if( mem.mmapHeap==MAP_FAILED ){
      mem.firstUnused = errno;
    }else{
      mem.firstUnused = 1;
      mem.nowUsedMMap = mem.szPage;
    }
  }
  if( mem.mmapHeap==MAP_FAILED ){
    return 0;
  }
  if( mem.firstFree ){
    int idx = mem.firstFree;
    int *a = (int*)mem.mmapHeap;
    mem.firstFree = a[idx];
  }else if( mem.firstUnused<mem.nPage ){
    idx = mem.firstUnused++;
  }
  if( idx ){
    mem.nowUsedMMap += mem.szPage;
    if( mem.nowUsedMMap>mem.mxUsedMMap ){
      mem.mxUsedMMap = mem.nowUsedMMap;
    }
    return (void*)&mem.mmapHeap[idx*mem.szPage];
  }else{
    return 0;
  }
}

/*
** Release the mmap-ed memory region if it is currently allocated and
** is not in use.
*/
static void mmapUnmap(void){
  if( mem.mmapHeap==MAP_FAILED ) return;
  if( mem.nPage==0 ) return;
  if( mem.nowUsedMMap>mem.szPage ) return;
  munmap(mem.mmapHeap, mem.nPage*mem.szPage);
  mem.nowUsedMMap = 0;
  mem.nPage = 0;
}
    

/*
** Return the amount of memory currently checked out.
*/
sqlite3_int64 sqlite3_memory_used(void){
  sqlite3_int64 n;
  memsys4Enter();
  n = mem.nowUsed + mem.nowUsedMMap;
  sqlite3_mutex_leave(mem.mutex);  
  return n;
}

/*
** Return the maximum amount of memory that has ever been
** checked out since either the beginning of this process
** or since the most recent reset.
*/
sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
  sqlite3_int64 n;
  memsys4Enter();
  n = mem.mxUsed + mem.mxUsedMMap;
  if( resetFlag ){
    mem.mxUsed = mem.nowUsed;
    mem.mxUsedMMap = mem.nowUsedMMap;
  }
  sqlite3_mutex_leave(mem.mutex);  
  return n;
}

/*
** Change the alarm callback
*/
int sqlite3_memory_alarm(
  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
  void *pArg,
  sqlite3_int64 iThreshold
){
  memsys4Enter();
  mem.alarmCallback = xCallback;
  mem.alarmArg = pArg;
  mem.alarmThreshold = iThreshold;
  sqlite3_mutex_leave(mem.mutex);
  return SQLITE_OK;
}

/*
** Trigger the alarm 
*/
static void sqlite3MemsysAlarm(int nByte){
  void (*xCallback)(void*,sqlite3_int64,int);
  sqlite3_int64 nowUsed;
  void *pArg;
  if( mem.alarmCallback==0 || mem.alarmBusy  ) return;
  mem.alarmBusy = 1;
  xCallback = mem.alarmCallback;
  nowUsed = mem.nowUsed;
  pArg = mem.alarmArg;
  sqlite3_mutex_leave(mem.mutex);
  xCallback(pArg, nowUsed, nByte);
  sqlite3_mutex_enter(mem.mutex);
  mem.alarmBusy = 0;
}

/*
** Allocate nBytes of memory
*/
static void *memsys4Malloc(int nBytes){
  sqlite3_int64 *p = 0;
  if( mem.alarmCallback!=0
         && mem.nowUsed+mem.nowUsedMMap+nBytes>=mem.alarmThreshold ){
    sqlite3MemsysAlarm(nBytes);
  }
  if( (p = mmapAlloc(nBytes))==0 ){
    p = malloc(nBytes+8);
    if( p==0 ){
      sqlite3MemsysAlarm(nBytes);
      p = malloc(nBytes+8);
    }
    if( p ){
      p[0] = nBytes;
      p++;
      mem.nowUsed += nBytes;
      if( mem.nowUsed>mem.mxUsed ){
        mem.mxUsed = mem.nowUsed;
      }
    }
  }
  return (void*)p; 
}

/*
** Return the size of a memory allocation
*/
static int memsys4Size(void *pPrior){
  char *z = (char*)pPrior;
  int idx = mem.nPage ? (z - mem.mmapHeap)/mem.szPage : 0;
  int nByte;
  if( idx>=1 && idx<mem.nPage ){
    nByte = mem.szPage;
  }else{
    sqlite3_int64 *p = pPrior;
    p--;
    nByte = (int)*p;
  }
  return nByte;
}

/*
** Free memory.
*/
static void memsys4Free(void *pPrior){
  sqlite3_int64 *p;
  int nByte;
  if( mmapFree(pPrior)==0 ){
    p = pPrior;
    p--;
    nByte = (int)*p;
    mem.nowUsed -= nByte;
    free(p);
    if( mem.nowUsed==0 ){
      mmapUnmap();
    }      
  }
}

/*
** Allocate nBytes of memory
*/
void *sqlite3_malloc(int nBytes){
  sqlite3_int64 *p = 0;
  if( nBytes>0 ){
    memsys4Enter();
    p = memsys4Malloc(nBytes);
    sqlite3_mutex_leave(mem.mutex);
  }
  return (void*)p; 
}

/*
** Free memory.
*/
void sqlite3_free(void *pPrior){
  if( pPrior==0 ){
    return;
  }
  assert( mem.mutex!=0 );
  sqlite3_mutex_enter(mem.mutex);
  memsys4Free(pPrior);
  sqlite3_mutex_leave(mem.mutex);  
}



/*
** Change the size of an existing memory allocation
*/
void *sqlite3_realloc(void *pPrior, int nBytes){
  int nOld;
  sqlite3_int64 *p;
  if( pPrior==0 ){
    return sqlite3_malloc(nBytes);
  }
  if( nBytes<=0 ){
    sqlite3_free(pPrior);
    return 0;
  }
  nOld = memsys4Size(pPrior);
  if( nBytes<=nOld && nBytes>=nOld-128 ){
    return pPrior;
  }
  assert( mem.mutex!=0 );
  sqlite3_mutex_enter(mem.mutex);
  p = memsys4Malloc(nBytes);
  if( p ){
    if( nOld<nBytes ){
      memcpy(p, pPrior, nOld);
    }else{
      memcpy(p, pPrior, nBytes);
    }
    memsys4Free(pPrior);
  }
  assert( mem.mutex!=0 );
  sqlite3_mutex_leave(mem.mutex);
  return (void*)p;
}

#endif /* SQLITE_MMAP_HEAP_SIZE */
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















































































































































































































































































































































































































































































































































































































































































































































































































Changes to src/mem5.c.

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
** implementations. Once sqlite3_initialize() has been called,
** the amount of memory available to SQLite is fixed and cannot
** be changed.
**
** This version of the memory allocation subsystem is included
** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
**
** $Id: mem5.c,v 1.14 2008/09/02 17:52:52 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is used only when 
** SQLITE_POW2_MEMORY_SIZE is defined.
*/
#ifdef SQLITE_ENABLE_MEMSYS5

/*
** Log2 of the minimum size of an allocation.  For example, if
** 4 then all allocations will be rounded up to at least 16 bytes.
** If 5 then all allocations will be rounded up to at least 32 bytes.
*/
#ifndef SQLITE_POW2_LOGMIN
# define SQLITE_POW2_LOGMIN 6
#endif

/*
** Log2 of the maximum size of an allocation.
*/
#ifndef SQLITE_POW2_LOGMAX
# define SQLITE_POW2_LOGMAX 20
#endif
#define POW2_MAX (((unsigned int)1)<<SQLITE_POW2_LOGMAX)

/*
** Number of distinct allocation sizes.
*/
#define NSIZE (SQLITE_POW2_LOGMAX - SQLITE_POW2_LOGMIN + 1)

/*
** 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.
*/
typedef struct Mem5Link Mem5Link;
struct Mem5Link {







|





|



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35






















36
37
38
39
40
41
42
** implementations. Once sqlite3_initialize() has been called,
** the amount of memory available to SQLite is fixed and cannot
** be changed.
**
** This version of the memory allocation subsystem is included
** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
**
** $Id: mem5.c,v 1.15 2008/10/28 18:58:20 drh Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is used only when 
** SQLITE_ENABLE_MEMSYS5 is defined.
*/
#ifdef SQLITE_ENABLE_MEMSYS5























/*
** 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.
*/
typedef struct Mem5Link Mem5Link;
struct Mem5Link {

Deleted 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
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
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
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
/*
** 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.
**
*************************************************************************
**
** This file contains an alternative memory allocation system for SQLite.
** This system is implemented as a wrapper around the system provided
** by the operating system - vanilla malloc(), realloc() and free().
**
** This system differentiates between requests for "small" allocations 
** (by default those of 128 bytes or less) and "large" allocations (all
** others). The 256 byte threshhold is configurable at runtime.
**
** All requests for large allocations are passed through to the 
** default system.
**
** Requests for small allocations are met by allocating space within
** one or more larger "chunks" of memory obtained from the default
** memory allocation system. Chunks of memory are usually 64KB or 
** larger. The algorithm used to manage space within each chunk is
** the same as that used by mem5.c. 
**
** This strategy is designed to prevent the default memory allocation
** system (usually the system malloc) from suffering from heap 
** fragmentation. On some systems, heap fragmentation can cause a 
** significant real-time slowdown.
**
** $Id: mem6.c,v 1.10 2008/09/02 17:52:52 danielk1977 Exp $
*/

#ifdef SQLITE_ENABLE_MEMSYS6

#include "sqliteInt.h"

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

/*
** Default value for the "small" allocation size threshold.
*/
#define SMALL_MALLOC_DEFAULT_THRESHOLD 256

/*
** Minimum size for a memory chunk.
*/
#define MIN_CHUNKSIZE (1<<16)

#define LOG2_MINALLOC 4


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]))

static SQLITE_WSD struct Mem6Global {
  int nMinAlloc;                  /* Minimum allowed allocation size */
  int nThreshold;                 /* Allocs larger than this go to malloc() */
  int nLogThreshold;              /* log2 of (nThreshold/nMinAlloc) */
  sqlite3_mutex *mutex;
  Mem6Chunk *pChunk;              /* Singly linked list of all memory chunks */
} mem6 = { 48642791 };

#define mem6 GLOBAL(struct Mem6Global, mem6)

/*
** 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<=mem6.nLogThreshold );
  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<=mem6.nLogThreshold );
  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<=mem6.nLogThreshold );
  i = iFirst = pChunk->aiFreelist[iLogsize];
  assert( iFirst>=0 );
  memsys6Unlink(pChunk, iFirst, iLogsize);
  return iFirst;
}

static int roundupLog2(int n){
  static const char LogTable256[256] = {
    0,                                                    /* 1 */
    1,                                                    /* 2 */
    2, 2,                                                 /* 3..4 */
    3, 3, 3, 3,                                           /* 5..8 */
    4, 4, 4, 4, 4, 4, 4, 4,                               /* 9..16 */
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,       /* 17..32 */
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,       /* 33..64 */
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,       /* 65..128 */
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,       /* 129..256 */
  };

  assert(n<=(1<<16) && n>0);
  if( n<=256 ) return LogTable256[n-1];
  return LogTable256[(n>>8) - ((n&0xFF)?0:1)] + 8;
}

/*
** Allocate and return a block of (pChunk->nAtom << iLogsize) bytes from chunk
** pChunk. If the allocation request cannot be satisfied, return 0.
*/
static void *chunkMalloc(Mem6Chunk *pChunk, int iLogsize){
  int i;           /* Index of a mem5.aPool[] slot */
  int iBin;        /* Index into mem5.aiFreelist[] */

  /* 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<=mem6.nLogThreshold; iBin++){}
  if( iBin>mem6.nLogThreshold ) 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<mem6.nLogThreshold ){
    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<=mem6.nLogThreshold; ii++){
    pChunk->aiFreelist[ii] = -1;
  }

  iOffset = 0;
  for(ii=mem6.nLogThreshold; ii>=0; ii--){
    int nAlloc = (1<<ii);
    while( (iOffset+nAlloc)<=pChunk->nBlock ){
      pChunk->aCtrl[iOffset] = ii | CTRL_FREE;
      memsys6Link(pChunk, iOffset, ii);
      iOffset += nAlloc;
    }
  }

  return pChunk;
}


static void mem6Enter(void){
  sqlite3_mutex_enter(mem6.mutex);
}

static void mem6Leave(void){
  sqlite3_mutex_leave(mem6.mutex);
}

/*
** Based on the number and size of the currently allocated chunks, return
** the size of the next chunk to allocate, in bytes.
*/
static int nextChunkSize(void){
  int iTotal = MIN_CHUNKSIZE;
  Mem6Chunk *p;
  for(p=mem6.pChunk; p; p=p->pNext){
    iTotal = iTotal*2;
  }
  return iTotal;
}

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

static void *memsys6Malloc(int nByte){
  Mem6Chunk *pChunk;
  void *p = 0;
  int nTotal = nByte+8;
  int iOffset = 0;

  if( nTotal>mem6.nThreshold ){
    p = malloc(nTotal);
  }else{
    int iLogsize = 0;
    if( nTotal>(1<<LOG2_MINALLOC) ){
      iLogsize = roundupLog2(nTotal) - LOG2_MINALLOC;
    }
    mem6Enter();
    for(pChunk=mem6.pChunk; pChunk; pChunk=pChunk->pNext){
      p = chunkMalloc(pChunk, iLogsize);
      if( p ){
        break;
      }
    }
    if( !p ){
      int iSize = nextChunkSize();
      p = malloc(iSize);
      if( p ){
        pChunk = chunkInit((u8 *)p, iSize, mem6.nMinAlloc);
        pChunk->pNext = mem6.pChunk;
        mem6.pChunk = pChunk;
        p = chunkMalloc(pChunk, iLogsize);
        assert(p);
      }
    }
    iOffset = ((u8*)p - (u8*)pChunk);
    mem6Leave();
  }

  if( !p ){
    return 0;
  }
  ((u32 *)p)[0] = iOffset;
  ((u32 *)p)[1] = nByte;
  return &((u32 *)p)[2];
}

static int memsys6Size(void *pPrior){
  if( pPrior==0 ) return 0;
  return ((u32*)pPrior)[-1];
}

static void memsys6Free(void *pPrior){
  int iSlot;
  void *p = &((u32 *)pPrior)[-2];
  iSlot = ((u32 *)p)[0];
  if( iSlot ){
    Mem6Chunk *pChunk;
    mem6Enter();
    pChunk = (Mem6Chunk *)(&((u8 *)p)[-1 * iSlot]);
    chunkFree(pChunk, p);
    if( chunkIsEmpty(pChunk) ){
      freeChunk(pChunk);
    }
    mem6Leave();
  }else{
    free(p);
  }
}

static void *memsys6Realloc(void *p, int nByte){
  void *p2;

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

  return p2;
}

static int memsys6Roundup(int n){
  if( n>mem6.nThreshold ){
    return n;
  }else{
    return (1<<roundupLog2(n));
  }
}

static int memsys6Init(void *pCtx){
  u8 bMemstat = sqlite3GlobalConfig.bMemstat;
  mem6.nMinAlloc = (1 << LOG2_MINALLOC);
  mem6.pChunk = 0;
  mem6.nThreshold = sqlite3GlobalConfig.nSmall;
  if( mem6.nThreshold<=0 ){
    mem6.nThreshold = SMALL_MALLOC_DEFAULT_THRESHOLD;
  }
  mem6.nLogThreshold = roundupLog2(mem6.nThreshold) - LOG2_MINALLOC;
  if( !bMemstat ){
    mem6.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
  }
  return SQLITE_OK;
}

static void memsys6Shutdown(void *pCtx){
  memset(&mem6, 0, sizeof(mem6));
}

/*
** 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/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
**    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.786 2008/10/28 17:52:39 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
int sqlite3MallocSize(void*);
int sqlite3DbMallocSize(sqlite3*, void*);
void *sqlite3ScratchMalloc(int);
void sqlite3ScratchFree(void*);
void *sqlite3PageMalloc(int);
void sqlite3PageFree(void*);
void sqlite3MemSetDefault(void);
const 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));
int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*, sqlite3_int64);

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







|







 







<
<

|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
2050
2051
2052
2053
2054
2055
2056


2057
2058
2059
2060
2061
2062
2063
2064
2065
**    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.787 2008/10/28 18:58:20 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

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


const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*, sqlite3_int64);

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

Changes to tool/mksqlite3c.tcl.

207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
222
223
224
225

   global.c
   status.c
   date.c
   os.c

   fault.c

   mem1.c
   mem2.c
   mem3.c
   mem5.c
   mem6.c
   mutex.c
   mutex_noop.c
   mutex_os2.c
   mutex_unix.c
   mutex_w32.c
   malloc.c
   printf.c







>




<







207
208
209
210
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225

   global.c
   status.c
   date.c
   os.c

   fault.c
   mem0.c
   mem1.c
   mem2.c
   mem3.c
   mem5.c

   mutex.c
   mutex_noop.c
   mutex_os2.c
   mutex_unix.c
   mutex_w32.c
   malloc.c
   printf.c