/ Check-in [c7b9d50d]
Login

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

Overview
Comment:Include the ThreadData structure in internal malloc() testing. Also fixes for revealed bugs. (CVS 2974)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c7b9d50d0a975912776aaa2b870308652f77e1e6
User & Date: danielk1977 2006-01-18 18:22:43
Context
2006-01-18
18:33
Omit thread2.test if memory-management is enabled at compile time. (CVS 2975) check-in: df91f685 user: danielk1977 tags: trunk
18:22
Include the ThreadData structure in internal malloc() testing. Also fixes for revealed bugs. (CVS 2974) check-in: c7b9d50d user: danielk1977 tags: trunk
17:25
Modify the sqlite3OsInMutex os-layer interface to take a single parameter to distinguish between mutexes held by the current thread and mutexes held by any thread. Part of the fix for ticket #1630. (CVS 2973) check-in: e1ad9df1 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

1778
1779
1780
1781
1782
1783
1784

1785




1786
1787
1788
1789
1790
1791
1792
....
1797
1798
1799
1800
1801
1802
1803

1804




1805
1806
1807
1808
1809
1810
1811
    }
    sqlite3OsLeaveMutex();
  }

  pTsd = pthread_getspecific(key);
  if( allocateFlag>0 ){
    if( pTsd==0 ){

      pTsd = sqlite3OsMalloc(sizeof(zeroData));




      if( pTsd ){
        *pTsd = zeroData;
        pthread_setspecific(key, pTsd);
        TSD_COUNTER(+1);
      }
    }
  }else if( pTsd!=0 && allocateFlag<0 
................................................................................
    pTsd = 0;
  }
  return pTsd;
#else
  static ThreadData *pTsd = 0;
  if( allocateFlag>0 ){
    if( pTsd==0 ){

      pTsd = sqlite3OsMalloc( sizeof(zeroData) );




      if( pTsd ){
        *pTsd = zeroData;
        TSD_COUNTER(+1);
      }
    }
  }else if( pTsd!=0 && allocateFlag<0
            && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){







>
|
>
>
>
>







 







>
|
>
>
>
>







1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
....
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
    }
    sqlite3OsLeaveMutex();
  }

  pTsd = pthread_getspecific(key);
  if( allocateFlag>0 ){
    if( pTsd==0 ){
      if( !sqlite3TestMallocFail() ){
        pTsd = sqlite3OsMalloc(sizeof(zeroData));
      }
#ifdef SQLITE_MEMDEBUG
      sqlite3_isFail = 0;
#endif
      if( pTsd ){
        *pTsd = zeroData;
        pthread_setspecific(key, pTsd);
        TSD_COUNTER(+1);
      }
    }
  }else if( pTsd!=0 && allocateFlag<0 
................................................................................
    pTsd = 0;
  }
  return pTsd;
#else
  static ThreadData *pTsd = 0;
  if( allocateFlag>0 ){
    if( pTsd==0 ){
      if( !sqlite3TestMallocFail() ){
        pTsd = sqlite3OsMalloc( sizeof(zeroData) );
      }
#ifdef SQLITE_MEMDEBUG
      sqlite3_isFail = 0;
#endif
      if( pTsd ){
        *pTsd = zeroData;
        TSD_COUNTER(+1);
      }
    }
  }else if( pTsd!=0 && allocateFlag<0
            && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
1995
1996
1997
1998
1999
2000
2001

2002
2003
2004
2005
2006
2007
2008
** 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.244 2006/01/18 17:25:46 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
................................................................................
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to 
  ** malloc() must have already been made by this thread before it gets
  ** to this point. This means the ThreadData must have been allocated already
  ** so that ThreadData.nAlloc can be set.
  */
  ThreadData *pTsd = sqlite3ThreadData();

  assert( pTsd && pTsd->nAlloc );
#endif

  switch( pPager->state ){
    case PAGER_RESERVED:
    case PAGER_SYNCED: 
    case PAGER_EXCLUSIVE: {







|







 







>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
** 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.245 2006/01/18 18:22:43 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
................................................................................
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to 
  ** malloc() must have already been made by this thread before it gets
  ** to this point. This means the ThreadData must have been allocated already
  ** so that ThreadData.nAlloc can be set.
  */
  ThreadData *pTsd = sqlite3ThreadData();
  assert( pPager );
  assert( pTsd && pTsd->nAlloc );
#endif

  switch( pPager->state ){
    case PAGER_RESERVED:
    case PAGER_SYNCED: 
    case PAGER_EXCLUSIVE: {

Changes to src/prepare.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
516
517
518
519
520
521
522



523
524
525
526
527
528
529
...
550
551
552
553
554
555
556

557
558
559
560
561
562
563
...
566
567
568
569
570
571
572

573

574
575
576
577
578
579
580
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.26 2006/01/18 16:51:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** Fill the InitData structure with an error message that indicates
................................................................................
      return SQLITE_LOCKED;
    }
  }
  
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.pTsd = sqlite3ThreadData();



  sParse.pTsd->nRef++;
  sqlite3RunParser(&sParse, zSql, &zErrMsg);

  if( sqlite3MallocFailed() ){
    sParse.rc = SQLITE_NOMEM;
  }
  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
................................................................................
      sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC);
      sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC);
      sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC);
    }
  } 
#endif


  if( sqlite3SafetyOff(db) ){
    rc = SQLITE_MISUSE;
  }
  if( rc==SQLITE_OK ){
    *ppStmt = (sqlite3_stmt*)sParse.pVdbe;
  }else if( sParse.pVdbe ){
    sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
................................................................................
  if( zErrMsg ){
    sqlite3Error(db, rc, "%s", zErrMsg);
    sqliteFree(zErrMsg);
  }else{
    sqlite3Error(db, rc, 0);
  }


  sParse.pTsd->nRef--;

  rc = sqlite3ApiExit(db, rc);
  sqlite3ReleaseThreadData();
  return rc;
}

#ifndef SQLITE_OMIT_UTF16
/*







|







 







>
>
>







 







>







 







>
|
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
...
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.27 2006/01/18 18:22:43 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** Fill the InitData structure with an error message that indicates
................................................................................
      return SQLITE_LOCKED;
    }
  }
  
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.pTsd = sqlite3ThreadData();
  if( !sParse.pTsd ){
    goto prepare_out;
  }
  sParse.pTsd->nRef++;
  sqlite3RunParser(&sParse, zSql, &zErrMsg);

  if( sqlite3MallocFailed() ){
    sParse.rc = SQLITE_NOMEM;
  }
  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
................................................................................
      sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC);
      sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC);
      sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC);
    }
  } 
#endif

prepare_out:
  if( sqlite3SafetyOff(db) ){
    rc = SQLITE_MISUSE;
  }
  if( rc==SQLITE_OK ){
    *ppStmt = (sqlite3_stmt*)sParse.pVdbe;
  }else if( sParse.pVdbe ){
    sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
................................................................................
  if( zErrMsg ){
    sqlite3Error(db, rc, "%s", zErrMsg);
    sqliteFree(zErrMsg);
  }else{
    sqlite3Error(db, rc, 0);
  }

  if( sParse.pTsd ){
    sParse.pTsd->nRef--;
  }
  rc = sqlite3ApiExit(db, rc);
  sqlite3ReleaseThreadData();
  return rc;
}

#ifndef SQLITE_OMIT_UTF16
/*

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1755
1756
1757
1758
1759
1760
1761

1762

1763
1764
1765
1766
1767
1768
1769
1770
1771
**    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.474 2006/01/18 16:51:35 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Extra interface definitions for those who need them
*/
................................................................................
#else
  #define sqlite3TableLock(v,w,x,y,z)
#endif

#ifdef SQLITE_MEMDEBUG
  void sqlite3MallocDisallow();
  void sqlite3MallocAllow();

#else

  #define sqlite3MallocDisallow()
  #define sqlite3MallocAllow()
#endif

#ifdef SQLITE_SSE
#include "sseInt.h"
#endif

#endif







|







 







>

>









7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
**    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.475 2006/01/18 18:22:43 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Extra interface definitions for those who need them
*/
................................................................................
#else
  #define sqlite3TableLock(v,w,x,y,z)
#endif

#ifdef SQLITE_MEMDEBUG
  void sqlite3MallocDisallow();
  void sqlite3MallocAllow();
  int sqlite3TestMallocFail();
#else
  #define sqlite3TestMallocFail() 0
  #define sqlite3MallocDisallow()
  #define sqlite3MallocAllow()
#endif

#ifdef SQLITE_SSE
#include "sseInt.h"
#endif

#endif

Changes to src/test1.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.196 2006/01/18 16:51:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  extern int sqlite3OutstandingMallocs(Tcl_Interp *interp);

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( objc==2 ){
    ThreadData *pTd = sqlite3ThreadData();
    const char *zArg = Tcl_GetString(objv[1]);
    if( 0==strcmp(zArg, "-bytes") ){
      Tcl_SetObjResult(interp, Tcl_NewIntObj(pTd->nAlloc));
    }else if( 0==strcmp(zArg, "-maxbytes") ){
      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_nMaxAlloc));
    }else if( 0==strcmp(zArg, "-clearmaxbytes") ){
      sqlite3_nMaxAlloc = pTd->nAlloc;







|







 







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.197 2006/01/18 18:22:43 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  extern int sqlite3OutstandingMallocs(Tcl_Interp *interp);

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  if( objc==2 ){
    ThreadData const *pTd = sqlite3ThreadDataReadOnly();
    const char *zArg = Tcl_GetString(objv[1]);
    if( 0==strcmp(zArg, "-bytes") ){
      Tcl_SetObjResult(interp, Tcl_NewIntObj(pTd->nAlloc));
    }else if( 0==strcmp(zArg, "-maxbytes") ){
      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_nMaxAlloc));
    }else if( 0==strcmp(zArg, "-clearmaxbytes") ){
      sqlite3_nMaxAlloc = pTd->nAlloc;

Changes to src/util.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
68
69
70
71
72
73
74


75

76
77
78
79
80
81
82
...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
...
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
...
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
...
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
...
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
...
484
485
486
487
488
489
490



491
492
493
494
495
496
497
498
499
500
501
...
531
532
533
534
535
536
537
538
539

540
541
542
543
544
545
546
547


548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
...
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
....
1318
1319
1320
1321
1322
1323
1324
1325




1326
1327
1328
1329
1330
1331
1332
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.177 2006/01/18 17:25:46 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <stdarg.h>
#include <ctype.h>

/*
................................................................................

#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
/*
** Set the soft heap-size limit for the current thread. Passing a negative
** value indicates no limit.
*/
void sqlite3_soft_heap_limit(int n){


  sqlite3ThreadData()->nSoftHeapLimit = n;

  sqlite3ReleaseThreadData();
}

/*
** Release memory held by SQLite instances created by the current thread.
*/
int sqlite3_release_memory(int n){
................................................................................
const char *sqlite3_zFile = 0;    /* Filename to associate debug info with */
int sqlite3_iLine = 0;            /* Line number for debug info */

/*
** Check for a simulated memory allocation failure.  Return true if
** the failure should be simulated.  Return false to proceed as normal.
*/
static int failMalloc(){
  ThreadData *pTsd = sqlite3ThreadData();
  if( sqlite3_isFail ){
    return 1;
  }
  if( sqlite3_iMallocFail>=0 ){
    sqlite3_iMallocFail--;
    if( sqlite3_iMallocFail==0 ){
      sqlite3_iMallocFail = sqlite3_iMallocReset;
................................................................................

#if SQLITE_MEMDEBUG>1
/*
** The argument points to an Os level allocation. Link it into the threads list
** of allocations.
*/
static void linkAlloc(void *p){
  ThreadData *pTsd = sqlite3ThreadData();
  void **pp = (void **)p;
  pp[0] = 0;
  pp[1] = sqlite3_pFirst;
  if( sqlite3_pFirst ){
    ((void **)sqlite3_pFirst)[0] = p;
  }
  sqlite3_pFirst = p;
................................................................................

/*
** The argument points to an Os level allocation. Unlinke it from the threads
** list of allocations.
*/
static void unlinkAlloc(void *p)
{
  ThreadData *pTsd = sqlite3ThreadData();
  void **pp = (void **)p;
  if( p==sqlite3_pFirst ){
    assert(!pp[0]);
    assert(!pp[1] || ((void **)(pp[1]))[0]==p);
    sqlite3_pFirst = pp[1];
    if( sqlite3_pFirst ){
      ((void **)sqlite3_pFirst)[0] = 0;
................................................................................
*/
static void relinkAlloc(void *p)
{
  void **pp = (void **)p;
  if( pp[0] ){
    ((void **)(pp[0]))[1] = p;
  }else{
    ThreadData *pTsd = sqlite3ThreadData();
    sqlite3_pFirst = p;
  }
  if( pp[1] ){
    ((void **)(pp[1]))[0] = p;
  }
}
#else
................................................................................
** Todo: We could have a version of this function that outputs to stdout, 
** to debug memory leaks when Tcl is not available.
*/
#ifdef TCLSH
#include <tcl.h>
int sqlite3OutstandingMallocs(Tcl_Interp *interp){
  void *p;
  ThreadData *pTsd = sqlite3ThreadData();
  Tcl_Obj *pRes = Tcl_NewObj();
  Tcl_IncrRefCount(pRes);

  for(p=sqlite3_pFirst; p; p=((void **)p)[1]){
    Tcl_Obj *pEntry = Tcl_NewObj();
    Tcl_Obj *pStack = Tcl_NewObj();
    char *z;
................................................................................
#endif

/*
** This is the test layer's wrapper around sqlite3OsMalloc().
*/
static void * OSMALLOC(int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  ThreadData *pTsd = sqlite3ThreadData();
  sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, pTsd->nAlloc);
#endif
  assert( !sqlite3_mallocDisallowed );
  if( !failMalloc() ){
    u32 *p;
    p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD);
    assert(p);
    sqlite3_nMalloc++;
    applyGuards(p);
    linkAlloc(p);
    return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
................................................................................

/*
** This is the test layer's wrapper around sqlite3OsRealloc().
*/
static void * OSREALLOC(void *pRealloc, int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  ThreadData *pTsd = sqlite3ThreadData();



  sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, pTsd->nAlloc);
#endif
  assert( !sqlite3_mallocDisallowed );
  if( !failMalloc() ){
    u32 *p = (u32 *)getOsPointer(pRealloc);
    checkGuards(p);
    p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD);
    applyGuards(p);
    relinkAlloc(p);
    return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
  }
................................................................................
** called to try to avoid this. No indication of whether or not this is
** successful is returned to the caller.
**
** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is
** a no-op
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
static void handleSoftLimit(int n){
  ThreadData *pTsd = sqlite3ThreadData();

  pTsd->nAlloc += n;
  assert( pTsd->nAlloc>=0 );
  if( n>0 && pTsd->nSoftHeapLimit>0 ){
    while( pTsd->nAlloc>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) );
  }else if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){
    sqlite3ReleaseThreadData();
  }
}


#else
#define handleSoftLimit(x)
#endif

/*
** Allocate and return N bytes of uninitialised memory by calling
** sqlite3OsMalloc(). If the Malloc() call fails, attempt to free memory 
** by calling sqlite3_release_memory().
*/
void *sqlite3MallocRaw(int n){
  void *p = 0;
  if( n>0 && !sqlite3MallocFailed() ){
    handleSoftLimit(n);
    while( !(p = OSMALLOC(n)) && sqlite3_release_memory(n) );
    if( !p ){
      /* If the allocation failed, call handleSoftLimit() again, this time
      ** with the additive inverse of the argument passed to 
      ** handleSoftLimit() above. This is so the ThreadData.nAlloc variable is
      ** still correct after a malloc() failure. 
      */
................................................................................
    return 0;
  }

  if( !p ){
    return sqlite3Malloc(n);
  }else{
    void *np = 0;
    handleSoftLimit(n - OSSIZEOF(p));
    while( !(np = OSREALLOC(p, n)) && sqlite3_release_memory(n) );
    if( !np ){
      /* If the allocation failed, call handleSoftLimit() again, this time
      ** with the additive inverse of the argument passed to 
      ** handleSoftLimit() above. This is so the ThreadData.nAlloc variable is
      ** still correct after a malloc() failure. 
      */
      handleSoftLimit(OSSIZEOF(p) - n);
      sqlite3FailedMalloc();
      OSMALLOC_FAILED();

    }
    return np;
  }
}

/*
** Free the memory pointed to by p. p must be either a NULL pointer or a 
................................................................................
}
#endif

/*
** Return a pointer to the ThreadData associated with the calling thread.
*/
ThreadData *sqlite3ThreadData(){
  return (ThreadData*)sqlite3OsThreadSpecificData(1);




}

/*
** Return a pointer to the ThreadData associated with the calling thread.
** If no ThreadData has been allocated to this thread yet, return a pointer
** to a substitute ThreadData structure that is all zeros. 
*/







|







 







>
>
|
>







 







|
<







 







<







 







<







 







<







 







<







 







|



|







 







>
>
>



|







 







|

>
|
|
|
|
|
|
|
|
>
>

|









|
<







 







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







 







|
>
>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
...
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
...
314
315
316
317
318
319
320

321
322
323
324
325
326
327
...
329
330
331
332
333
334
335

336
337
338
339
340
341
342
...
361
362
363
364
365
366
367

368
369
370
371
372
373
374
...
392
393
394
395
396
397
398

399
400
401
402
403
404
405
...
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
...
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
...
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
...
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
....
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.178 2006/01/18 18:22:43 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <stdarg.h>
#include <ctype.h>

/*
................................................................................

#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
/*
** Set the soft heap-size limit for the current thread. Passing a negative
** value indicates no limit.
*/
void sqlite3_soft_heap_limit(int n){
  ThreadData *pTd = sqlite3ThreadData();
  if( pTd ){
    pTd->nSoftHeapLimit = n;
  }
  sqlite3ReleaseThreadData();
}

/*
** Release memory held by SQLite instances created by the current thread.
*/
int sqlite3_release_memory(int n){
................................................................................
const char *sqlite3_zFile = 0;    /* Filename to associate debug info with */
int sqlite3_iLine = 0;            /* Line number for debug info */

/*
** Check for a simulated memory allocation failure.  Return true if
** the failure should be simulated.  Return false to proceed as normal.
*/
int sqlite3TestMallocFail(){

  if( sqlite3_isFail ){
    return 1;
  }
  if( sqlite3_iMallocFail>=0 ){
    sqlite3_iMallocFail--;
    if( sqlite3_iMallocFail==0 ){
      sqlite3_iMallocFail = sqlite3_iMallocReset;
................................................................................

#if SQLITE_MEMDEBUG>1
/*
** The argument points to an Os level allocation. Link it into the threads list
** of allocations.
*/
static void linkAlloc(void *p){

  void **pp = (void **)p;
  pp[0] = 0;
  pp[1] = sqlite3_pFirst;
  if( sqlite3_pFirst ){
    ((void **)sqlite3_pFirst)[0] = p;
  }
  sqlite3_pFirst = p;
................................................................................

/*
** The argument points to an Os level allocation. Unlinke it from the threads
** list of allocations.
*/
static void unlinkAlloc(void *p)
{

  void **pp = (void **)p;
  if( p==sqlite3_pFirst ){
    assert(!pp[0]);
    assert(!pp[1] || ((void **)(pp[1]))[0]==p);
    sqlite3_pFirst = pp[1];
    if( sqlite3_pFirst ){
      ((void **)sqlite3_pFirst)[0] = 0;
................................................................................
*/
static void relinkAlloc(void *p)
{
  void **pp = (void **)p;
  if( pp[0] ){
    ((void **)(pp[0]))[1] = p;
  }else{

    sqlite3_pFirst = p;
  }
  if( pp[1] ){
    ((void **)(pp[1]))[0] = p;
  }
}
#else
................................................................................
** Todo: We could have a version of this function that outputs to stdout, 
** to debug memory leaks when Tcl is not available.
*/
#ifdef TCLSH
#include <tcl.h>
int sqlite3OutstandingMallocs(Tcl_Interp *interp){
  void *p;

  Tcl_Obj *pRes = Tcl_NewObj();
  Tcl_IncrRefCount(pRes);

  for(p=sqlite3_pFirst; p; p=((void **)p)[1]){
    Tcl_Obj *pEntry = Tcl_NewObj();
    Tcl_Obj *pStack = Tcl_NewObj();
    char *z;
................................................................................
#endif

/*
** This is the test layer's wrapper around sqlite3OsMalloc().
*/
static void * OSMALLOC(int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  ThreadData const *pTsd = sqlite3ThreadDataReadOnly();
  sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, pTsd->nAlloc);
#endif
  assert( !sqlite3_mallocDisallowed );
  if( !sqlite3TestMallocFail() ){
    u32 *p;
    p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD);
    assert(p);
    sqlite3_nMalloc++;
    applyGuards(p);
    linkAlloc(p);
    return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
................................................................................

/*
** This is the test layer's wrapper around sqlite3OsRealloc().
*/
static void * OSREALLOC(void *pRealloc, int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  ThreadData *pTsd = sqlite3ThreadData();
  if( !pTsd ){
    return 0;
  }
  sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, pTsd->nAlloc);
#endif
  assert( !sqlite3_mallocDisallowed );
  if( !sqlite3TestMallocFail() ){
    u32 *p = (u32 *)getOsPointer(pRealloc);
    checkGuards(p);
    p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD);
    applyGuards(p);
    relinkAlloc(p);
    return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
  }
................................................................................
** called to try to avoid this. No indication of whether or not this is
** successful is returned to the caller.
**
** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is
** a no-op
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
static int handleSoftLimit(int n){
  ThreadData *pTsd = sqlite3ThreadData();
  if( pTsd ){
    pTsd->nAlloc += n;
    assert( pTsd->nAlloc>=0 );
    if( n>0 && pTsd->nSoftHeapLimit>0 ){
      while( pTsd->nAlloc>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) );
    }else if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){
      sqlite3ReleaseThreadData();
    }
  }
  return (pTsd ? 0 : 1);
}
#else
#define handleSoftLimit(x) 0
#endif

/*
** Allocate and return N bytes of uninitialised memory by calling
** sqlite3OsMalloc(). If the Malloc() call fails, attempt to free memory 
** by calling sqlite3_release_memory().
*/
void *sqlite3MallocRaw(int n){
  void *p = 0;
  if( n>0 && !sqlite3MallocFailed() && !handleSoftLimit(n) ){

    while( !(p = OSMALLOC(n)) && sqlite3_release_memory(n) );
    if( !p ){
      /* If the allocation failed, call handleSoftLimit() again, this time
      ** with the additive inverse of the argument passed to 
      ** handleSoftLimit() above. This is so the ThreadData.nAlloc variable is
      ** still correct after a malloc() failure. 
      */
................................................................................
    return 0;
  }

  if( !p ){
    return sqlite3Malloc(n);
  }else{
    void *np = 0;
    if( !handleSoftLimit(n - OSSIZEOF(p)) ){
      while( !(np = OSREALLOC(p, n)) && sqlite3_release_memory(n) );
      if( !np ){
        /* If the allocation failed, call handleSoftLimit() again, this time
        ** with the additive inverse of the argument passed to 
        ** handleSoftLimit() above. This is so the ThreadData.nAlloc variable is
        ** still correct after a malloc() failure. 
        */
        handleSoftLimit(OSSIZEOF(p) - n);
        sqlite3FailedMalloc();
        OSMALLOC_FAILED();
      }
    }
    return np;
  }
}

/*
** Free the memory pointed to by p. p must be either a NULL pointer or a 
................................................................................
}
#endif

/*
** Return a pointer to the ThreadData associated with the calling thread.
*/
ThreadData *sqlite3ThreadData(){
  ThreadData *p = (ThreadData*)sqlite3OsThreadSpecificData(1);
  if( !p ){
    sqlite3FailedMalloc();
  }
  return p;
}

/*
** Return a pointer to the ThreadData associated with the calling thread.
** If no ThreadData has been allocated to this thread yet, return a pointer
** to a substitute ThreadData structure that is all zeros. 
*/

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
404
405
406
407
408
409
410



411
412
413
414
415
416
417
....
4611
4612
4613
4614
4615
4616
4617

4618

4619
4620
4621
4622
4623
4624
4625
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.532 2006/01/18 16:51:36 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
#endif
#ifndef NDEBUG
  Mem *pStackLimit;
#endif
  ThreadData *pTsd = sqlite3ThreadData();




  if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
  pTsd->nRef++;
  assert( db->magic==SQLITE_MAGIC_BUSY );
  pTos = p->pTos;
  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
................................................................................
    p->rc = rc;
    rc = SQLITE_ERROR;
  }else{
    rc = SQLITE_DONE;
  }
  sqlite3VdbeHalt(p);
  p->pTos = pTos;

  pTsd->nRef--;

  return rc;

  /* Jump to here if a malloc() fails.  It's hard to get a malloc()
  ** to fail on a modern VM computer, so this code is untested.
  */
no_mem:
  sqlite3SetString(&p->zErrMsg, "out of memory", (char*)0);







|







 







>
>
>







 







>
|
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
....
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.533 2006/01/18 18:22:43 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
#endif
#ifndef NDEBUG
  Mem *pStackLimit;
#endif
  ThreadData *pTsd = sqlite3ThreadData();
  if( !pTsd ){
    goto no_mem;
  }

  if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
  pTsd->nRef++;
  assert( db->magic==SQLITE_MAGIC_BUSY );
  pTos = p->pTos;
  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
................................................................................
    p->rc = rc;
    rc = SQLITE_ERROR;
  }else{
    rc = SQLITE_DONE;
  }
  sqlite3VdbeHalt(p);
  p->pTos = pTos;
  if( pTsd ){
    pTsd->nRef--;
  }
  return rc;

  /* Jump to here if a malloc() fails.  It's hard to get a malloc()
  ** to fail on a modern VM computer, so this code is untested.
  */
no_mem:
  sqlite3SetString(&p->zErrMsg, "out of memory", (char*)0);

Changes to src/vdbeapi.c.

238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
    assert( p->aOp[p->nOp-1].p3!=0 );
    assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC );
    db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3, elapseTime);
  }
#endif

  sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
  return sqlite3ApiExit(p->db, rc);

}

/*
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
*/
void *sqlite3_user_data(sqlite3_context *p){







|
>







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    assert( p->aOp[p->nOp-1].p3!=0 );
    assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC );
    db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3, elapseTime);
  }
#endif

  sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
  p->rc = sqlite3ApiExit(p->db, p->rc);
  return rc;
}

/*
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
*/
void *sqlite3_user_data(sqlite3_context *p){