SQLite

Check-in [5059644c4b]
Login

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

Overview
Comment:Implement the 'CONFIG_SINGLETHREAD' and 'CONFIG_MULTITHREAD' configuration modes. (CVS 5234)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5059644c4bc5f6679afd939e0bc26080f42a9918
User & Date: danielk1977 2008-06-18 17:09:10.000
Context
2008-06-18
17:59
Fix a test case in mutex1.test that was failing when sqlite was compiled with SQLITE_THREADSAFE=0. (CVS 5235) (check-in: d1a87c3bcc user: danielk1977 tags: trunk)
17:09
Implement the 'CONFIG_SINGLETHREAD' and 'CONFIG_MULTITHREAD' configuration modes. (CVS 5234) (check-in: 5059644c4b user: danielk1977 tags: trunk)
15:34
Make sure aggregate functions can take any number of arguments up to the limit imposed by SQLITE_LIMIT_FUNCTION_ARGS. Ticket #3179. Modify the group_concat() function to take an unlimited number of arguments in order to facilitate testing this behavior. (CVS 5233) (check-in: 70c6739f4e user: drh tags: trunk)
Changes
Unified Diff Show Whitespace Changes Patch
Changes to src/btree.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2004 April 6
**
** 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: btree.c,v 1.465 2008/06/17 15:12:01 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
#include "btreeInt.h"












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2004 April 6
**
** 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: btree.c,v 1.466 2008/06/18 17:09:10 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
#include "btreeInt.h"

1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
        db->flags |= SQLITE_SharedCache;
      }
      if( !zFullPathname ){
        sqlite3_free(p);
        return SQLITE_NOMEM;
      }
      sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);
      mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
      sqlite3_mutex_enter(mutexShared);
      for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
        assert( pBt->nRef>0 );
        if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
                 && sqlite3PagerVfs(pBt->pPager)==pVfs ){
          p->pBt = pBt;
          pBt->nRef++;







|







1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
        db->flags |= SQLITE_SharedCache;
      }
      if( !zFullPathname ){
        sqlite3_free(p);
        return SQLITE_NOMEM;
      }
      sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);
      mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
      sqlite3_mutex_enter(mutexShared);
      for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
        assert( pBt->nRef>0 );
        if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
                 && sqlite3PagerVfs(pBt->pPager)==pVfs ){
          p->pBt = pBt;
          pBt->nRef++;
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
   
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
    /* Add the new BtShared object to the linked list sharable BtShareds.
    */
    if( p->sharable ){
      sqlite3_mutex *mutexShared;
      pBt->nRef = 1;
      mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
      if( SQLITE_THREADSAFE ){
        pBt->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
        if( pBt->mutex==0 ){
          rc = SQLITE_NOMEM;
          db->mallocFailed = 0;
          goto btree_open_out;
        }
      }
      sqlite3_mutex_enter(mutexShared);







|
|
|







1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
   
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
    /* Add the new BtShared object to the linked list sharable BtShareds.
    */
    if( p->sharable ){
      sqlite3_mutex *mutexShared;
      pBt->nRef = 1;
      mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
      if( SQLITE_THREADSAFE && sqlite3Config.bCoreMutex ){
        pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
        if( pBt->mutex==0 ){
          rc = SQLITE_NOMEM;
          db->mallocFailed = 0;
          goto btree_open_out;
        }
      }
      sqlite3_mutex_enter(mutexShared);
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
static int removeFromSharingList(BtShared *pBt){
#ifndef SQLITE_OMIT_SHARED_CACHE
  sqlite3_mutex *pMaster;
  BtShared *pList;
  int removed = 0;

  assert( sqlite3_mutex_notheld(pBt->mutex) );
  pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
  sqlite3_mutex_enter(pMaster);
  pBt->nRef--;
  if( pBt->nRef<=0 ){
    if( sqlite3SharedCacheList==pBt ){
      sqlite3SharedCacheList = pBt->pNext;
    }else{
      pList = sqlite3SharedCacheList;







|







1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
static int removeFromSharingList(BtShared *pBt){
#ifndef SQLITE_OMIT_SHARED_CACHE
  sqlite3_mutex *pMaster;
  BtShared *pList;
  int removed = 0;

  assert( sqlite3_mutex_notheld(pBt->mutex) );
  pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
  sqlite3_mutex_enter(pMaster);
  pBt->nRef--;
  if( pBt->nRef<=0 ){
    if( sqlite3SharedCacheList==pBt ){
      sqlite3SharedCacheList = pBt->pNext;
    }else{
      pList = sqlite3SharedCacheList;
Changes to src/date.c.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This file contains the C functions that implement date and time
** functions for SQLite.  
**
** There is only one exported symbol in this file - the function
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: date.c,v 1.84 2008/06/15 02:51:47 drh Exp $
**
** SQLite processes all times and dates as Julian Day numbers.  The
** dates and times are stored as the number of days since noon
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
** calendar system. 
**
** 1970-01-01 00:00:00 is JD 2440587.5







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This file contains the C functions that implement date and time
** functions for SQLite.  
**
** There is only one exported symbol in this file - the function
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: date.c,v 1.85 2008/06/18 17:09:10 danielk1977 Exp $
**
** SQLite processes all times and dates as Julian Day numbers.  The
** dates and times are stored as the number of days since noon
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
** calendar system. 
**
** 1970-01-01 00:00:00 is JD 2440587.5
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
    y.h = sLocal.tm_hour;
    y.m = sLocal.tm_min;
    y.s = sLocal.tm_sec;
  }
#else
  {
    struct tm *pTm;
    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
    pTm = localtime(&t);
    y.Y = pTm->tm_year + 1900;
    y.M = pTm->tm_mon + 1;
    y.D = pTm->tm_mday;
    y.h = pTm->tm_hour;
    y.m = pTm->tm_min;
    y.s = pTm->tm_sec;
    sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
  }
#endif
  y.validYMD = 1;
  y.validHMS = 1;
  y.validJD = 0;
  y.validTZ = 0;
  computeJD(&y);







|







|







470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
    y.h = sLocal.tm_hour;
    y.m = sLocal.tm_min;
    y.s = sLocal.tm_sec;
  }
#else
  {
    struct tm *pTm;
    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
    pTm = localtime(&t);
    y.Y = pTm->tm_year + 1900;
    y.M = pTm->tm_mon + 1;
    y.D = pTm->tm_mday;
    y.h = pTm->tm_hour;
    y.m = pTm->tm_min;
    y.s = pTm->tm_sec;
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  }
#endif
  y.validYMD = 1;
  y.validHMS = 1;
  y.validJD = 0;
  y.validTZ = 0;
  computeJD(&y);
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
    struct tm sNow;
    gmtime_r(&t, &sNow);
    strftime(zBuf, 20, zFormat, &sNow);
  }
#else
  {
    struct tm *pTm;
    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
    pTm = gmtime(&t);
    strftime(zBuf, 20, zFormat, pTm);
    sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
  }
#endif

  sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
#endif








|


|







1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
    struct tm sNow;
    gmtime_r(&t, &sNow);
    strftime(zBuf, 20, zFormat, &sNow);
  }
#else
  {
    struct tm *pTm;
    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
    pTm = gmtime(&t);
    strftime(zBuf, 20, zFormat, pTm);
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  }
#endif

  sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
#endif

Changes to src/loadext.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to dynamically load extensions into
** the SQLite library.
**
** $Id: loadext.c,v 1.48 2008/06/13 18:24:27 drh Exp $
*/

#ifndef SQLITE_CORE
  #define SQLITE_CORE 1  /* Disable the API redefinition in sqlite3ext.h */
#endif
#include "sqlite3ext.h"
#include "sqliteInt.h"







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to dynamically load extensions into
** the SQLite library.
**
** $Id: loadext.c,v 1.49 2008/06/18 17:09:10 danielk1977 Exp $
*/

#ifndef SQLITE_CORE
  #define SQLITE_CORE 1  /* Disable the API redefinition in sqlite3ext.h */
#endif
#include "sqlite3ext.h"
#include "sqliteInt.h"
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  if( rc ){
    return rc;
  }else
#endif
  {
    int i;
#ifndef SQLITE_MUTEX_NOOP
    sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
    sqlite3_mutex_enter(mutex);
    for(i=0; i<autoext.nExt; i++){
      if( autoext.aExt[i]==xInit ) break;
    }
    if( i==autoext.nExt ){
      int nByte = (autoext.nExt+1)*sizeof(autoext.aExt[0]);







|







474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  if( rc ){
    return rc;
  }else
#endif
  {
    int i;
#ifndef SQLITE_MUTEX_NOOP
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
    sqlite3_mutex_enter(mutex);
    for(i=0; i<autoext.nExt; i++){
      if( autoext.aExt[i]==xInit ) break;
    }
    if( i==autoext.nExt ){
      int nByte = (autoext.nExt+1)*sizeof(autoext.aExt[0]);
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
*/
void sqlite3_reset_auto_extension(void){
#ifndef SQLITE_OMIT_AUTOINIT
  if( sqlite3_initialize()==SQLITE_OK )
#endif
  {
#ifndef SQLITE_MUTEX_NOOP
    sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
    sqlite3_mutex_enter(mutex);
    sqlite3_free(autoext.aExt);
    autoext.aExt = 0;
    autoext.nExt = 0;
    sqlite3_mutex_leave(mutex);
  }







|







507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
*/
void sqlite3_reset_auto_extension(void){
#ifndef SQLITE_OMIT_AUTOINIT
  if( sqlite3_initialize()==SQLITE_OK )
#endif
  {
#ifndef SQLITE_MUTEX_NOOP
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
    sqlite3_mutex_enter(mutex);
    sqlite3_free(autoext.aExt);
    autoext.aExt = 0;
    autoext.nExt = 0;
    sqlite3_mutex_leave(mutex);
  }
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
  if( autoext.nExt==0 ){
    /* Common case: early out without every having to acquire a mutex */
    return SQLITE_OK;
  }
  for(i=0; go; i++){
    char *zErrmsg = 0;
#ifndef SQLITE_MUTEX_NOOP
    sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
    sqlite3_mutex_enter(mutex);
    if( i>=autoext.nExt ){
      xInit = 0;
      go = 0;
    }else{
      xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))







|







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
  if( autoext.nExt==0 ){
    /* Common case: early out without every having to acquire a mutex */
    return SQLITE_OK;
  }
  for(i=0; go; i++){
    char *zErrmsg = 0;
#ifndef SQLITE_MUTEX_NOOP
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
    sqlite3_mutex_enter(mutex);
    if( i>=autoext.nExt ){
      xInit = 0;
      go = 0;
    }else{
      xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
Changes to src/main.c.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** 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.448 2008/06/18 13:27:47 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** 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.449 2008/06/18 17:09:10 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
** or for the first call after a call to sqlite3_shutdown.
*/
int sqlite3_initialize(void){
  int rc;
  if( sqlite3IsInit ) return SQLITE_OK;
  rc = sqlite3_mutex_init();
  if( rc==SQLITE_OK ){
    sqlite3_mutex *pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
    sqlite3_mutex_enter(pMutex);
    if( sqlite3IsInit==0 ){
      sqlite3IsInit = 1;
      if( rc==SQLITE_OK ) rc = sqlite3MallocInit();
      if( rc==SQLITE_OK ) rc = sqlite3_os_init();
      if( rc!=SQLITE_OK ){
        sqlite3IsInit = 0;







|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
** or for the first call after a call to sqlite3_shutdown.
*/
int sqlite3_initialize(void){
  int rc;
  if( sqlite3IsInit ) return SQLITE_OK;
  rc = sqlite3_mutex_init();
  if( rc==SQLITE_OK ){
    sqlite3_mutex *pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
    sqlite3_mutex_enter(pMutex);
    if( sqlite3IsInit==0 ){
      sqlite3IsInit = 1;
      if( rc==SQLITE_OK ) rc = sqlite3MallocInit();
      if( rc==SQLITE_OK ) rc = sqlite3_os_init();
      if( rc!=SQLITE_OK ){
        sqlite3IsInit = 0;
1204
1205
1206
1207
1208
1209
1210

1211
1212
1213
1214
1215
1216

1217
1218
1219
1220
1221
1222
1223
               SQLITE_OPEN_SUBJOURNAL | 
               SQLITE_OPEN_MASTER_JOURNAL
             );

  /* Allocate the sqlite data structure */
  db = sqlite3MallocZero( sizeof(sqlite3) );
  if( db==0 ) goto opendb_out;

  db->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
  if( db->mutex==0 ){
    sqlite3_free(db);
    db = 0;
    goto opendb_out;
  }

  sqlite3_mutex_enter(db->mutex);
  db->errMask = 0xff;
  db->priorNewRowid = 0;
  db->nDb = 2;
  db->magic = SQLITE_MAGIC_BUSY;
  db->aDb = db->aDbStatic;
  assert( sizeof(db->aLimit)==sizeof(aHardLimit) );







>
|





>







1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
               SQLITE_OPEN_SUBJOURNAL | 
               SQLITE_OPEN_MASTER_JOURNAL
             );

  /* Allocate the sqlite data structure */
  db = sqlite3MallocZero( sizeof(sqlite3) );
  if( db==0 ) goto opendb_out;
  if( sqlite3Config.bFullMutex ){
    db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
  if( db->mutex==0 ){
    sqlite3_free(db);
    db = 0;
    goto opendb_out;
  }
  }
  sqlite3_mutex_enter(db->mutex);
  db->errMask = 0xff;
  db->priorNewRowid = 0;
  db->nDb = 2;
  db->magic = SQLITE_MAGIC_BUSY;
  db->aDb = db->aDbStatic;
  assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
  db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE;
  sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt),
                          SQLITE_DEFAULT_LOCKING_MODE);
#endif

opendb_out:
  if( db ){
    assert( db->mutex!=0 );
    sqlite3_mutex_leave(db->mutex);
  }
  if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
    sqlite3_close(db);
    db = 0;
  }
  *ppDb = db;







|







1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
  db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE;
  sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt),
                          SQLITE_DEFAULT_LOCKING_MODE);
#endif

opendb_out:
  if( db ){
    assert( db->mutex!=0 || sqlite3Config.bFullMutex==0 );
    sqlite3_mutex_leave(db->mutex);
  }
  if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
    sqlite3_close(db);
    db = 0;
  }
  *ppDb = db;
Changes to src/malloc.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** Memory allocation functions used throughout sqlite.
**
** $Id: malloc.c,v 1.18 2008/06/17 15:12:01 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

/*
** This routine runs when the memory allocator sees that the







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** Memory allocation functions used throughout sqlite.
**
** $Id: malloc.c,v 1.19 2008/06/18 17:09:10 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

/*
** This routine runs when the memory allocator sees that the
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
** Initialize the memory allocation subsystem.
*/
int sqlite3MallocInit(void){
  if( sqlite3Config.m.xMalloc==0 ){
    sqlite3MemSetDefault();
  }
  memset(&mem0, 0, sizeof(mem0));
  if( sqlite3Config.bMemstat && sqlite3Config.bCoreMutex ){
    mem0.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
  }
  return sqlite3Config.m.xInit(sqlite3Config.m.pAppData);
}

/*
** Deinitialize the memory allocation subsystem.
*/







|
|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
** Initialize the memory allocation subsystem.
*/
int sqlite3MallocInit(void){
  if( sqlite3Config.m.xMalloc==0 ){
    sqlite3MemSetDefault();
  }
  memset(&mem0, 0, sizeof(mem0));
  if( sqlite3Config.bMemstat ){
    mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
  }
  return sqlite3Config.m.xInit(sqlite3Config.m.pAppData);
}

/*
** Deinitialize the memory allocation subsystem.
*/
Changes to src/mem2.c.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
** 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.31 2008/06/17 17:21:18 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is used only if the
** SQLITE_MEMDEBUG macro is defined
*/







|







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

/*
** This version of the memory allocator is used only if the
** SQLITE_MEMDEBUG macro is defined
*/
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  return pHdr->iSize;
}

/*
** Initialize the memory allocation subsystem.
*/
static int sqlite3MemInit(void *NotUsed){
  mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  return SQLITE_OK;
}

/*
** Deinitialize the memory allocation subsystem.
*/
static void sqlite3MemShutdown(void *NotUsed){







|







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  return pHdr->iSize;
}

/*
** Initialize the memory allocation subsystem.
*/
static int sqlite3MemInit(void *NotUsed){
  mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
  return SQLITE_OK;
}

/*
** Deinitialize the memory allocation subsystem.
*/
static void sqlite3MemShutdown(void *NotUsed){
Changes to src/mem3.c.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
** use of malloc().  All dynamically allocatable memory is
** contained in a static array, mem.aPool[].  The size of this
** fixed memory pool is SQLITE_MEMORY_SIZE bytes.
**
** This version of the memory allocation subsystem is used if
** and only if SQLITE_MEMORY_SIZE is defined.
**
** $Id: mem3.c,v 1.13 2008/06/13 18:24:27 drh Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is used only when 
** SQLITE_MEMORY_SIZE is defined.
*/







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
** use of malloc().  All dynamically allocatable memory is
** contained in a static array, mem.aPool[].  The size of this
** fixed memory pool is SQLITE_MEMORY_SIZE bytes.
**
** This version of the memory allocation subsystem is used if
** and only if SQLITE_MEMORY_SIZE is defined.
**
** $Id: mem3.c,v 1.14 2008/06/18 17:09:10 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is used only when 
** SQLITE_MEMORY_SIZE is defined.
*/
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
**
** Also:  Initialize the memory allocation subsystem the first time
** this routine is called.
*/
static void memsys3Enter(void){
  if( mem.mutex==0 ){
    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
    mem.aPool[0].u.hdr.size4x = SQLITE_MEMORY_SIZE/2 + 2;
    mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.prevSize = SQLITE_MEMORY_SIZE/8;
    mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.size4x = 1;
    mem.iMaster = 1;
    mem.szMaster = SQLITE_MEMORY_SIZE/8;
    mem.mnMaster = mem.szMaster;
  }







|







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
**
** Also:  Initialize the memory allocation subsystem the first time
** this routine is called.
*/
static void memsys3Enter(void){
  if( mem.mutex==0 ){
    mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
    mem.aPool[0].u.hdr.size4x = SQLITE_MEMORY_SIZE/2 + 2;
    mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.prevSize = SQLITE_MEMORY_SIZE/8;
    mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.size4x = 1;
    mem.iMaster = 1;
    mem.szMaster = SQLITE_MEMORY_SIZE/8;
    mem.mnMaster = mem.szMaster;
  }
Changes to src/mem4.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.2 2008/02/14 23:26:56 drh 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







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

/*
** 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 = sqlite3_mutex_alloc(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







|







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

/*
** 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
Changes to src/mem5.c.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
** use of malloc().  All dynamically allocatable memory is
** contained in a static array, mem.aPool[].  The size of this
** fixed memory pool is SQLITE_POW2_MEMORY_SIZE bytes.
**
** This version of the memory allocation subsystem is used if
** and only if SQLITE_POW2_MEMORY_SIZE is defined.
**
** $Id: mem5.c,v 1.5 2008/06/13 18:24:27 drh Exp $
*/
#include "sqliteInt.h"

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







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
** use of malloc().  All dynamically allocatable memory is
** contained in a static array, mem.aPool[].  The size of this
** fixed memory pool is SQLITE_POW2_MEMORY_SIZE bytes.
**
** This version of the memory allocation subsystem is used if
** and only if SQLITE_POW2_MEMORY_SIZE is defined.
**
** $Id: mem5.c,v 1.6 2008/06/18 17:09:10 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is used only when 
** SQLITE_POW2_MEMORY_SIZE is defined.
*/
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
*/
static void memsys5Enter(void){
  if( mem.mutex==0 ){
    int i;
    assert( sizeof(Mem5Block)==POW2_MIN );
    assert( (SQLITE_POW2_MEMORY_SIZE % POW2_MAX)==0 );
    assert( SQLITE_POW2_MEMORY_SIZE>=POW2_MAX );
    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
    sqlite3_mutex_enter(mem.mutex);
    for(i=0; i<NSIZE; i++) mem.aiFreelist[i] = -1;
    for(i=0; i<=NBLOCK-SZ_MAX; i += SZ_MAX){
      mem.aCtrl[i] = (NSIZE-1) | CTRL_FREE;
      memsys5Link(i, NSIZE-1);
    }
  }else{







|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
*/
static void memsys5Enter(void){
  if( mem.mutex==0 ){
    int i;
    assert( sizeof(Mem5Block)==POW2_MIN );
    assert( (SQLITE_POW2_MEMORY_SIZE % POW2_MAX)==0 );
    assert( SQLITE_POW2_MEMORY_SIZE>=POW2_MAX );
    mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
    sqlite3_mutex_enter(mem.mutex);
    for(i=0; i<NSIZE; i++) mem.aiFreelist[i] = -1;
    for(i=0; i<=NBLOCK-SZ_MAX; i += SZ_MAX){
      mem.aCtrl[i] = (NSIZE-1) | CTRL_FREE;
      memsys5Link(i, NSIZE-1);
    }
  }else{
Changes to src/mutex.c.
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
** exclusion and is thus suitable for use only in applications
** that use SQLite in a single thread.  But this implementation
** does do a lot of error checking on mutexes to make sure they
** are called correctly and at appropriate times.  Hence, this
** implementation is suitable for testing.
** debugging purposes
**
** $Id: mutex.c,v 1.23 2008/06/18 09:45:56 danielk1977 Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_MUTEX_NOOP
/*
** Initialize the mutex system.
*/
int sqlite3_mutex_init(void){ 
  int rc;

  if( !sqlite3Config.mutex.xMutexAlloc ){
    /* If the xMutexAlloc method has not been set, then the user did not
    ** install a mutex implementation via sqlite3_config() prior to 
    ** sqlite3_initialize() being called. This block copies pointers to
    ** the default implementation into the sqlite3Config structure.
    **
    ** The danger is that although sqlite3_config() is not a threadsafe
    ** API, sqlite3_initialize() is, and so multiple threads may be
    ** attempting to run this function simultaneously. To guard write
    ** access to the sqlite3Config structure, the 'MASTER' static mutex
    ** is obtained before modifying it.
    */
    sqlite3_mutex_methods *p = sqlite3DefaultMutex();
    sqlite3_mutex *pMaster;

    rc = p->xMutexInit();
    if( rc==SQLITE_OK ){
      pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
      assert(pMaster);
      p->xMutexEnter(pMaster);
      assert( sqlite3Config.mutex.xMutexAlloc==0 
           || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc
      );
      if( !sqlite3Config.mutex.xMutexAlloc ){
        sqlite3Config.mutex = *p;
      }
      p->xMutexLeave(pMaster);
    }
  }else{
    rc = sqlite3Config.mutex.xMutexInit();
  }


  return rc;
}

/*
** Shutdown the mutex system. This call frees resources allocated by
** sqlite3_mutex_init().
*/
int sqlite3_mutex_end(void){
  int rc = SQLITE_OK;
  rc = sqlite3Config.mutex.xMutexEnd();
  return rc;
}

/*
** Retrieve a pointer to a static mutex or allocate a new dynamic one.
*/
sqlite3_mutex *sqlite3_mutex_alloc(int id){
  return sqlite3Config.mutex.xMutexAlloc(id);
}








/*
** Free a dynamic mutex.
*/
void sqlite3_mutex_free(sqlite3_mutex *p){
  if( p ){
    sqlite3Config.mutex.xMutexFree(p);







|








|
>













|

















>




















>
>
>
>
>
>
>







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
** exclusion and is thus suitable for use only in applications
** that use SQLite in a single thread.  But this implementation
** does do a lot of error checking on mutexes to make sure they
** are called correctly and at appropriate times.  Hence, this
** implementation is suitable for testing.
** debugging purposes
**
** $Id: mutex.c,v 1.24 2008/06/18 17:09:10 danielk1977 Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_MUTEX_NOOP
/*
** Initialize the mutex system.
*/
int sqlite3_mutex_init(void){ 
  int rc = SQLITE_OK;
  if( sqlite3Config.bCoreMutex ){
  if( !sqlite3Config.mutex.xMutexAlloc ){
    /* If the xMutexAlloc method has not been set, then the user did not
    ** install a mutex implementation via sqlite3_config() prior to 
    ** sqlite3_initialize() being called. This block copies pointers to
    ** the default implementation into the sqlite3Config structure.
    **
    ** The danger is that although sqlite3_config() is not a threadsafe
    ** API, sqlite3_initialize() is, and so multiple threads may be
    ** attempting to run this function simultaneously. To guard write
    ** access to the sqlite3Config structure, the 'MASTER' static mutex
    ** is obtained before modifying it.
    */
    sqlite3_mutex_methods *p = sqlite3DefaultMutex();
      sqlite3_mutex *pMaster = 0;

    rc = p->xMutexInit();
    if( rc==SQLITE_OK ){
      pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
      assert(pMaster);
      p->xMutexEnter(pMaster);
      assert( sqlite3Config.mutex.xMutexAlloc==0 
           || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc
      );
      if( !sqlite3Config.mutex.xMutexAlloc ){
        sqlite3Config.mutex = *p;
      }
      p->xMutexLeave(pMaster);
    }
  }else{
    rc = sqlite3Config.mutex.xMutexInit();
  }
  }

  return rc;
}

/*
** Shutdown the mutex system. This call frees resources allocated by
** sqlite3_mutex_init().
*/
int sqlite3_mutex_end(void){
  int rc = SQLITE_OK;
  rc = sqlite3Config.mutex.xMutexEnd();
  return rc;
}

/*
** Retrieve a pointer to a static mutex or allocate a new dynamic one.
*/
sqlite3_mutex *sqlite3_mutex_alloc(int id){
  return sqlite3Config.mutex.xMutexAlloc(id);
}

sqlite3_mutex *sqlite3MutexAlloc(int id){
  if( !sqlite3Config.bCoreMutex ){
    return 0;
  }
  return sqlite3Config.mutex.xMutexAlloc(id);
}

/*
** Free a dynamic mutex.
*/
void sqlite3_mutex_free(sqlite3_mutex *p){
  if( p ){
    sqlite3Config.mutex.xMutexFree(p);
Changes to src/os.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains OS interface code that is common to all
** architectures.
**
** $Id: os.c,v 1.113 2008/06/15 02:51:48 drh Exp $
*/
#define _SQLITE_OS_C_ 1
#include "sqliteInt.h"
#undef _SQLITE_OS_C_

/*
** The default SQLite sqlite3_vfs implementations do not allocate







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains OS interface code that is common to all
** architectures.
**
** $Id: os.c,v 1.114 2008/06/18 17:09:10 danielk1977 Exp $
*/
#define _SQLITE_OS_C_ 1
#include "sqliteInt.h"
#undef _SQLITE_OS_C_

/*
** The default SQLite sqlite3_vfs implementations do not allocate
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
  sqlite3_mutex *mutex;
#endif
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return 0;
#endif
#ifndef SQLITE_MUTEX_NOOP
  mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  sqlite3_vfs *pVfs = 0;
  static int isInit = 0;
  sqlite3_mutex_enter(mutex);
  if( !isInit ){
    vfsList = sqlite3OsDefaultVfs();
    isInit = 1;
  }
  for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
    if( zVfs==0 ) break;
    if( strcmp(zVfs, pVfs->zName)==0 ) break;
  }
  sqlite3_mutex_leave(mutex);
  return pVfs;
}

/*
** Unlink a VFS from the linked list
*/
static void vfsUnlink(sqlite3_vfs *pVfs){
  assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) );
  if( pVfs==0 ){
    /* No-op */
  }else if( vfsList==pVfs ){
    vfsList = pVfs->pNext;
  }else if( vfsList ){
    sqlite3_vfs *p = vfsList;
    while( p->pNext && p->pNext!=pVfs ){







|




















|







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
  sqlite3_mutex *mutex;
#endif
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return 0;
#endif
#ifndef SQLITE_MUTEX_NOOP
  mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  sqlite3_vfs *pVfs = 0;
  static int isInit = 0;
  sqlite3_mutex_enter(mutex);
  if( !isInit ){
    vfsList = sqlite3OsDefaultVfs();
    isInit = 1;
  }
  for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
    if( zVfs==0 ) break;
    if( strcmp(zVfs, pVfs->zName)==0 ) break;
  }
  sqlite3_mutex_leave(mutex);
  return pVfs;
}

/*
** Unlink a VFS from the linked list
*/
static void vfsUnlink(sqlite3_vfs *pVfs){
  assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
  if( pVfs==0 ){
    /* No-op */
  }else if( vfsList==pVfs ){
    vfsList = pVfs->pNext;
  }else if( vfsList ){
    sqlite3_vfs *p = vfsList;
    while( p->pNext && p->pNext!=pVfs ){
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  sqlite3_mutex *mutex;
#endif
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return rc;
#endif
#ifndef SQLITE_MUTEX_NOOP
  mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  sqlite3_vfs_find(0);  /* Make sure we are initialized */
  sqlite3_mutex_enter(mutex);
  vfsUnlink(pVfs);
  if( makeDflt || vfsList==0 ){
    pVfs->pNext = vfsList;
    vfsList = pVfs;







|







254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  sqlite3_mutex *mutex;
#endif
#ifndef SQLITE_OMIT_AUTOINIT
  int rc = sqlite3_initialize();
  if( rc ) return rc;
#endif
#ifndef SQLITE_MUTEX_NOOP
  mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  sqlite3_vfs_find(0);  /* Make sure we are initialized */
  sqlite3_mutex_enter(mutex);
  vfsUnlink(pVfs);
  if( makeDflt || vfsList==0 ){
    pVfs->pNext = vfsList;
    vfsList = pVfs;
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
}

/*
** Unregister a VFS so that it is no longer accessible.
*/
int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
#ifndef SQLITE_MUTEX_NOOP
  sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  sqlite3_mutex_enter(mutex);
  vfsUnlink(pVfs);
  sqlite3_mutex_leave(mutex);
  return SQLITE_OK;
}








|







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
}

/*
** Unregister a VFS so that it is no longer accessible.
*/
int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
#ifndef SQLITE_MUTEX_NOOP
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
  sqlite3_mutex_enter(mutex);
  vfsUnlink(pVfs);
  sqlite3_mutex_leave(mutex);
  return SQLITE_OK;
}

Changes to src/os_unix.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code that is specific to Unix systems.
**
** $Id: os_unix.c,v 1.187 2008/06/13 18:24:27 drh Exp $
*/
#include "sqliteInt.h"
#if OS_UNIX              /* This file is used on unix only */

/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */

/*







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code that is specific to Unix systems.
**
** $Id: os_unix.c,v 1.188 2008/06/18 17:09:10 danielk1977 Exp $
*/
#include "sqliteInt.h"
#if OS_UNIX              /* This file is used on unix only */

/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */

/*
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
} sqlite3LockingStyle;
#endif /* SQLITE_ENABLE_LOCKING_STYLE */

/*
** Helper functions to obtain and relinquish the global mutex.
*/
static void enterMutex(){
  sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
}
static void leaveMutex(){
  sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
}

#if SQLITE_THREADSAFE
/*
** This variable records whether or not threads can override each others
** locks.
**







|


|







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
} sqlite3LockingStyle;
#endif /* SQLITE_ENABLE_LOCKING_STYLE */

/*
** Helper functions to obtain and relinquish the global mutex.
*/
static void enterMutex(){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
static void leaveMutex(){
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}

#if SQLITE_THREADSAFE
/*
** This variable records whether or not threads can override each others
** locks.
**
Changes to src/pager.c.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.458 2008/06/17 15:12:01 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.459 2008/06/18 17:09:10 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  static void pagerEnter(Pager *p){
    p->iInUseDB++;
    if( p->iInUseMM && p->iInUseDB==1 ){
#ifndef SQLITE_MUTEX_NOOP
      sqlite3_mutex *mutex;
      mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
      p->iInUseDB = 0;
      sqlite3_mutex_enter(mutex);
      p->iInUseDB = 1;
      sqlite3_mutex_leave(mutex);
    }
    assert( p->iInUseMM==0 );







|







514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  static void pagerEnter(Pager *p){
    p->iInUseDB++;
    if( p->iInUseMM && p->iInUseDB==1 ){
#ifndef SQLITE_MUTEX_NOOP
      sqlite3_mutex *mutex;
      mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
      p->iInUseDB = 0;
      sqlite3_mutex_enter(mutex);
      p->iInUseDB = 1;
      sqlite3_mutex_leave(mutex);
    }
    assert( p->iInUseMM==0 );
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
** memory-management is enabled, also add the page to the global 
** list of free pages.
*/
static void lruListAdd(PgHdr *pPg){
  listAdd(&pPg->pPager->lru, &pPg->free, pPg);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( !pPg->pPager->memDb ){
    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU));
    listAdd(&sqlite3LruPageList, &pPg->gfree, pPg);
    sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU));
  }
#endif
}

/* 
** Remove page pPg from the list of free pages for the associated pager.
** If memory-management is enabled, also remove pPg from the global list
** of free pages.
*/
static void lruListRemove(PgHdr *pPg){
  listRemove(&pPg->pPager->lru, &pPg->free, pPg);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( !pPg->pPager->memDb ){
    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU));
    listRemove(&sqlite3LruPageList, &pPg->gfree, pPg);
    sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU));
  }
#endif
}

/* 
** This function is called just after the needSync flag has been cleared
** from all pages managed by pPager (usually because the journal file
** has just been synced). It updates the pPager->lru.pFirstSynced variable
** and, if memory-management is enabled, the sqlite3LruPageList.pFirstSynced
** variable also.
*/
static void lruListSetFirstSynced(Pager *pPager){
  pPager->lru.pFirstSynced = pPager->lru.pFirst;
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( !pPager->memDb ){
    PgHdr *p;
    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU));
    for(p=sqlite3LruPageList.pFirst; p && p->needSync; p=p->gfree.pNext);
    assert(p==pPager->lru.pFirstSynced || p==sqlite3LruPageList.pFirstSynced);
    sqlite3LruPageList.pFirstSynced = p;
    sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU));
  }
#endif
}

/*
** Return true if page *pPg has already been written to the statement
** journal (or statement snapshot has been created, if *pPg is part







|

|













|

|
















|



|







612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
** memory-management is enabled, also add the page to the global 
** list of free pages.
*/
static void lruListAdd(PgHdr *pPg){
  listAdd(&pPg->pPager->lru, &pPg->free, pPg);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( !pPg->pPager->memDb ){
    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
    listAdd(&sqlite3LruPageList, &pPg->gfree, pPg);
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
  }
#endif
}

/* 
** Remove page pPg from the list of free pages for the associated pager.
** If memory-management is enabled, also remove pPg from the global list
** of free pages.
*/
static void lruListRemove(PgHdr *pPg){
  listRemove(&pPg->pPager->lru, &pPg->free, pPg);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( !pPg->pPager->memDb ){
    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
    listRemove(&sqlite3LruPageList, &pPg->gfree, pPg);
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
  }
#endif
}

/* 
** This function is called just after the needSync flag has been cleared
** from all pages managed by pPager (usually because the journal file
** has just been synced). It updates the pPager->lru.pFirstSynced variable
** and, if memory-management is enabled, the sqlite3LruPageList.pFirstSynced
** variable also.
*/
static void lruListSetFirstSynced(Pager *pPager){
  pPager->lru.pFirstSynced = pPager->lru.pFirst;
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( !pPager->memDb ){
    PgHdr *p;
    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
    for(p=sqlite3LruPageList.pFirst; p && p->needSync; p=p->gfree.pNext);
    assert(p==pPager->lru.pFirstSynced || p==sqlite3LruPageList.pFirstSynced);
    sqlite3LruPageList.pFirstSynced = p;
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
  }
#endif
}

/*
** Return true if page *pPg has already been written to the statement
** journal (or statement snapshot has been created, if *pPg is part
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
  *ppPager = pPager;
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  pPager->iInUseMM = 0;
  pPager->iInUseDB = 0;
  if( !memDb ){
#ifndef SQLITE_MUTEX_NOOP
    sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
    sqlite3_mutex_enter(mutex);
    pPager->pNext = sqlite3PagerList;
    if( sqlite3PagerList ){
      assert( sqlite3PagerList->pPrev==0 );
      sqlite3PagerList->pPrev = pPager;
    }







|







2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
  /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
  *ppPager = pPager;
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  pPager->iInUseMM = 0;
  pPager->iInUseDB = 0;
  if( !memDb ){
#ifndef SQLITE_MUTEX_NOOP
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
    sqlite3_mutex_enter(mutex);
    pPager->pNext = sqlite3PagerList;
    if( sqlite3PagerList ){
      assert( sqlite3PagerList->pPrev==0 );
      sqlite3PagerList->pPrev = pPager;
    }
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
** a hot journal may be left in the filesystem but no error is returned
** to the caller.
*/
int sqlite3PagerClose(Pager *pPager){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( !MEMDB ){
#ifndef SQLITE_MUTEX_NOOP
    sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
    sqlite3_mutex_enter(mutex);
    if( pPager->pPrev ){
      pPager->pPrev->pNext = pPager->pNext;
    }else{
      sqlite3PagerList = pPager->pNext;
    }







|







2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
** a hot journal may be left in the filesystem but no error is returned
** to the caller.
*/
int sqlite3PagerClose(Pager *pPager){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( !MEMDB ){
#ifndef SQLITE_MUTEX_NOOP
    sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
    sqlite3_mutex_enter(mutex);
    if( pPager->pPrev ){
      pPager->pPrev->pNext = pPager->pNext;
    }else{
      sqlite3PagerList = pPager->pNext;
    }
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
  BusyHandler *savedBusy;     /* Saved copy of the busy handler */
  int rc = SQLITE_OK;

  /* Acquire the memory-management mutex
  */
#ifndef SQLITE_MUTEX_NOOP
  sqlite3_mutex *mutex;       /* The MEM2 mutex */
  mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
  sqlite3_mutex_enter(mutex);

  /* Signal all database connections that memory management wants
  ** to have access to the pagers.
  */
  for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
     pPager->iInUseMM = 1;
  }

  while( rc==SQLITE_OK && (nReq<0 || nReleased<nReq) ){
    PgHdr *pPg;
    PgHdr *pRecycled;
 
    /* Try to find a page to recycle that does not require a sync(). If
    ** this is not possible, find one that does require a sync().
    */
    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU));
    pPg = sqlite3LruPageList.pFirstSynced;
    while( pPg && (pPg->needSync || pPg->pPager->iInUseDB) ){
      pPg = pPg->gfree.pNext;
    }
    if( !pPg ){
      pPg = sqlite3LruPageList.pFirst;
      while( pPg && pPg->pPager->iInUseDB ){
        pPg = pPg->gfree.pNext;
      }
    }
    sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU));

    /* If pPg==0, then the block above has failed to find a page to
    ** recycle. In this case return early - no further memory will
    ** be released.
    */
    if( !pPg ) break;








|

















|










|







3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
  BusyHandler *savedBusy;     /* Saved copy of the busy handler */
  int rc = SQLITE_OK;

  /* Acquire the memory-management mutex
  */
#ifndef SQLITE_MUTEX_NOOP
  sqlite3_mutex *mutex;       /* The MEM2 mutex */
  mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
  sqlite3_mutex_enter(mutex);

  /* Signal all database connections that memory management wants
  ** to have access to the pagers.
  */
  for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
     pPager->iInUseMM = 1;
  }

  while( rc==SQLITE_OK && (nReq<0 || nReleased<nReq) ){
    PgHdr *pPg;
    PgHdr *pRecycled;
 
    /* Try to find a page to recycle that does not require a sync(). If
    ** this is not possible, find one that does require a sync().
    */
    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
    pPg = sqlite3LruPageList.pFirstSynced;
    while( pPg && (pPg->needSync || pPg->pPager->iInUseDB) ){
      pPg = pPg->gfree.pNext;
    }
    if( !pPg ){
      pPg = sqlite3LruPageList.pFirst;
      while( pPg && pPg->pPager->iInUseDB ){
        pPg = pPg->gfree.pNext;
      }
    }
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));

    /* If pPg==0, then the block above has failed to find a page to
    ** recycle. In this case return early - no further memory will
    ** be released.
    */
    if( !pPg ) break;

Changes to src/random.c.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** This file contains code to implement a pseudo-random number
** generator (PRNG) for SQLite.
**
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
** $Id: random.c,v 1.23 2008/03/21 16:45:47 drh Exp $
*/
#include "sqliteInt.h"


/* All threads share a single random number generator.
** This structure is the current state of the generator.
*/







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** This file contains code to implement a pseudo-random number
** generator (PRNG) for SQLite.
**
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
** $Id: random.c,v 1.24 2008/06/18 17:09:10 danielk1977 Exp $
*/
#include "sqliteInt.h"


/* All threads share a single random number generator.
** This structure is the current state of the generator.
*/
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
}

/*
** Return N random bytes.
*/
void sqlite3_randomness(int N, void *pBuf){
  unsigned char *zBuf = pBuf;
  static sqlite3_mutex *mutex = 0;
  if( mutex==0 ){
    mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG);
  }
  sqlite3_mutex_enter(mutex);
  while( N-- ){
    *(zBuf++) = randomByte();
  }
  sqlite3_mutex_leave(mutex);
}








<
<
|
<







88
89
90
91
92
93
94


95

96
97
98
99
100
101
102
}

/*
** Return N random bytes.
*/
void sqlite3_randomness(int N, void *pBuf){
  unsigned char *zBuf = pBuf;


  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);

  sqlite3_mutex_enter(mutex);
  while( N-- ){
    *(zBuf++) = randomByte();
  }
  sqlite3_mutex_leave(mutex);
}

Changes to src/sqliteInt.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** 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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.713 2008/06/18 13:27:47 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** 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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.714 2008/06/18 17:09:10 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
1802
1803
1804
1805
1806
1807
1808

1809
1810
1811
1812
1813
1814
1815
void *sqlite3ScratchMalloc(int);
void sqlite3ScratchFree(void*);
void *sqlite3PageMalloc(int);
void sqlite3PageFree(void*);
void sqlite3MemSetDefault(void);

sqlite3_mutex_methods *sqlite3DefaultMutex(void);


int sqlite3IsNaN(double);

char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
  void sqlite3DebugPrintf(const char*, ...);







>







1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
void *sqlite3ScratchMalloc(int);
void sqlite3ScratchFree(void*);
void *sqlite3PageMalloc(int);
void sqlite3PageFree(void*);
void sqlite3MemSetDefault(void);

sqlite3_mutex_methods *sqlite3DefaultMutex(void);
sqlite3_mutex *sqlite3MutexAlloc(int);

int sqlite3IsNaN(double);

char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
  void sqlite3DebugPrintf(const char*, ...);
Changes to src/test3.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the btree.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.97 2008/06/06 11:11:26 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>








|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the btree.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.98 2008/06/18 17:09:10 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    return TCL_ERROR;
  }
  if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
  if( Tcl_GetInt(interp, argv[3], &flags) ) return TCL_ERROR;
  nRefSqlite3++;
  if( nRefSqlite3==1 ){
    sDb.pVfs = sqlite3_vfs_find(0);
    sDb.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
    sqlite3_mutex_enter(sDb.mutex);
  }
  rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, flags,
     SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;







|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    return TCL_ERROR;
  }
  if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
  if( Tcl_GetInt(interp, argv[3], &flags) ) return TCL_ERROR;
  nRefSqlite3++;
  if( nRefSqlite3==1 ){
    sDb.pVfs = sqlite3_vfs_find(0);
    sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
    sqlite3_mutex_enter(sDb.mutex);
  }
  rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, flags,
     SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
Changes to src/test_mutex.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
** 2008 June 18
**
** 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: test_mutex.c,v 1.1 2008/06/18 09:45:56 danielk1977 Exp $
*/

#include "tcl.h"
#include "sqlite3.h"
#include <stdlib.h>
#include <assert.h>
#include <string.h>












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
** 2008 June 18
**
** 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: test_mutex.c,v 1.2 2008/06/18 17:09:10 danielk1977 Exp $
*/

#include "tcl.h"
#include "sqlite3.h"
#include <stdlib.h>
#include <assert.h>
#include <string.h>
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
  }

  for(ii=0; ii<8; ii++){
    g.aCounter[ii] = 0;
  }
  return TCL_OK;
}





































int Sqlitetest_mutex_Init(Tcl_Interp *interp){
  static struct {
    char *zName;
    Tcl_ObjCmdProc *xProc;
  } aCmd[] = {
    { "sqlite3_shutdown",        (Tcl_ObjCmdProc*)test_shutdown },
    { "sqlite3_initialize",      (Tcl_ObjCmdProc*)test_initialize },


    { "install_mutex_counters",  (Tcl_ObjCmdProc*)test_install_mutex_counters },
    { "read_mutex_counters",     (Tcl_ObjCmdProc*)test_read_mutex_counters },
    { "clear_mutex_counters",    (Tcl_ObjCmdProc*)test_clear_mutex_counters },
  };
  int i;
  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  }
  memset(&g, 0, sizeof(g));
  return SQLITE_OK;
}








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








>













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
  }

  for(ii=0; ii<8; ii++){
    g.aCounter[ii] = 0;
  }
  return TCL_OK;
}

/*
** sqlite3_config OPTION
*/
static int test_config(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  struct ConfigOption {
    const char *zName;
    int iValue;
  } aOpt[] = {
    {"singlethread", SQLITE_CONFIG_SINGLETHREAD},
    {"multithread",  SQLITE_CONFIG_MULTITHREAD},
    {"serialized",   SQLITE_CONFIG_SERIALIZED},
    {0, 0}
  };
  int s = sizeof(struct ConfigOption);
  int i;
  int rc;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }

  if( Tcl_GetIndexFromObjStruct(interp, objv[1], aOpt, s, "flag", 0, &i) ){
    return TCL_ERROR;
  }

  rc = sqlite3_config(aOpt[i].iValue);
  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
  return TCL_OK;
}

int Sqlitetest_mutex_Init(Tcl_Interp *interp){
  static struct {
    char *zName;
    Tcl_ObjCmdProc *xProc;
  } aCmd[] = {
    { "sqlite3_shutdown",        (Tcl_ObjCmdProc*)test_shutdown },
    { "sqlite3_initialize",      (Tcl_ObjCmdProc*)test_initialize },
    { "sqlite3_config",          (Tcl_ObjCmdProc*)test_config },

    { "install_mutex_counters",  (Tcl_ObjCmdProc*)test_install_mutex_counters },
    { "read_mutex_counters",     (Tcl_ObjCmdProc*)test_read_mutex_counters },
    { "clear_mutex_counters",    (Tcl_ObjCmdProc*)test_clear_mutex_counters },
  };
  int i;
  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  }
  memset(&g, 0, sizeof(g));
  return SQLITE_OK;
}

Changes to src/vdbeapi.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code use to implement APIs that are part of the
** VDBE.
**
** $Id: vdbeapi.c,v 1.132 2008/05/16 15:24:58 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
** The following structure contains pointers to the end points of a







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code use to implement APIs that are part of the
** VDBE.
**
** $Id: vdbeapi.c,v 1.133 2008/06/18 17:09:10 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
** The following structure contains pointers to the end points of a
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

/*
** Add vdbe p to the end of the statement lru list. It is assumed that
** p is not already part of the list when this is called. The lru list
** is protected by the SQLITE_MUTEX_STATIC_LRU mutex.
*/
static void stmtLruAdd(Vdbe *p){
  sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));

  if( p->pLruPrev || p->pLruNext || sqlite3LruStatements.pFirst==p ){
    sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
    return;
  }

  assert( stmtLruCheck() );

  if( !sqlite3LruStatements.pFirst ){
    assert( !sqlite3LruStatements.pLast );
    sqlite3LruStatements.pFirst = p;
    sqlite3LruStatements.pLast = p;
  }else{
    assert( !sqlite3LruStatements.pLast->pLruNext );
    p->pLruPrev = sqlite3LruStatements.pLast;
    sqlite3LruStatements.pLast->pLruNext = p;
    sqlite3LruStatements.pLast = p;
  }

  assert( stmtLruCheck() );

  sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
}

/*
** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is already held, remove
** statement p from the least-recently-used statement list. If the 
** statement is not currently part of the list, this call is a no-op.
*/







|


|


















|







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

/*
** Add vdbe p to the end of the statement lru list. It is assumed that
** p is not already part of the list when this is called. The lru list
** is protected by the SQLITE_MUTEX_STATIC_LRU mutex.
*/
static void stmtLruAdd(Vdbe *p){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));

  if( p->pLruPrev || p->pLruNext || sqlite3LruStatements.pFirst==p ){
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
    return;
  }

  assert( stmtLruCheck() );

  if( !sqlite3LruStatements.pFirst ){
    assert( !sqlite3LruStatements.pLast );
    sqlite3LruStatements.pFirst = p;
    sqlite3LruStatements.pLast = p;
  }else{
    assert( !sqlite3LruStatements.pLast->pLruNext );
    p->pLruPrev = sqlite3LruStatements.pLast;
    sqlite3LruStatements.pLast->pLruNext = p;
    sqlite3LruStatements.pLast = p;
  }

  assert( stmtLruCheck() );

  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
}

/*
** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is already held, remove
** statement p from the least-recently-used statement list. If the 
** statement is not currently part of the list, this call is a no-op.
*/
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

/*
** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is not held, remove
** statement p from the least-recently-used statement list. If the 
** statement is not currently part of the list, this call is a no-op.
*/
static void stmtLruRemove(Vdbe *p){
  sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
  stmtLruRemoveNomutex(p);
  sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
}

/*
** Try to release n bytes of memory by freeing buffers associated 
** with the memory registers of currently unused vdbes.
*/
int sqlite3VdbeReleaseMemory(int n){
  Vdbe *p;
  Vdbe *pNext;
  int nFree = 0;

  sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
  for(p=sqlite3LruStatements.pFirst; p && nFree<n; p=pNext){
    pNext = p->pLruNext;

    /* For each statement handle in the lru list, attempt to obtain the
    ** associated database mutex. If it cannot be obtained, continue
    ** to the next statement handle. It is not possible to block on
    ** the database mutex - that could cause deadlock.
    */
    if( SQLITE_OK==sqlite3_mutex_try(p->db->mutex) ){
      nFree += sqlite3VdbeReleaseBuffers(p);
      stmtLruRemoveNomutex(p);
      sqlite3_mutex_leave(p->db->mutex);
    }
  }
  sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));

  return nFree;
}

/*
** Call sqlite3Reprepare() on the statement. Remove it from the
** lru list before doing so, as Reprepare() will free all the







|

|











|














|







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

/*
** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is not held, remove
** statement p from the least-recently-used statement list. If the 
** statement is not currently part of the list, this call is a no-op.
*/
static void stmtLruRemove(Vdbe *p){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
  stmtLruRemoveNomutex(p);
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
}

/*
** Try to release n bytes of memory by freeing buffers associated 
** with the memory registers of currently unused vdbes.
*/
int sqlite3VdbeReleaseMemory(int n){
  Vdbe *p;
  Vdbe *pNext;
  int nFree = 0;

  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
  for(p=sqlite3LruStatements.pFirst; p && nFree<n; p=pNext){
    pNext = p->pLruNext;

    /* For each statement handle in the lru list, attempt to obtain the
    ** associated database mutex. If it cannot be obtained, continue
    ** to the next statement handle. It is not possible to block on
    ** the database mutex - that could cause deadlock.
    */
    if( SQLITE_OK==sqlite3_mutex_try(p->db->mutex) ){
      nFree += sqlite3VdbeReleaseBuffers(p);
      stmtLruRemoveNomutex(p);
      sqlite3_mutex_leave(p->db->mutex);
    }
  }
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));

  return nFree;
}

/*
** Call sqlite3Reprepare() on the statement. Remove it from the
** lru list before doing so, as Reprepare() will free all the
Changes to test/mutex1.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2008 June 17
#
# 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: mutex1.test,v 1.1 2008/06/18 09:45:56 danielk1977 Exp $

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

proc mutex_counters {varname} {
  upvar $varname var
  set var(total) 0











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2008 June 17
#
# 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: mutex1.test,v 1.2 2008/06/18 17:09:10 danielk1977 Exp $

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

proc mutex_counters {varname} {
  upvar $varname var
  set var(total) 0
71
72
73
74
75
76
77



78






































79

80
81
82
83
84
85
86
} {SQLITE_OK}

do_test mutex1-1.9 {
  mutex_counters counters
  list $counters(total) $counters(static_master)
} {0 0}











































do_test mutex1-X {

  sqlite3_shutdown
  clear_mutex_counters
  install_mutex_counters 0
} {SQLITE_OK}

finish_test








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

>







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
} {SQLITE_OK}

do_test mutex1-1.9 {
  mutex_counters counters
  list $counters(total) $counters(static_master)
} {0 0}

#-------------------------------------------------------------------------
# Tests mutex1-2.* test the three thread-safety related modes that
# can be selected using sqlite3_config:
#
#   * Serialized mode,
#   * Multi-threaded mode,
#   * Single-threaded mode.
#

foreach {mode mutexes} {
  singlethread {}
  multithread  {fast static_master static_mem static_prng}
  serialized   {fast recursive static_master static_mem static_prng}
} {
  do_test mutex1.2.$mode.1 {
    catch {db close}
    sqlite3_shutdown
    sqlite3_config $mode
  } SQLITE_OK

  do_test mutex1.2.$mode.2 {
    clear_mutex_counters
    sqlite3 db test.db
    catchsql { CREATE TABLE abc(a, b, c) }
    db eval {
      INSERT INTO abc VALUES(1, 2, 3);
    }
  } {}

  do_test mutex1.2.$mode.3 {
    mutex_counters counters

    set res [list]
    foreach {key value} [array get counters] {
      if {$key ne "total" && $value > 0} {
        lappend res $key
      }
    }
    lsort $res
  } $mutexes
}

do_test mutex1-X {
  db close
  sqlite3_shutdown
  clear_mutex_counters
  install_mutex_counters 0
} {SQLITE_OK}

finish_test

Added test/mutex2.test.
















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# 2007 March 26
#
# 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 runs some other test files after calling sqlite3_config to
# set the thread-safety mode to SQLITE_CONFIG_SINGLETHREAD and
# SQLITE_CONFIG_MULTITHREAD (instead of the default SQLITE_CONFIG_SERIALIZED).
#
# $Id: mutex2.test,v 1.1 2008/06/18 17:09:10 danielk1977 Exp $

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

ifcapable {!pager_pragmas} {
  finish_test
  return
}

rename finish_test really_finish_test2
proc finish_test {} {}
set ISQUICK 1

rename do_test really_do_test
proc do_test {args} {
  set sc [concat really_do_test "mutex2-${::thread_mode}.[lindex $args 0]" \
      [lrange $args 1 end]]
  eval $sc
}

foreach ::thread_mode {singlethread multithread} {
  do_test mutex2-$::thread_mode.0 {
    catch {db close}
    sqlite3_shutdown
    sqlite3_config $::thread_mode
  } SQLITE_OK

  source $testdir/delete.test
  source $testdir/delete2.test
  source $testdir/insert.test
  source $testdir/rollback.test
  source $testdir/select1.test
  source $testdir/select2.test
  source $testdir/trans.test
  source $testdir/update.test
  source $testdir/vacuum.test
  source $testdir/types.test
  source $testdir/types2.test
  source $testdir/types3.test

  #source $testdir/malloc.test
  #source $testdir/ioerr.test
}

do_test mutex2-X {
  catch {db close}
  sqlite3_shutdown
  sqlite3_config serialized
} SQLITE_OK

rename finish_test ""
rename really_finish_test2 finish_test
rename do_test ""
rename really_do_test do_test
finish_test

Changes to test/quick.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
#    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 runs all tests.
#
# $Id: quick.test,v 1.78 2008/04/19 20:34:19 drh Exp $

proc lshift {lvar} {
  upvar $lvar l
  set ret [lindex $l 0]
  set l [lrange $l 1 end]
  return $ret
}








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
#    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 runs all tests.
#
# $Id: quick.test,v 1.79 2008/06/18 17:09:10 danielk1977 Exp $

proc lshift {lvar} {
  upvar $lvar l
  set ret [lindex $l 0]
  set l [lrange $l 1 end]
  return $ret
}
60
61
62
63
64
65
66

67
68
69
70
71
72
73
  malloc.test
  malloc2.test
  malloc3.test
  malloc4.test
  memleak.test
  misc7.test
  misuse.test

  onefile.test
  quick.test
  soak.test
  speed1.test
  speed1p.test
  speed2.test
  speed3.test







>







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  malloc.test
  malloc2.test
  malloc3.test
  malloc4.test
  memleak.test
  misc7.test
  misuse.test
  mutex2.test
  onefile.test
  quick.test
  soak.test
  speed1.test
  speed1p.test
  speed2.test
  speed3.test
Changes to test/veryquick.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
#    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 runs all tests.
#
# $Id: veryquick.test,v 1.3 2008/04/19 20:34:19 drh Exp $

proc lshift {lvar} {
  upvar $lvar l
  set ret [lindex $l 0]
  set l [lrange $l 1 end]
  return $ret
}








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
#    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 runs all tests.
#
# $Id: veryquick.test,v 1.4 2008/06/18 17:09:10 danielk1977 Exp $

proc lshift {lvar} {
  upvar $lvar l
  set ret [lindex $l 0]
  set l [lrange $l 1 end]
  return $ret
}
82
83
84
85
86
87
88

89
90
91
92
93
94
95
  mallocD.test
  mallocE.test
  mallocF.test
  mallocG.test
  memleak.test
  misc7.test
  misuse.test

  onefile.test
  quick.test
  soak.test
  speed1.test
  speed1p.test
  speed2.test
  speed3.test







>







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  mallocD.test
  mallocE.test
  mallocF.test
  mallocG.test
  memleak.test
  misc7.test
  misuse.test
  mutex2.test
  onefile.test
  quick.test
  soak.test
  speed1.test
  speed1p.test
  speed2.test
  speed3.test