/ Check-in [e1ad9df1]
Login

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

Overview
Comment: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)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e1ad9df1cf46287f2a7789275e98d28e05880e17
User & Date: drh 2006-01-18 17:25:46
Context
2006-01-18
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
16:51
Use a global variable protected by a mutex instead of thread-specific-data to record malloc() failures. (CVS 2972) check-in: ac090f2a user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os.h.

   287    287   int sqlite3OsSyncDirectory(const char*);
   288    288   int sqlite3OsTempFileName(char*);
   289    289   int sqlite3OsRandomSeed(char*);
   290    290   int sqlite3OsSleep(int ms);
   291    291   int sqlite3OsCurrentTime(double*);
   292    292   void sqlite3OsEnterMutex(void);
   293    293   void sqlite3OsLeaveMutex(void);
   294         -int sqlite3OsInMutex(void);
          294  +int sqlite3OsInMutex(int);
   295    295   ThreadData *sqlite3OsThreadSpecificData(int);
   296    296   void *sqlite3OsMalloc(int);
   297    297   void *sqlite3OsRealloc(void *, int);
   298    298   void sqlite3OsFree(void *);
   299    299   int sqlite3OsAllocationSize(void *);
   300    300   
   301    301   /*

Changes to src/os_unix.c.

   474    474   }
   475    475   #endif /* SQLITE_UNIX_THREADS */
   476    476   
   477    477   /*
   478    478   ** Release a lockInfo structure previously allocated by findLockInfo().
   479    479   */
   480    480   static void releaseLockInfo(struct lockInfo *pLock){
   481         -  assert( sqlite3OsInMutex() );
          481  +  assert( sqlite3OsInMutex(1) );
   482    482     pLock->nRef--;
   483    483     if( pLock->nRef==0 ){
   484    484       sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);
   485    485       sqliteFree(pLock);
   486    486     }
   487    487   }
   488    488   
   489    489   /*
   490    490   ** Release a openCnt structure previously allocated by findLockInfo().
   491    491   */
   492    492   static void releaseOpenCnt(struct openCnt *pOpen){
   493         -  assert( sqlite3OsInMutex() );
          493  +  assert( sqlite3OsInMutex(1) );
   494    494     pOpen->nRef--;
   495    495     if( pOpen->nRef==0 ){
   496    496       sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);
   497    497       free(pOpen->aPending);
   498    498       sqliteFree(pOpen);
   499    499     }
   500    500   }
................................................................................
   516    516     struct openKey key2;
   517    517     struct stat statbuf;
   518    518     struct lockInfo *pLock;
   519    519     struct openCnt *pOpen;
   520    520     rc = fstat(fd, &statbuf);
   521    521     if( rc!=0 ) return 1;
   522    522   
   523         -  assert( sqlite3OsInMutex() );
          523  +  assert( sqlite3OsInMutex(1) );
   524    524     memset(&key1, 0, sizeof(key1));
   525    525     key1.dev = statbuf.st_dev;
   526    526     key1.ino = statbuf.st_ino;
   527    527   #ifdef SQLITE_UNIX_THREADS
   528    528     if( threadsOverrideEachOthersLocks<0 ){
   529    529       testThreadLockingBehavior(fd);
   530    530     }
................................................................................
  1676   1676   ** The following pair of routine implement mutual exclusion for
  1677   1677   ** multi-threaded processes.  Only a single thread is allowed to
  1678   1678   ** executed code that is surrounded by EnterMutex() and LeaveMutex().
  1679   1679   **
  1680   1680   ** SQLite uses only a single Mutex.  There is not much critical
  1681   1681   ** code and what little there is executes quickly and without blocking.
  1682   1682   **
  1683         -** This mutex is not recursive.
         1683  +** As of version 3.3.2, this mutex must be recursive.
  1684   1684   */
  1685   1685   void sqlite3UnixEnterMutex(){
  1686   1686   #ifdef SQLITE_UNIX_THREADS
  1687   1687     pthread_mutex_lock(&mutex1);
  1688   1688     if( inMutex==0 ){
  1689   1689       pthread_mutex_lock(&mutex2);
  1690   1690       mutexOwner = pthread_self();
................................................................................
  1705   1705     pthread_mutex_unlock(&mutex1);
  1706   1706   #else
  1707   1707     inMutex--;
  1708   1708   #endif
  1709   1709   }
  1710   1710   
  1711   1711   /*
  1712         -** Return TRUE if we are currently within the mutex and FALSE if not.
         1712  +** Return TRUE if the mutex is currently held.
         1713  +**
         1714  +** If the thisThreadOnly parameter is true, return true only if the
         1715  +** calling thread holds the mutex.  If the parameter is false, return
         1716  +** true if any thread holds the mutex.
  1713   1717   */
  1714         -int sqlite3UnixInMutex(){
         1718  +int sqlite3UnixInMutex(int thisThreadOnly){
  1715   1719   #ifdef SQLITE_UNIX_THREADS
  1716         -  return inMutex && pthread_equal(mutexOwner, pthread_self());
         1720  +  return inMutex>0 && 
         1721  +           (thisThreadOnly==0 || pthread_equal(mutexOwner, pthread_self()));
  1717   1722   #else
  1718         -  return inMutex;
         1723  +  return inMutex>0;
  1719   1724   #endif
  1720   1725   }
  1721   1726   
  1722   1727   /*
  1723   1728   ** Remember the number of thread-specific-data blocks allocated.
  1724   1729   ** Use this to verify that we are not leaking thread-specific-data.
  1725   1730   ** Ticket #1601

Changes to src/os_win.c.

  1064   1064   }
  1065   1065   
  1066   1066   /*
  1067   1067   ** Static variables used for thread synchronization
  1068   1068   */
  1069   1069   static int inMutex = 0;
  1070   1070   #ifdef SQLITE_W32_THREADS
  1071         -  static HANDLE mutexOwner;
         1071  +  static DWORD mutexOwner;
  1072   1072     static CRITICAL_SECTION cs;
  1073   1073   #endif
  1074   1074   
  1075   1075   /*
  1076         -** The following pair of routine implement mutual exclusion for
         1076  +** The following pair of routines implement mutual exclusion for
  1077   1077   ** multi-threaded processes.  Only a single thread is allowed to
  1078   1078   ** executed code that is surrounded by EnterMutex() and LeaveMutex().
  1079   1079   **
  1080   1080   ** SQLite uses only a single Mutex.  There is not much critical
  1081   1081   ** code and what little there is executes quickly and without blocking.
         1082  +**
         1083  +** Version 3.3.1 and earlier used a simple mutex.  Beginning with
         1084  +** version 3.3.2, a recursive mutex is required.
  1082   1085   */
  1083   1086   void sqlite3WinEnterMutex(){
  1084   1087   #ifdef SQLITE_W32_THREADS
  1085   1088     static int isInit = 0;
  1086   1089     while( !isInit ){
  1087   1090       static long lock = 0;
  1088   1091       if( InterlockedIncrement(&lock)==1 ){
................................................................................
  1089   1092         InitializeCriticalSection(&cs);
  1090   1093         isInit = 1;
  1091   1094       }else{
  1092   1095         Sleep(1);
  1093   1096       }
  1094   1097     }
  1095   1098     EnterCriticalSection(&cs);
  1096         -  mutexOwner = GetCurrentThread();
         1099  +  mutexOwner = GetCurrentThreadId();
  1097   1100   #endif
  1098   1101     inMutex++;
  1099   1102   }
  1100   1103   void sqlite3WinLeaveMutex(){
  1101   1104     assert( inMutex );
  1102   1105     inMutex--;
  1103   1106   #ifdef SQLITE_W32_THREADS
         1107  +  assert( mutexOwner==GetCurrentThreadId() );
  1104   1108     LeaveCriticalSection(&cs);
  1105   1109   #endif
  1106   1110   }
  1107   1111   
  1108   1112   /*
  1109         -** Return TRUE if we are currently within the mutex and FALSE if not.
         1113  +** Return TRUE if the mutex is currently held.
         1114  +**
         1115  +** If the thisThreadOnly parameter is true, return true if and only if the
         1116  +** calling thread holds the mutex.  If the parameter is false, return
         1117  +** true if any thread holds the mutex.
  1110   1118   */
  1111         -int sqlite3WinInMutex(){
         1119  +int sqlite3WinInMutex(int thisThreadOnly){
  1112   1120   #ifdef SQLITE_W32_THREADS
  1113         -  return inMutex && mutexOwner==GetCurrentThread();
         1121  +  return inMutex>0 && (thisThreadOnly==0 || mutexOwner==GetCurrentThreadId());
  1114   1122   #else
  1115         -  return inMutex;
         1123  +  return inMutex>0;
  1116   1124   #endif
  1117   1125   }
  1118   1126   
  1119   1127   
  1120   1128   /*
  1121   1129   ** The following variable, if set to a non-zero value, becomes the result
  1122   1130   ** returned from sqlite3OsCurrentTime().  This is used for testing.

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.243 2006/01/18 16:51:35 danielk1977 Exp $
           21  +** @(#) $Id: pager.c,v 1.244 2006/01/18 17:25:46 drh Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   #include "os.h"
    26     26   #include "pager.h"
    27     27   #include <assert.h>
    28     28   #include <string.h>
................................................................................
  2433   2433     int i;
  2434   2434   
  2435   2435     /* If the the global mutex is held, this subroutine becomes a
  2436   2436     ** o-op; zero bytes of memory are freed.  This is because
  2437   2437     ** some of the code invoked by this function may also
  2438   2438     ** try to obtain the mutex, resulting in a deadlock.
  2439   2439     */
  2440         -  if( sqlite3OsInMutex() ){
         2440  +  if( sqlite3OsInMutex(0) ){
  2441   2441       return 0;
  2442   2442     }
  2443   2443   
  2444   2444     /* Outermost loop runs for at most two iterations. First iteration we
  2445   2445     ** try to find memory that can be released without calling fsync(). Second
  2446   2446     ** iteration (which only runs if the first failed to free nReq bytes of
  2447   2447     ** memory) is permitted to call fsync(). This is of course much more 

Changes to src/util.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Utility functions used throughout sqlite.
    13     13   **
    14     14   ** This file contains functions for allocating memory, comparing
    15     15   ** strings, and stuff like that.
    16     16   **
    17         -** $Id: util.c,v 1.176 2006/01/18 16:51:36 danielk1977 Exp $
           17  +** $Id: util.c,v 1.177 2006/01/18 17:25:46 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "os.h"
    21     21   #include <stdarg.h>
    22     22   #include <ctype.h>
    23     23   
    24     24   /*
................................................................................
  1369   1369   }
  1370   1370   
  1371   1371   /* 
  1372   1372   ** Return true is a malloc has failed in this thread since the last call
  1373   1373   ** to sqlite3ApiExit(), or false otherwise.
  1374   1374   */
  1375   1375   int sqlite3MallocFailed(){
  1376         -  return (mallocHasFailed && sqlite3OsInMutex());
         1376  +  return (mallocHasFailed && sqlite3OsInMutex(1));
  1377   1377   }
  1378   1378   
  1379   1379   /* 
  1380   1380   ** Set the "malloc has failed" condition to true for this thread.
  1381   1381   */
  1382   1382   void sqlite3FailedMalloc(){
  1383   1383     sqlite3OsEnterMutex();