Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch begin-concurrent-pnu-mutexfree-shmlock Excluding Merge-Ins
This is equivalent to a diff from f2083ee4 to 186b376e
2018-12-18
| ||
17:47 | Merge latest begin-concurrent changes into this branch. (check-in: a93ca38b user: dan tags: begin-concurrent-pnu) | |
2018-12-10
| ||
16:53 | Merge latest mutexfree-shmlock changes into this branch. (Leaf check-in: 186b376e user: dan tags: begin-concurrent-pnu-mutexfree-shmlock) | |
16:52 | Make SQLITE_MFS_NSHARD a compile time setting. (check-in: b9a74151 user: dan tags: mutexfree-shmlock) | |
15:58 | Merge the latest version of mutexfree-shmlock with this branch. (check-in: 6007abfe user: dan tags: begin-concurrent-pnu-mutexfree-shmlock) | |
2018-12-06
| ||
20:26 | Add the mutexfree-shmlock experiment to the begin-concurrent-pnu branch. (check-in: 3aead209 user: dan tags: begin-concurrent-pnu-mutexfree-shmlock) | |
03:13 | Merge fixes from trunk. (check-in: f2083ee4 user: drh tags: begin-concurrent-pnu) | |
02:08 | Merge bug fixes from trunk. (check-in: 1e13aaa2 user: drh tags: begin-concurrent) | |
00:08 | Merge ALTER TABLE and sqlite3_normalized_sql() bug fixes from trunk. (check-in: 3793e5d5 user: drh tags: begin-concurrent-pnu) | |
Changes to src/main.c.
︙ | |||
1992 1993 1994 1995 1996 1997 1998 | 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 | - | (void)SQLITE_MISUSE_BKPT; return 0; } #endif sqlite3_mutex_enter(db->mutex); pOld = db->pTraceArg; db->mTrace = xTrace ? SQLITE_TRACE_LEGACY : 0; |
︙ | |||
2017 2018 2019 2020 2021 2022 2023 | 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 | - - - | return SQLITE_MISUSE_BKPT; } #endif sqlite3_mutex_enter(db->mutex); if( mTrace==0 ) xTrace = 0; if( xTrace==0 ) mTrace = 0; db->mTrace = mTrace; |
︙ |
Changes to src/os_unix.c.
︙ | |||
42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | + + + + + + + + + + | ** * Locking primitives for the proxy uber-locking-method. (MacOSX only) ** * Definitions of sqlite3_vfs objects for all locking methods ** plus implementations of sqlite3_os_init() and sqlite3_os_end(). */ #include "sqliteInt.h" #if SQLITE_OS_UNIX /* This file is used on unix only */ /* Turn this feature on in all builds for now */ #define SQLITE_MUTEXFREE_SHMLOCK 1 #define SQLITE_MFS_EXCLUSIVE 255 #ifndef SQLITE_MFS_NSHARD # define SQLITE_MFS_NSHARD 8 #endif #if SQLITE_MFS_NSHARD<1 # error "SQLITE_MFS_NSHARD must be greater than 0" #endif /* ** There are various methods for file locking used for concurrency ** control: ** ** 1. POSIX locking (the default), ** 2. No locking, ** 3. Dot-file locking, |
︙ | |||
4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 | 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | int nRef; /* Number of unixShm objects pointing to this */ unixShm *pFirst; /* All unixShm objects pointing to this */ #ifdef SQLITE_DEBUG u8 exclMask; /* Mask of exclusive locks held */ u8 sharedMask; /* Mask of shared locks held */ u8 nextShmId; /* Next available unixShm.id value */ #endif #ifdef SQLITE_MUTEXFREE_SHMLOCK /* In unix-excl mode, if SQLITE_MUTEXFREE_SHMLOCK is defined, all locks ** are stored in the following 64-bit value. There are in total 8 ** shm-locking slots, each of which are assigned 8-bits from the 64-bit ** value. The least-significant 8 bits correspond to shm-locking slot ** 0, and so on. ** ** If the 8-bits corresponding to a shm-locking locking slot are set to ** 0xFF, then a write-lock is held on the slot. Or, if they are set to ** a non-zero value smaller than 0xFF, then they represent the total ** number of read-locks held on the slot. There is no way to distinguish ** between a write-lock and 255 read-locks. */ struct LockingSlot { u32 nLock; u64 aPadding[7]; } aMFSlot[3 + SQLITE_MFS_NSHARD*5]; #endif }; /* ** Atomic CAS primitive used in multi-process mode. Equivalent to: ** ** int unixCompareAndSwap(u32 *ptr, u32 oldval, u32 newval){ ** if( *ptr==oldval ){ ** *ptr = newval; ** return 1; ** } ** return 0; ** } */ #define unixCompareAndSwap(ptr,oldval,newval) \ __sync_bool_compare_and_swap(ptr,oldval,newval) /* ** Structure used internally by this VFS to record the state of an ** open shared memory connection. ** ** The following fields are initialized when this object is created and ** are read-only thereafter: |
︙ | |||
4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 | 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 | + + + | struct unixShm { unixShmNode *pShmNode; /* The underlying unixShmNode object */ unixShm *pNext; /* Next unixShm with the same unixShmNode */ u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */ u8 id; /* Id of this connection within its unixShmNode */ u16 sharedMask; /* Mask of shared locks held */ u16 exclMask; /* Mask of exclusive locks held */ #ifdef SQLITE_MUTEXFREE_SHMLOCK u8 aMFCurrent[8]; /* Current slot used for each shared lock */ #endif }; /* ** Constants used for locking */ #define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ #define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ |
︙ | |||
4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 | 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | *pp = 0; } if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; sqlite3_mutex_leave(pShmNode->pShmMutex); return rc; } #ifdef SQLITE_MUTEXFREE_SHMLOCK static int unixMutexFreeShmlock( unixFile *pFd, /* Database file holding the shared memory */ int ofst, /* First lock to acquire or release */ int n, /* Number of locks to acquire or release */ int flags /* What to do with the lock */ ){ struct LockMapEntry { int iFirst; int nSlot; } aMap[9] = { { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3+0*SQLITE_MFS_NSHARD, SQLITE_MFS_NSHARD }, { 3+1*SQLITE_MFS_NSHARD, SQLITE_MFS_NSHARD }, { 3+2*SQLITE_MFS_NSHARD, SQLITE_MFS_NSHARD }, { 3+3*SQLITE_MFS_NSHARD, SQLITE_MFS_NSHARD }, { 3+4*SQLITE_MFS_NSHARD, SQLITE_MFS_NSHARD }, { 3+5*SQLITE_MFS_NSHARD, 0 }, }; unixShm *p = pFd->pShm; /* The shared memory being locked */ unixShm *pX; /* For looping over all siblings */ unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */ int rc = SQLITE_OK; int iIncr; u16 mask; /* Mask of locks to take or release */ if( flags & SQLITE_SHM_SHARED ){ /* SHARED locks */ u32 iOld, iNew, *ptr; int iIncr = -1; if( (flags & SQLITE_SHM_UNLOCK)==0 ){ p->aMFCurrent[ofst] = (p->aMFCurrent[ofst] + 1) % aMap[ofst].nSlot; iIncr = 1; } ptr = &pShmNode->aMFSlot[aMap[ofst].iFirst + p->aMFCurrent[ofst]].nLock; do { iOld = *ptr; iNew = iOld + iIncr; if( iNew>SQLITE_MFS_EXCLUSIVE ){ return SQLITE_BUSY; } }while( 0==unixCompareAndSwap(ptr, iOld, iNew) ); }else{ /* EXCLUSIVE locks */ int iFirst = aMap[ofst].iFirst; int iLast = aMap[ofst+n].iFirst; int i; for(i=iFirst; i<iLast; i++){ u32 *ptr = &pShmNode->aMFSlot[i].nLock; if( flags & SQLITE_SHM_UNLOCK ){ assert( (*ptr)==SQLITE_MFS_EXCLUSIVE ); *ptr = 0; }else{ u32 iOld; do { iOld = *ptr; if( iOld>0 ){ while( i>iFirst ){ i--; pShmNode->aMFSlot[i].nLock = 0; } return SQLITE_BUSY; } }while( 0==unixCompareAndSwap(ptr, iOld, SQLITE_MFS_EXCLUSIVE) ); } } } return SQLITE_OK; } #else # define unixMutexFreeShmlock(a,b,c,d) SQLITE_OK #endif /* ** Change the lock state for a shared-memory segment. ** ** Note that the relationship between SHAREd and EXCLUSIVE locks is a little ** different here than in posix. In xShmLock(), one can go from unlocked ** to shared and back or from unlocked to exclusive and back. But one may ** not go from shared to exclusive or from exclusive to shared. |
︙ | |||
4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 | 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 | + + + + + + + + + + + + | assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); if( pDbFd->pInode->bProcessLock ){ return unixMutexFreeShmlock(pDbFd, ofst, n, flags); } mask = (1<<(ofst+n)) - (1<<ofst); assert( n>1 || mask==(1<<ofst) ); if( flags & SQLITE_SHM_LOCK ){ assert( !(flags&SQLITE_SHM_SHARED) || (p->sharedMask&mask)==0 ); assert( !(flags&SQLITE_SHM_EXCLUSIVE) || !(p->exclMask&mask) ); }else{ assert( !(flags&SQLITE_SHM_SHARED) || (p->sharedMask&mask)==mask ); assert( !(flags&SQLITE_SHM_EXCLUSIVE) || (p->exclMask&mask)==mask ); } sqlite3_mutex_enter(pShmNode->pShmMutex); if( flags & SQLITE_SHM_UNLOCK ){ u16 allMask = 0; /* Mask of locks held by siblings */ /* See if any siblings hold this same lock */ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ if( pX==p ) continue; |
︙ | |||
4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 | 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 | + + + + | ** All loads and stores begun before the barrier must complete before ** any load or store begun after the barrier. */ static void unixShmBarrier( sqlite3_file *fd /* Database file holding the shared memory */ ){ UNUSED_PARAMETER(fd); #ifdef SQLITE_MUTEXFREE_SHMLOCK __sync_synchronize(); #else sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ assert( fd->pMethods->xLock==nolockLock || unixFileMutexNotheld((unixFile*)fd) ); unixEnterMutex(); /* Also mutex, for redundancy */ unixLeaveMutex(); #endif } /* ** Close a connection to shared-memory. Delete the underlying ** storage if deleteFlag is true. ** ** If there is no shared memory associated with the connection then this |
︙ |
Changes to src/sqlite.h.in.
︙ | |||
2987 2988 2989 2990 2991 2992 2993 | 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 | - - - + + + | ** ^The callback function registered by sqlite3_profile() is invoked ** as each SQL statement finishes. ^The profile callback contains ** the original statement text and an estimate of wall-clock time ** of how long that statement took to run. ^The profile callback ** time is in units of nanoseconds, however the current implementation ** is only capable of millisecond resolution so the six least significant ** digits in the time are meaningless. Future versions of SQLite |
︙ |
Changes to src/test_superlock.c.
︙ | |||
37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | + + | ** An instance of the following structure is allocated for each active ** superlock. The opaque handle returned by sqlite3demo_superlock() is ** actually a pointer to an instance of this structure. */ struct Superlock { sqlite3 *db; /* Database handle used to lock db */ int bWal; /* True if db is a WAL database */ int bRecoveryLocked; /* True if WAL RECOVERY lock is held */ int bReaderLocked; /* True if WAL READER locks are held */ }; typedef struct Superlock Superlock; /* ** The pCtx pointer passed to this function is actually a pointer to a ** SuperlockBusy structure. Invoke the busy-handler function encapsulated ** by the structure and return the result. |
︙ | |||
103 104 105 106 107 108 109 | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | - + + + + + + + - - + + + + + + + | } /* ** Obtain the extra locks on the database file required for WAL databases. ** Invoke the supplied busy-handler as required. */ static int superlockWalLock( |
︙ | |||
228 229 230 231 232 233 234 | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | - + | ** to drop the WAL read and write locks currently held. Otherwise, the ** new WAL locks may conflict with the old. */ if( rc==SQLITE_OK ){ if( SQLITE_OK==(rc = superlockIsWal(pLock)) && pLock->bWal ){ rc = sqlite3_exec(pLock->db, "COMMIT", 0, 0, 0); if( rc==SQLITE_OK ){ |
︙ |
Changes to src/test_vfs.c.
︙ | |||
1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 | 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | return TCL_OK; bad_args: Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-fullshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?"); return TCL_ERROR; } extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); extern const char *sqlite3ErrName(int); /* ** tclcmd: vfs_shmlock DB DBNAME (shared|exclusive) (lock|unlock) OFFSET N */ static int SQLITE_TCLAPI test_vfs_shmlock( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ const char *azArg1[] = {"shared", "exclusive", 0}; const char *azArg2[] = {"lock", "unlock", 0}; sqlite3 *db = 0; int rc = SQLITE_OK; const char *zDbname = 0; int iArg1 = 0; int iArg2 = 0; int iOffset = 0; int n = 0; sqlite3_file *pFd; if( objc!=7 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME (shared|exclusive) (lock|unlock) OFFSET N" ); return TCL_ERROR; } zDbname = Tcl_GetString(objv[2]); if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || Tcl_GetIndexFromObj(interp, objv[3], azArg1, "ARG", 0, &iArg1) || Tcl_GetIndexFromObj(interp, objv[4], azArg2, "ARG", 0, &iArg2) || Tcl_GetIntFromObj(interp, objv[5], &iOffset) || Tcl_GetIntFromObj(interp, objv[6], &n) ){ return TCL_ERROR; } sqlite3_file_control(db, zDbname, SQLITE_FCNTL_FILE_POINTER, (void*)&pFd); if( pFd==0 ){ return TCL_ERROR; } rc = pFd->pMethods->xShmLock(pFd, iOffset, n, (iArg1==0 ? SQLITE_SHM_SHARED : SQLITE_SHM_EXCLUSIVE) | (iArg2==0 ? SQLITE_SHM_LOCK : SQLITE_SHM_UNLOCK) ); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); return TCL_OK; } int Sqlitetestvfs_Init(Tcl_Interp *interp){ Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0); Tcl_CreateObjCommand(interp, "vfs_shmlock", test_vfs_shmlock, 0, 0); return TCL_OK; } #endif |
Changes to src/wal.c.
︙ | |||
2793 2794 2795 2796 2797 2798 2799 | 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 | - - - + + + - - - + + + - - - - - - - | ** checkpoint need not have completed for this to cause problems. */ volatile WalCkptInfo *pInfo = walCkptInfo(pWal); assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 ); assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame ); |
︙ |
Changes to test/lock_common.tcl.
︙ | |||
11 12 13 14 15 16 17 | 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 | - + - - + - + + + + | # This file contains code used by several different test scripts. The # code in this file allows testfixture to control another process (or # processes) to test locking. # proc do_multiclient_test {varname script} { |
︙ |
Changes to test/permutations.test.
︙ | |||
601 602 603 604 605 606 607 608 609 610 611 612 613 614 | 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 | + + + + + + + + + + | Run some tests using the "test_onefile.c" demo } -initialize { set ::G(perm:sqlite3_args) [list -vfs fs] } -files { conflict.test insert.test insert2.test insert3.test rollback.test select1.test select2.test select3.test } # Run some tests using the "unix-excl" VFS. # test_suite "unix-excl" -description { Run some tests using the "unix-excl" VFS } -initialize { set ::G(perm:sqlite3_args) [list -vfs unix-excl] } -files { shmlock.test } # Run some tests using UTF-16 databases. # test_suite "utf16" -description { Run tests using UTF-16 databases } -presql { pragma encoding = 'UTF-16' |
︙ |
Added test/shmlock.test.