/ Changes On Branch mutexInitCmpSwap
Login

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

Changes In Branch mutexInitCmpSwap Excluding Merge-Ins

This is equivalent to a diff from 10a214fdb3 to 6b85f8cd4d

2015-09-23
19:17
Take care that the number of reserved bits per page is consistent between the source and destination databases when doing the back-copy on a VACUUM. check-in: 5b61b72f54 user: drh tags: trunk
16:35
Merge updates from trunk. check-in: 0a75ebd23e user: mistachkin tags: mutexInitIsInitReCheck
16:24
Simplify thread-safety of mutex initialization. check-in: da0587c522 user: mistachkin tags: mutexInitSimpleCmpSwap
15:54
Merge updates from trunk. Closed-Leaf check-in: 6b85f8cd4d user: mistachkin tags: mutexInitCmpSwap
11:59
Capture AFL-generated fuzz tests for json1.c into the test/fuzzdata4.db file. check-in: 10a214fdb3 user: drh tags: trunk
01:10
Do not allow a comma at the end of a JSON array or object. check-in: 7c7a3f3e9b user: drh tags: trunk
2015-09-13
18:45
Experimental changes to avoid recusrively calling xMutexInit. check-in: c9400ff167 user: mistachkin tags: mutexInitCmpSwap

Changes to src/global.c.

   170    170      SQLITE_USE_URI,            /* bOpenUri */
   171    171      SQLITE_ALLOW_COVERING_INDEX_SCAN,   /* bUseCis */
   172    172      0x7ffffffe,                /* mxStrlen */
   173    173      0,                         /* neverCorrupt */
   174    174      128,                       /* szLookaside */
   175    175      500,                       /* nLookaside */
   176    176      {0,0,0,0,0,0,0,0},         /* m */
          177  +   (void*)0,                  /* pMutex */
   177    178      {0,0,0,0,0,0,0,0,0},       /* mutex */
   178    179      {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
   179    180      (void*)0,                  /* pHeap */
   180    181      0,                         /* nHeap */
   181    182      0, 0,                      /* mnHeap, mxHeap */
   182    183      SQLITE_DEFAULT_MMAP_SIZE,  /* szMmap */
   183    184      SQLITE_MAX_MMAP_SIZE,      /* mxMmap */

Changes to src/main.c.

   167    167     ** This operation is protected by the STATIC_MASTER mutex.  Note that
   168    168     ** MutexAlloc() is called for a static mutex prior to initializing the
   169    169     ** malloc subsystem - this implies that the allocation of a static
   170    170     ** mutex must not require support from the malloc subsystem.
   171    171     */
   172    172     MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
   173    173     sqlite3_mutex_enter(pMaster);
   174         -  sqlite3GlobalConfig.isMutexInit = 1;
          174  +  if( sqlite3GlobalConfig.isInit ){
          175  +    assert( sqlite3GlobalConfig.isMutexInit );
          176  +    assert( sqlite3GlobalConfig.isMallocInit );
          177  +    sqlite3_mutex_leave(pMaster);
          178  +    return SQLITE_OK;
          179  +  }
          180  +  sqlite3GlobalConfig.isMutexInit = 1; /* possibly redundant */
   175    181     if( !sqlite3GlobalConfig.isMallocInit ){
   176    182       rc = sqlite3MallocInit();
   177    183     }
   178    184     if( rc==SQLITE_OK ){
   179    185       sqlite3GlobalConfig.isMallocInit = 1;
   180    186       if( !sqlite3GlobalConfig.pInitMutex ){
   181    187         sqlite3GlobalConfig.pInitMutex =
................................................................................
   325    331   #endif
   326    332     }
   327    333     if( sqlite3GlobalConfig.isMutexInit ){
   328    334       sqlite3MutexEnd();
   329    335       sqlite3GlobalConfig.isMutexInit = 0;
   330    336     }
   331    337   
          338  +  /*
          339  +  ** Force the state of the mutex subsystem to be completely reset now, even
          340  +  ** if the configured xMutexEnd(), if any, failed.  This is not thread-safe.
          341  +  ** This is necessary even if the xMutexInit() was never called, due to the
          342  +  ** possiblity of this state being changed via SQLITE_CONFIG_MUTEX.  After
          343  +  ** this point, the application must enable any custom mutex implementation
          344  +  ** again via SQLITE_CONFIG_MUTEX, if necessary.
          345  +  */
          346  +  sqlite3GlobalConfig.pMutex = 0;
          347  +  memset(&sqlite3GlobalConfig.mutex, 0, sizeof(sqlite3_mutex_methods));
          348  +
   332    349     return SQLITE_OK;
   333    350   }
   334    351   
   335    352   /*
   336    353   ** This API allows applications to modify the global configuration of
   337    354   ** the SQLite library at run-time.
   338    355   **
................................................................................
   380    397         sqlite3GlobalConfig.bCoreMutex = 1;  /* Enable mutex on core */
   381    398         sqlite3GlobalConfig.bFullMutex = 1;  /* Enable mutex on connections */
   382    399         break;
   383    400       }
   384    401   #endif
   385    402   #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */
   386    403       case SQLITE_CONFIG_MUTEX: {
   387         -      /* Specify an alternative mutex implementation */
   388         -      sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*);
          404  +      /* Atomically compare-and-swap the mutex implementation pointer to
          405  +       * help prevent a race condition with sqlite3MutexInit(). */
          406  +      if( sqlite3CompareAndSwap((void * volatile *)&sqlite3GlobalConfig.pMutex,
          407  +                                0, &sqlite3GlobalConfig.mutex)==0 ){
          408  +        /* Specify an alternative mutex implementation */
          409  +        sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*);
          410  +      }else{
          411  +        rc = SQLITE_ERROR;
          412  +      }
   389    413         break;
   390    414       }
   391    415   #endif
   392    416   #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-14450-37597 */
   393    417       case SQLITE_CONFIG_GETMUTEX: {
   394    418         /* Retrieve the current mutex implementation */
   395    419         *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex;

Changes to src/mutex.c.

    22     22   ** allocate a mutex while the system is uninitialized.
    23     23   */
    24     24   static SQLITE_WSD int mutexIsInit = 0;
    25     25   #endif /* SQLITE_DEBUG && !defined(SQLITE_MUTEX_OMIT) */
    26     26   
    27     27   
    28     28   #ifndef SQLITE_MUTEX_OMIT
           29  +/*
           30  +** This structure is for use by mutexIsInvalid() only.  It represents an
           31  +** invalid mutex implementation (i.e. one where all the function pointers
           32  +** are null).
           33  +*/
           34  +static const sqlite3_mutex_methods mutexNullMethods = {
           35  +  0, /* xMutexInit */
           36  +  0, /* xMutexEnd */
           37  +  0, /* xMutexAlloc */
           38  +  0, /* xMutexFree */
           39  +  0, /* xMutexEnter */
           40  +  0, /* xMutexTry */
           41  +  0, /* xMutexLeave */
           42  +  0, /* xMutexHeld */
           43  +  0  /* xMutexNotheld */
           44  +};
           45  +
           46  +/*
           47  +** Returns non-zero if the currently configured mutex implemention is
           48  +** invalid (i.e. all of its function pointers are null).
           49  +*/
           50  +static int mutexIsInvalid(void){
           51  +  return memcmp(&sqlite3GlobalConfig.mutex, &mutexNullMethods,
           52  +                sizeof(sqlite3_mutex_methods))==0;
           53  +}
           54  +
           55  +/*
           56  +** Copies a mutex implementation.  Both arguments must point to valid
           57  +** memory.
           58  +*/
           59  +static void mutexCopy(
           60  +  sqlite3_mutex_methods *pTo,
           61  +  sqlite3_mutex_methods const *pFrom
           62  +){
           63  +  pTo->xMutexInit = pFrom->xMutexInit;
           64  +  pTo->xMutexEnd = pFrom->xMutexEnd;
           65  +  pTo->xMutexFree = pFrom->xMutexFree;
           66  +  pTo->xMutexEnter = pFrom->xMutexEnter;
           67  +  pTo->xMutexTry = pFrom->xMutexTry;
           68  +  pTo->xMutexLeave = pFrom->xMutexLeave;
           69  +  pTo->xMutexHeld = pFrom->xMutexHeld;
           70  +  pTo->xMutexNotheld = pFrom->xMutexNotheld;
           71  +  pTo->xMutexAlloc = pFrom->xMutexAlloc;
           72  +}
           73  +
    29     74   /*
    30     75   ** Initialize the mutex system.
    31     76   */
    32     77   int sqlite3MutexInit(void){ 
    33         -  int rc = SQLITE_OK;
    34         -  if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
    35         -    /* If the xMutexAlloc method has not been set, then the user did not
    36         -    ** install a mutex implementation via sqlite3_config() prior to 
    37         -    ** sqlite3_initialize() being called. This block copies pointers to
    38         -    ** the default implementation into the sqlite3GlobalConfig structure.
           78  +  static int initPending = 0;
           79  +  int rc;
           80  +  if( sqlite3CompareAndSwap((void * volatile *)&sqlite3GlobalConfig.pMutex,
           81  +                   0, &sqlite3GlobalConfig.mutex)==0 || mutexIsInvalid() ){
           82  +    /* If the mutex implementation pointer has not been set, then the user
           83  +    ** did not install a mutex implementation via sqlite3_config() prior to
           84  +    ** sqlite3_initialize() being called.  This block copies the pointers
           85  +    ** for the default implementation into the sqlite3GlobalConfig structure.
    39     86       */
    40     87       sqlite3_mutex_methods const *pFrom;
    41         -    sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
    42     88   
    43     89       if( sqlite3GlobalConfig.bCoreMutex ){
    44     90         pFrom = sqlite3DefaultMutex();
    45     91       }else{
    46     92         pFrom = sqlite3NoopMutex();
    47     93       }
    48         -    pTo->xMutexInit = pFrom->xMutexInit;
    49         -    pTo->xMutexEnd = pFrom->xMutexEnd;
    50         -    pTo->xMutexFree = pFrom->xMutexFree;
    51         -    pTo->xMutexEnter = pFrom->xMutexEnter;
    52         -    pTo->xMutexTry = pFrom->xMutexTry;
    53         -    pTo->xMutexLeave = pFrom->xMutexLeave;
    54         -    pTo->xMutexHeld = pFrom->xMutexHeld;
    55         -    pTo->xMutexNotheld = pFrom->xMutexNotheld;
           94  +    mutexCopy(&sqlite3GlobalConfig.mutex, pFrom);
    56     95       sqlite3MemoryBarrier();
    57         -    pTo->xMutexAlloc = pFrom->xMutexAlloc;
    58     96     }
    59         -  assert( sqlite3GlobalConfig.mutex.xMutexInit );
    60         -  rc = sqlite3GlobalConfig.mutex.xMutexInit();
           97  +  if( !initPending ){
           98  +    assert( sqlite3GlobalConfig.mutex.xMutexInit );
           99  +    initPending = 1;
          100  +    rc = sqlite3GlobalConfig.mutex.xMutexInit();
          101  +    initPending = 0;
          102  +  }
    61    103   
    62    104   #ifdef SQLITE_DEBUG
    63    105     GLOBAL(int, mutexIsInit) = 1;
    64    106   #endif
    65    107   
    66    108     return rc;
    67    109   }

Changes to src/mutex_noop.c.

    24     24   ** If compiled with SQLITE_DEBUG, then additional logic is inserted
    25     25   ** that does error checking on mutexes to make sure they are being
    26     26   ** called correctly.
    27     27   */
    28     28   #include "sqliteInt.h"
    29     29   
    30     30   #ifndef SQLITE_MUTEX_OMIT
           31  +
           32  +/*
           33  +** Try to provide an atomic compare-and-swap operation on a void pointer,
           34  +** needed for initialization only.
           35  +*/
           36  +void *sqlite3NoopCompareAndSwap(
           37  +  void *volatile *pCurVal,
           38  +  void *cmpVal,
           39  +  void *swapVal
           40  +){
           41  +  /*
           42  +  ** This platform may not have a way to perform an atomic compare-and-swap
           43  +  ** operation; therefore, use the fallback algorithm.
           44  +  **
           45  +  ** WARNING: This code is almost certainly not thread-safe.
           46  +  */
           47  +  void *oldVal = *pCurVal;
           48  +  if( oldVal==cmpVal ){
           49  +    *pCurVal = swapVal;
           50  +  }
           51  +  return oldVal;
           52  +}
    31     53   
    32     54   #ifndef SQLITE_DEBUG
    33     55   /*
    34     56   ** Stub routines for all mutex methods.
    35     57   **
    36     58   ** This routines provide no mutual exclusion or error checking.
    37     59   */

Changes to src/mutex_unix.c.

    86     86   void sqlite3MemoryBarrier(void){
    87     87   #if defined(SQLITE_MEMORY_BARRIER)
    88     88     SQLITE_MEMORY_BARRIER;
    89     89   #elif defined(__GNUC__) && GCC_VERSION>=4001000
    90     90     __sync_synchronize();
    91     91   #endif
    92     92   }
           93  +
           94  +/*
           95  +** Try to provide an atomic compare-and-swap operation on a void pointer,
           96  +** needed for initialization only.
           97  +*/
           98  +void *sqlite3CompareAndSwap(
           99  +  void *volatile *pCurVal,
          100  +  void *cmpVal,
          101  +  void *swapVal
          102  +){
          103  +#if defined(SQLITE_COMPARE_AND_SWAP)
          104  +  return SQLITE_COMPARE_AND_SWAP(pCurVal, cmpVal, swapVal);
          105  +#elif defined(__GNUC__) && GCC_VERSION>=4001000 && SQLITE_PTRSIZE>4
          106  +  return (void *)__sync_val_compare_and_swap_8(
          107  +      (u64 volatile *)pCurVal, (u64)cmpVal, (u64)swapVal);
          108  +#elif defined(__GNUC__) && GCC_VERSION>=4001000
          109  +  return (void *)__sync_val_compare_and_swap_4(
          110  +      (u32 volatile *)pCurVal, (u32)cmpVal, (u32)swapVal);
          111  +#else
          112  +  /*
          113  +  ** This platform may not have a way to perform an atomic compare-and-swap
          114  +  ** operation; therefore, use the fallback algorithm.
          115  +  **
          116  +  ** WARNING: This code is almost certainly not thread-safe.
          117  +  */
          118  +  return sqlite3NoopCompareAndSwap(pCurVal, cmpVal, swapVal);
          119  +#endif
          120  +}
    93    121   
    94    122   /*
    95    123   ** Initialize and deinitialize the mutex subsystem.
    96    124   */
    97    125   static int pthreadMutexInit(void){ return SQLITE_OK; }
    98    126   static int pthreadMutexEnd(void){ return SQLITE_OK; }
    99    127   

Changes to src/mutex_w32.c.

    85     85     SQLITE_MEMORY_BARRIER;
    86     86   #elif defined(__GNUC__)
    87     87     __sync_synchronize();
    88     88   #else
    89     89     MemoryBarrier();
    90     90   #endif
    91     91   }
           92  +
           93  +/*
           94  +** Try to provide an atomic compare-and-swap operation on a void pointer,
           95  +** needed for initialization only.
           96  +*/
           97  +void *sqlite3CompareAndSwap(
           98  +  void * volatile *pCurVal,
           99  +  void *cmpVal,
          100  +  void *swapVal
          101  +){
          102  +#if defined(SQLITE_COMPARE_AND_SWAP)
          103  +  return SQLITE_COMPARE_AND_SWAP(pCurVal, cmpVal, swapVal);
          104  +#elif SQLITE_PTRSIZE>4
          105  +  return (void *)InterlockedCompareExchange64(
          106  +      (LONGLONG SQLITE_WIN32_VOLATILE *)pCurVal, (LONGLONG)swapVal,
          107  +      (LONGLONG)cmpVal);
          108  +#else
          109  +  return (void *)InterlockedCompareExchange(
          110  +      (LONG SQLITE_WIN32_VOLATILE *)pCurVal, (LONG)swapVal,
          111  +      (LONG)cmpVal);
          112  +#endif
          113  +}
    92    114   
    93    115   /*
    94    116   ** Initialize and deinitialize the mutex subsystem.
    95    117   */
    96    118   static sqlite3_mutex winMutex_staticMutexes[] = {
    97    119     SQLITE3_MUTEX_INITIALIZER,
    98    120     SQLITE3_MUTEX_INITIALIZER,

Changes to src/sqliteInt.h.

  2934   2934     int bOpenUri;                     /* True to interpret filenames as URIs */
  2935   2935     int bUseCis;                      /* Use covering indices for full-scans */
  2936   2936     int mxStrlen;                     /* Maximum string length */
  2937   2937     int neverCorrupt;                 /* Database is always well-formed */
  2938   2938     int szLookaside;                  /* Default lookaside buffer size */
  2939   2939     int nLookaside;                   /* Default lookaside buffer count */
  2940   2940     sqlite3_mem_methods m;            /* Low-level memory allocation interface */
         2941  +  sqlite3_mutex_methods *pMutex;    /* Address of mutex member or zero. */
  2941   2942     sqlite3_mutex_methods mutex;      /* Low-level mutex interface */
  2942   2943     sqlite3_pcache_methods2 pcache2;  /* Low-level page-cache interface */
  2943   2944     void *pHeap;                      /* Heap storage space */
  2944   2945     int nHeap;                        /* Size of pHeap[] */
  2945   2946     int mnReq, mxReq;                 /* Min and max heap requests sizes */
  2946   2947     sqlite3_int64 szMmap;             /* mmap() space per open file */
  2947   2948     sqlite3_int64 mxMmap;             /* Maximum value for szMmap */
................................................................................
  3185   3186   const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
  3186   3187   #endif
  3187   3188   
  3188   3189   
  3189   3190   #ifndef SQLITE_MUTEX_OMIT
  3190   3191     sqlite3_mutex_methods const *sqlite3DefaultMutex(void);
  3191   3192     sqlite3_mutex_methods const *sqlite3NoopMutex(void);
         3193  +  void *sqlite3NoopCompareAndSwap(void * volatile *, void *, void *);
  3192   3194     sqlite3_mutex *sqlite3MutexAlloc(int);
  3193   3195     int sqlite3MutexInit(void);
  3194   3196     int sqlite3MutexEnd(void);
  3195   3197   #endif
  3196   3198   #if !defined(SQLITE_MUTEX_OMIT) && !defined(SQLITE_MUTEX_NOOP)
  3197   3199     void sqlite3MemoryBarrier(void);
  3198   3200   #else
  3199   3201   # define sqlite3MemoryBarrier()
  3200   3202   #endif
         3203  +#if !defined(SQLITE_MUTEX_OMIT)
         3204  +# if !defined(SQLITE_MUTEX_NOOP)
         3205  +   void *sqlite3CompareAndSwap(void * volatile *, void *, void *);
         3206  +# else
         3207  +#  define sqlite3CompareAndSwap sqlite3NoopCompareAndSwap
         3208  +# endif
         3209  +#else
         3210  +# define sqlite3CompareAndSwap(x,y,z)
         3211  +#endif
  3201   3212   
  3202   3213   sqlite3_int64 sqlite3StatusValue(int);
  3203   3214   void sqlite3StatusUp(int, int);
  3204   3215   void sqlite3StatusDown(int, int);
  3205   3216   void sqlite3StatusSet(int, int);
  3206   3217   
  3207   3218   /* Access to mutexes used by sqlite3_status() */