/ Check-in [149a7082]
Login

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

Overview
Comment:Get the new xShmLock interface design working on os_win.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal-incr-ckpt
Files: files | file ages | folders
SHA1: 149a7082e266edf0dc25c23823a9e240f5285215
User & Date: drh 2010-05-31 16:10:12
Context
2010-05-31
16:17
Zero the checkpoint header as the last step of successful WAL recovery. Avoid an unnecessary lock/unlock in WalBeginReadTransaction. check-in: db3509c5 user: dan tags: wal-incr-ckpt
16:10
Get the new xShmLock interface design working on os_win.c. check-in: 149a7082 user: drh tags: wal-incr-ckpt
14:39
Make sure WAL alway requests enough shared-memory space. check-in: 138f1283 user: drh tags: wal-incr-ckpt
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

  3179   3179   
  3180   3180   /*
  3181   3181   ** Constants used for locking
  3182   3182   */
  3183   3183   #define UNIX_SHM_BASE   ((18+SQLITE_SHM_NLOCK)*4)         /* first lock byte */
  3184   3184   #define UNIX_SHM_DMS    (UNIX_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
  3185   3185   
  3186         -#ifdef SQLITE_DEBUG
  3187         -/*
  3188         -** Return a pointer to a nul-terminated string in static memory that
  3189         -** describes a locking mask.  The string is of the form "MSABCD" with
  3190         -** each character representing a lock.  "M" for MUTEX, "S" for DMS, 
  3191         -** and "A" through "D" for the region locks.  If a lock is held, the
  3192         -** letter is shown.  If the lock is not held, the letter is converted
  3193         -** to ".".
  3194         -**
  3195         -** This routine is for debugging purposes only and does not appear
  3196         -** in a production build.
  3197         -*/
  3198         -static const char *unixShmLockString(u16 maskShared, u16 maskExclusive){
  3199         -  static char zBuf[52];
  3200         -  static int iBuf = 0;
  3201         -  int i;
  3202         -  u16 mask;
  3203         -  char *z;
  3204         -
  3205         -  z = &zBuf[iBuf];
  3206         -  iBuf += 16;
  3207         -  if( iBuf>=sizeof(zBuf) ) iBuf = 0;
  3208         -  for(i=0, mask=1; i<SQLITE_SHM_NLOCK; i++, mask += mask){
  3209         -    if( mask & maskShared ){
  3210         -      z[i] = 's';
  3211         -    }else if( mask & maskExclusive ){
  3212         -      z[i] = 'E';
  3213         -    }else{
  3214         -      z[i] = '.';
  3215         -    }
  3216         -  }
  3217         -  z[i] = 0;
  3218         -  return z;
  3219         -}
  3220         -#endif /* SQLITE_DEBUG */
  3221         -
  3222   3186   /*
  3223   3187   ** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
  3224   3188   **
  3225   3189   ** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
  3226   3190   ** otherwise.
  3227   3191   */
  3228   3192   static int unixShmSystemLock(
................................................................................
  3279   3243       }else if( lockType==F_RDLCK ){
  3280   3244         OSTRACE(("read-lock failed"));
  3281   3245       }else{
  3282   3246         assert( lockType==F_WRLCK );
  3283   3247         OSTRACE(("write-lock %d failed", ofst));
  3284   3248       }
  3285   3249     }
  3286         -  OSTRACE((" - afterwards %s\n",
  3287         -           unixShmLockString(pShmNode->sharedMask, pShmNode->exclMask)));
         3250  +  OSTRACE((" - afterwards %03x,%03x\n",
         3251  +           pShmNode->sharedMask, pShmNode->exclMask));
  3288   3252     }
  3289   3253   #endif
  3290   3254   
  3291   3255     return rc;        
  3292   3256   }
  3293   3257   
  3294   3258   
................................................................................
  3703   3667         if( rc==SQLITE_OK ){
  3704   3668           p->sharedMask &= ~mask;
  3705   3669           p->exclMask |= mask;
  3706   3670         }
  3707   3671       }
  3708   3672     }
  3709   3673     sqlite3_mutex_leave(pShmNode->mutex);
  3710         -  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",
  3711         -           p->id, getpid(), unixShmLockString(p->sharedMask, p->exclMask)));
         3674  +  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
         3675  +           p->id, getpid(), p->sharedMask, p->exclMask));
  3712   3676     return rc;
  3713   3677   }
  3714   3678   
  3715   3679   /*
  3716   3680   ** Implement a memory barrier or memory fence on shared memory.  
  3717   3681   **
  3718   3682   ** All loads and stores begun before the barrier must complete before

Changes to src/os_win.c.

  1223   1223     DWORD lastErrno;           /* The Windows errno from the last I/O error */
  1224   1224     int szMap;                 /* Size of the mapping of file into memory */
  1225   1225     char *pMMapBuf;            /* Where currently mmapped().  NULL if unmapped */
  1226   1226     int nRef;                  /* Number of winShm objects pointing to this */
  1227   1227     winShm *pFirst;            /* All winShm objects pointing to this */
  1228   1228     winShmNode *pNext;         /* Next in list of all winShmNode objects */
  1229   1229   #ifdef SQLITE_DEBUG
  1230         -  u8 exclMask;               /* Mask of exclusive locks held */
  1231         -  u8 sharedMask;             /* Mask of shared locks held */
  1232   1230     u8 nextShmId;              /* Next available winShm.id value */
  1233   1231   #endif
  1234   1232   };
  1235   1233   
  1236   1234   /*
  1237   1235   ** A global array of all winShmNode objects.
  1238   1236   **
................................................................................
  1249   1247   **
  1250   1248   ** The winShm.pFile element is initialized when the object is created
  1251   1249   ** and is read-only thereafter.
  1252   1250   */
  1253   1251   struct winShm {
  1254   1252     winShmNode *pShmNode;      /* The underlying winShmNode object */
  1255   1253     winShm *pNext;             /* Next winShm with the same winShmNode */
  1256         -  u8 lockState;              /* Current lock state */
  1257   1254     u8 hasMutex;               /* True if holding the winShmNode mutex */
  1258   1255     u8 hasMutexBuf;            /* True if holding pFile->mutexBuf */
  1259         -  u8 sharedMask;             /* Mask of shared locks held */
  1260         -  u8 exclMask;               /* Mask of exclusive locks held */
  1261   1256   #ifdef SQLITE_DEBUG
  1262   1257     u8 id;                     /* Id of this connection with its winShmNode */
  1263   1258   #endif
  1264   1259   };
  1265   1260   
  1266         -/*
  1267         -** Size increment by which shared memory grows
  1268         -*/
  1269         -#define SQLITE_WIN_SHM_INCR  4096
  1270         -
  1271   1261   /*
  1272   1262   ** Constants used for locking
  1273   1263   */
  1274         -#define WIN_SHM_BASE      80        /* Byte offset of the first lock byte */
  1275         -#define WIN_SHM_DMS       0x01      /* Mask for Dead-Man-Switch lock */
  1276         -#define WIN_SHM_A         0x10      /* Mask for region locks... */
  1277         -#define WIN_SHM_B         0x20
  1278         -#define WIN_SHM_C         0x40
  1279         -#define WIN_SHM_D         0x80
  1280         -
  1281         -#ifdef SQLITE_DEBUG
  1282         -/*
  1283         -** Return a pointer to a nul-terminated string in static memory that
  1284         -** describes a locking mask.  The string is of the form "MSABCD" with
  1285         -** each character representing a lock.  "M" for MUTEX, "S" for DMS, 
  1286         -** and "A" through "D" for the region locks.  If a lock is held, the
  1287         -** letter is shown.  If the lock is not held, the letter is converted
  1288         -** to ".".
  1289         -**
  1290         -** This routine is for debugging purposes only and does not appear
  1291         -** in a production build.
  1292         -*/
  1293         -static const char *winShmLockString(u8 mask){
  1294         -  static char zBuf[48];
  1295         -  static int iBuf = 0;
  1296         -  char *z;
  1297         -
  1298         -  z = &zBuf[iBuf];
  1299         -  iBuf += 8;
  1300         -  if( iBuf>=sizeof(zBuf) ) iBuf = 0;
  1301         -
  1302         -  z[0] = (mask & WIN_SHM_DMS)   ? 'S' : '.';
  1303         -  z[1] = (mask & WIN_SHM_A)     ? 'A' : '.';
  1304         -  z[2] = (mask & WIN_SHM_B)     ? 'B' : '.';
  1305         -  z[3] = (mask & WIN_SHM_C)     ? 'C' : '.';
  1306         -  z[4] = (mask & WIN_SHM_D)     ? 'D' : '.';
  1307         -  z[5] = 0;
  1308         -  return z;
  1309         -}
  1310         -#endif /* SQLITE_DEBUG */
         1264  +#define WIN_SHM_BASE   ((18+SQLITE_SHM_NLOCK)*4)        /* first lock byte */
         1265  +#define WIN_SHM_DMS    (WIN_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
  1311   1266   
  1312   1267   /*
  1313         -** Apply posix advisory locks for all bytes identified in lockMask.
  1314         -**
  1315         -** lockMask might contain multiple bits but all bits are guaranteed
  1316         -** to be contiguous.
  1317         -**
  1318         -** Locks block if the mask is exactly WIN_SHM_C and are non-blocking
  1319         -** otherwise.
         1268  +** Apply advisory locks for all n bytes beginning at ofst.
  1320   1269   */
  1321   1270   #define _SHM_UNLCK  1
  1322   1271   #define _SHM_RDLCK  2
  1323   1272   #define _SHM_WRLCK  3
  1324   1273   static int winShmSystemLock(
  1325   1274     winShmNode *pFile,    /* Apply locks to this open shared-memory segment */
  1326   1275     int lockType,         /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
  1327         -  u8 lockMask           /* Which bytes to lock or unlock */
         1276  +  int ofst,             /* Offset to first byte to be locked/unlocked */
         1277  +  int nByte             /* Number of bytes to lock or unlock */
  1328   1278   ){
  1329   1279     OVERLAPPED ovlp;
  1330   1280     DWORD dwFlags;
  1331         -  int nBytes;           /* Number of bytes to lock */
  1332         -  int i;                /* Offset into the locking byte range */
  1333   1281     int rc = 0;           /* Result code form Lock/UnlockFileEx() */
  1334         -  u8 mask;              /* Mask of bits in lockMask */
  1335   1282   
  1336   1283     /* Access to the winShmNode object is serialized by the caller */
  1337   1284     assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
  1338   1285   
  1339   1286     /* Initialize the locking parameters */
  1340         -  if( lockMask==WIN_SHM_C && lockType!=_SHM_UNLCK ){
  1341         -    dwFlags = 0;
  1342         -    OSTRACE(("SHM-LOCK %d requesting blocking lock %s\n", 
  1343         -             pFile->hFile.h,
  1344         -             winShmLockString(lockMask)));
  1345         -  }else{
  1346         -    dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
  1347         -    OSTRACE(("SHM-LOCK %d requesting %s %s\n", 
  1348         -             pFile->hFile.h,
  1349         -             lockType!=_SHM_UNLCK ? "lock" : "unlock", 
  1350         -             winShmLockString(lockMask)));
  1351         -  }
         1287  +  dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
  1352   1288     if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
  1353   1289   
  1354   1290     /* Find the first bit in lockMask that is set */
  1355         -  for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
  1356         -  assert( mask!=0 );
  1357   1291     memset(&ovlp, 0, sizeof(OVERLAPPED));
  1358         -  ovlp.Offset = i+WIN_SHM_BASE;
  1359         -  nBytes = 1;
  1360         -
  1361         -  /* Extend the locking range for each additional bit that is set */
  1362         -  mask <<= 1;
  1363         -  while( mask!=0 && (lockMask & mask)!=0 ){
  1364         -    nBytes++;
  1365         -    mask <<= 1;
  1366         -  }
  1367         -
  1368         -  /* Verify that all bits set in lockMask are contiguous */
  1369         -  assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
         1292  +  ovlp.Offset = ofst;
  1370   1293   
  1371   1294     /* Release/Acquire the system-level lock */
  1372   1295     if( lockType==_SHM_UNLCK ){
  1373         -    for(i=0; i<nBytes; i++, ovlp.Offset++){
  1374         -      rc = UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
  1375         -      if( !rc ) break;
  1376         -    }
         1296  +    rc = UnlockFileEx(pFile->hFile.h, 0, nByte, 0, &ovlp);
  1377   1297     }else{
  1378         -    /* release old individual byte locks (if any)
  1379         -    ** and set new individual byte locks */
  1380         -    for(i=0; i<nBytes; i++, ovlp.Offset++){
  1381         -      UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
  1382         -      rc = LockFileEx(pFile->hFile.h, dwFlags, 0, 1, 0, &ovlp);
  1383         -      if( !rc ) break;
  1384         -    }
         1298  +    rc = LockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp);
  1385   1299     }
  1386   1300     if( !rc ){
  1387   1301       OSTRACE(("SHM-LOCK %d %s ERROR 0x%08lx\n", 
  1388   1302                pFile->hFile.h,
  1389   1303                lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx",
  1390   1304                GetLastError()));
  1391         -    /* release individual byte locks (if any) */
  1392         -    ovlp.Offset-=i;
  1393         -    for(i=0; i<nBytes; i++, ovlp.Offset++){
  1394         -      UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
  1395         -    }
  1396   1305     }
  1397   1306     rc = (rc!=0) ? SQLITE_OK : SQLITE_BUSY;
  1398   1307   
  1399         -  /* Update the global lock state and do debug tracing */
  1400         -#ifdef SQLITE_DEBUG
  1401         -  OSTRACE(("SHM-LOCK %d ", pFile->hFile.h));
  1402         -  if( rc==SQLITE_OK ){
  1403         -    if( lockType==_SHM_UNLCK ){
  1404         -      OSTRACE(("unlock ok"));
  1405         -      pFile->exclMask &= ~lockMask;
  1406         -      pFile->sharedMask &= ~lockMask;
  1407         -    }else if( lockType==_SHM_RDLCK ){
  1408         -      OSTRACE(("read-lock ok"));
  1409         -      pFile->exclMask &= ~lockMask;
  1410         -      pFile->sharedMask |= lockMask;
  1411         -    }else{
  1412         -      assert( lockType==_SHM_WRLCK );
  1413         -      OSTRACE(("write-lock ok"));
  1414         -      pFile->exclMask |= lockMask;
  1415         -      pFile->sharedMask &= ~lockMask;
  1416         -    }
  1417         -  }else{
  1418         -    if( lockType==_SHM_UNLCK ){
  1419         -      OSTRACE(("unlock failed"));
  1420         -    }else if( lockType==_SHM_RDLCK ){
  1421         -      OSTRACE(("read-lock failed"));
  1422         -    }else{
  1423         -      assert( lockType==_SHM_WRLCK );
  1424         -      OSTRACE(("write-lock failed"));
  1425         -    }
  1426         -  }
  1427         -  OSTRACE((" - change requested %s - afterwards %s:%s\n",
  1428         -           winShmLockString(lockMask),
  1429         -           winShmLockString(pFile->sharedMask),
  1430         -           winShmLockString(pFile->exclMask)));
  1431         -#endif
  1432         -
  1433         -  return rc;
  1434         -}
  1435         -
  1436         -/*
  1437         -** For connection p, unlock all of the locks identified by the unlockMask
  1438         -** parameter.
  1439         -*/
  1440         -static int winShmUnlock(
  1441         -  winShmNode *pFile,   /* The underlying shared-memory file */
  1442         -  winShm *p,           /* The connection to be unlocked */
  1443         -  u8 unlockMask         /* Mask of locks to be unlocked */
  1444         -){
  1445         -  int rc;      /* Result code */
  1446         -  winShm *pX; /* For looping over all sibling connections */
  1447         -  u8 allMask;  /* Union of locks held by connections other than "p" */
  1448         -
  1449         -  /* Access to the winShmNode object is serialized by the caller */
  1450         -  assert( sqlite3_mutex_held(pFile->mutex) );
  1451         -
  1452         -  /* don't attempt to unlock anything we don't have locks for */
  1453         -  if( (unlockMask & (p->exclMask|p->sharedMask)) != unlockMask ){
  1454         -    OSTRACE(("SHM-LOCK %d unlocking more than we have locked - requested %s - have %s\n",
  1455         -             pFile->hFile.h,
  1456         -             winShmLockString(unlockMask),
  1457         -             winShmLockString(p->exclMask|p->sharedMask)));
  1458         -    unlockMask &= (p->exclMask|p->sharedMask);
  1459         -  }
  1460         -
  1461         -  /* Compute locks held by sibling connections */
  1462         -  allMask = 0;
  1463         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  1464         -    if( pX==p ) continue;
  1465         -    assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
  1466         -    allMask |= pX->sharedMask;
  1467         -  }
  1468         -
  1469         -  /* Unlock the system-level locks */
  1470         -  if( (unlockMask & allMask)!=unlockMask ){
  1471         -    rc = winShmSystemLock(pFile, _SHM_UNLCK, unlockMask & ~allMask);
  1472         -  }else{
  1473         -    rc = SQLITE_OK;
  1474         -  }
  1475         -
  1476         -  /* Undo the local locks */
  1477         -  if( rc==SQLITE_OK ){
  1478         -    p->exclMask &= ~unlockMask;
  1479         -    p->sharedMask &= ~unlockMask;
  1480         -  } 
  1481         -  return rc;
  1482         -}
  1483         -
  1484         -/*
  1485         -** Get reader locks for connection p on all locks in the readMask parameter.
  1486         -*/
  1487         -static int winShmSharedLock(
  1488         -  winShmNode *pFile,   /* The underlying shared-memory file */
  1489         -  winShm *p,           /* The connection to get the shared locks */
  1490         -  u8 readMask           /* Mask of shared locks to be acquired */
  1491         -){
  1492         -  int rc;        /* Result code */
  1493         -  winShm *pX;   /* For looping over all sibling connections */
  1494         -  u8 allShared;  /* Union of locks held by connections other than "p" */
  1495         -
  1496         -  /* Access to the winShmNode object is serialized by the caller */
  1497         -  assert( sqlite3_mutex_held(pFile->mutex) );
  1498         -
  1499         -  /* Find out which shared locks are already held by sibling connections.
  1500         -  ** If any sibling already holds an exclusive lock, go ahead and return
  1501         -  ** SQLITE_BUSY.
  1502         -  */
  1503         -  allShared = 0;
  1504         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  1505         -    if( pX==p ) continue;
  1506         -    if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
  1507         -    allShared |= pX->sharedMask;
  1508         -  }
  1509         -
  1510         -  /* Get shared locks at the system level, if necessary */
  1511         -  if( (~allShared) & readMask ){
  1512         -    rc = winShmSystemLock(pFile, _SHM_RDLCK, readMask);
  1513         -  }else{
  1514         -    rc = SQLITE_OK;
  1515         -  }
  1516         -
  1517         -  /* Get the local shared locks */
  1518         -  if( rc==SQLITE_OK ){
  1519         -    p->sharedMask |= readMask;
  1520         -  }
  1521         -  return rc;
  1522         -}
  1523         -
  1524         -/*
  1525         -** For connection p, get an exclusive lock on all locks identified in
  1526         -** the writeMask parameter.
  1527         -*/
  1528         -static int winShmExclusiveLock(
  1529         -  winShmNode *pFile,    /* The underlying shared-memory file */
  1530         -  winShm *p,            /* The connection to get the exclusive locks */
  1531         -  u8 writeMask           /* Mask of exclusive locks to be acquired */
  1532         -){
  1533         -  int rc;        /* Result code */
  1534         -  winShm *pX;   /* For looping over all sibling connections */
  1535         -
  1536         -  /* Access to the winShmNode object is serialized by the caller */
  1537         -  assert( sqlite3_mutex_held(pFile->mutex) );
  1538         -
  1539         -  /* Make sure no sibling connections hold locks that will block this
  1540         -  ** lock.  If any do, return SQLITE_BUSY right away.
  1541         -  */
  1542         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  1543         -    if( pX==p ) continue;
  1544         -    if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
  1545         -    if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
  1546         -  }
  1547         -
  1548         -  /* Get the exclusive locks at the system level.  Then if successful
  1549         -  ** also mark the local connection as being locked.
  1550         -  */
  1551         -  rc = winShmSystemLock(pFile, _SHM_WRLCK, writeMask);
  1552         -  if( rc==SQLITE_OK ){
  1553         -    p->sharedMask &= ~writeMask;
  1554         -    p->exclMask |= writeMask;
  1555         -  }
  1556   1308     return rc;
  1557   1309   }
  1558   1310   
  1559   1311   /*
  1560   1312   ** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
  1561   1313   **
  1562   1314   ** This is not a VFS shared-memory method; it is a utility function called
................................................................................
  1676   1428         rc = SQLITE_CANTOPEN_BKPT;
  1677   1429         goto shm_open_err;
  1678   1430       }
  1679   1431   
  1680   1432       /* Check to see if another process is holding the dead-man switch.
  1681   1433       ** If not, truncate the file to zero length. 
  1682   1434       */
  1683         -    if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS)==SQLITE_OK ){
         1435  +    if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
  1684   1436         rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
  1685   1437       }
  1686   1438       if( rc==SQLITE_OK ){
  1687         -      rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS);
         1439  +      winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
         1440  +      rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
  1688   1441       }
  1689   1442       if( rc ) goto shm_open_err;
  1690   1443     }
  1691   1444   
  1692   1445     /* Make the new connection a child of the winShmNode */
  1693   1446     p->pShmNode = pShmNode;
  1694   1447     p->pNext = pShmNode->pFirst;
................................................................................
  1699   1452     pShmNode->nRef++;
  1700   1453     pDbFd->pShm = p;
  1701   1454     winShmLeaveMutex();
  1702   1455     return SQLITE_OK;
  1703   1456   
  1704   1457     /* Jump here on any error */
  1705   1458   shm_open_err:
  1706         -  winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS);
         1459  +  winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
  1707   1460     winShmPurge();                 /* This call frees pShmNode if required */
  1708   1461     sqlite3_free(p);
  1709   1462     sqlite3_free(pNew);
  1710   1463     winShmLeaveMutex();
  1711   1464     return rc;
  1712   1465   }
  1713   1466   
................................................................................
  1724   1477     winShmNode *pShmNode; /* The underlying shared-memory file */
  1725   1478     winShm **pp;          /* For looping over sibling connections */
  1726   1479   
  1727   1480     pDbFd = (winFile*)fd;
  1728   1481     p = pDbFd->pShm;
  1729   1482     pShmNode = p->pShmNode;
  1730   1483   
  1731         -  /* Verify that the connection being closed holds no locks */
  1732         -  assert( p->exclMask==0 );
  1733         -  assert( p->sharedMask==0 );
  1734         -
  1735   1484     /* Remove connection p from the set of connections associated
  1736   1485     ** with pShmNode */
  1737   1486     sqlite3_mutex_enter(pShmNode->mutex);
  1738   1487     for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
  1739   1488     *pp = p->pNext;
  1740   1489   
  1741   1490     /* Free the connection p */
................................................................................
  1778   1527     winShmNode *pShmNode = p->pShmNode;
  1779   1528     int rc = SQLITE_OK;
  1780   1529   
  1781   1530     *pNewSize = 0;
  1782   1531     if( reqSize>=0 ){
  1783   1532       sqlite3_int64 sz;
  1784   1533       rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
  1785         -    if( SQLITE_OK==rc ){
  1786         -      reqSize = (reqSize + SQLITE_WIN_SHM_INCR - 1)/SQLITE_WIN_SHM_INCR;
  1787         -      reqSize *= SQLITE_WIN_SHM_INCR;
  1788         -      if( reqSize>sz ){
  1789         -        rc = winTruncate((sqlite3_file *)&pShmNode->hFile, reqSize);
  1790         -      }
         1534  +    if( SQLITE_OK==rc && reqSize>sz ){
         1535  +      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, reqSize);
  1791   1536       }
  1792   1537     }
  1793   1538     if( SQLITE_OK==rc ){
  1794   1539       sqlite3_int64 sz;
  1795   1540       rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
  1796   1541       if( SQLITE_OK==rc ){
  1797   1542         *pNewSize = (int)sz;
................................................................................
  1829   1574   ** *ppBuf and *pNewMapSize might be NULL and zero if no space has
  1830   1575   ** yet been allocated to the underlying storage.
  1831   1576   */
  1832   1577   static int winShmGet(
  1833   1578     sqlite3_file *fd,        /* The database file holding the shared memory */
  1834   1579     int reqMapSize,          /* Requested size of mapping. -1 means don't care */
  1835   1580     int *pNewMapSize,        /* Write new size of mapping here */
  1836         -  void **ppBuf             /* Write mapping buffer origin here */
         1581  +  void volatile **ppBuf    /* Write mapping buffer origin here */
  1837   1582   ){
  1838   1583     winFile *pDbFd = (winFile*)fd;
  1839   1584     winShm *p = pDbFd->pShm;
  1840   1585     winShmNode *pShmNode = p->pShmNode;
  1841   1586     int rc = SQLITE_OK;
  1842   1587   
  1843         -  if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
         1588  +  if( p->hasMutexBuf==0 ){
  1844   1589       assert( sqlite3_mutex_notheld(pShmNode->mutex) );
  1845   1590       sqlite3_mutex_enter(pShmNode->mutexBuf);
  1846   1591       p->hasMutexBuf = 1;
  1847   1592     }
  1848   1593     sqlite3_mutex_enter(pShmNode->mutex);
  1849   1594     if( pShmNode->szMap==0 || reqMapSize>pShmNode->szMap ){
  1850   1595       int actualSize;
................................................................................
  1916   1661   ** If the shared-memory object is in lock state RECOVER, then we do not
  1917   1662   ** really want to release the lock, so in that case too, this routine
  1918   1663   ** is a no-op.
  1919   1664   */
  1920   1665   static int winShmRelease(sqlite3_file *fd){
  1921   1666     winFile *pDbFd = (winFile*)fd;
  1922   1667     winShm *p = pDbFd->pShm;
  1923         -  if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
         1668  +  if( p->hasMutexBuf ){
  1924   1669       winShmNode *pShmNode = p->pShmNode;
  1925   1670       assert( sqlite3_mutex_notheld(pShmNode->mutex) );
  1926   1671       sqlite3_mutex_leave(pShmNode->mutexBuf);
  1927   1672       p->hasMutexBuf = 0;
  1928   1673     }
  1929   1674     return SQLITE_OK;
  1930   1675   }
  1931         -
  1932         -/*
  1933         -** Symbolic names for LOCK states used for debugging.
  1934         -*/
  1935         -#ifdef SQLITE_DEBUG
  1936         -static const char *azLkName[] = {
  1937         -  "UNLOCK",
  1938         -  "READ",
  1939         -  "READ_FULL",
  1940         -  "WRITE",
  1941         -  "PENDING",
  1942         -  "CHECKPOINT",
  1943         -  "RECOVER"
  1944         -};
  1945         -#endif
  1946         -
  1947   1676   
  1948   1677   /*
  1949   1678   ** Change the lock state for a shared-memory segment.
  1950   1679   */
  1951   1680   static int winShmLock(
  1952         -  sqlite3_file *fd,          /* Database holding the shared memory */
  1953         -  int desiredLock,           /* One of SQLITE_SHM_xxxxx locking states */
  1954         -  int *pGotLock              /* The lock you actually got */
         1681  +  sqlite3_file *fd,          /* Database file holding the shared memory */
         1682  +  int ofst,                  /* First lock to acquire or release */
         1683  +  int n,                     /* Number of locks to acquire or release */
         1684  +  int flags                  /* What to do with the lock */
  1955   1685   ){
  1956   1686     winFile *pDbFd = (winFile*)fd;
  1957   1687     winShm *p = pDbFd->pShm;
  1958   1688     winShmNode *pShmNode = p->pShmNode;
  1959   1689     int rc = SQLITE_PROTOCOL;
  1960   1690   
  1961         -  /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
  1962         -  ** directly requested; they are side effects from requesting
  1963         -  ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
  1964         -  */
  1965         -  assert( desiredLock==SQLITE_SHM_UNLOCK
  1966         -       || desiredLock==SQLITE_SHM_READ
  1967         -       || desiredLock==SQLITE_SHM_WRITE
  1968         -       || desiredLock==SQLITE_SHM_CHECKPOINT
  1969         -       || desiredLock==SQLITE_SHM_RECOVER );
         1691  +  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
         1692  +  assert( n>=1 );
         1693  +  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
         1694  +       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
         1695  +       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
         1696  +       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
         1697  +  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
  1970   1698   
  1971         -  /* Return directly if this is just a lock state query, or if
  1972         -  ** the connection is already in the desired locking state.
  1973         -  */
  1974         -  if( desiredLock==p->lockState
  1975         -   || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
  1976         -  ){
  1977         -    OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s and got %s\n",
  1978         -             pShmNode->hFile.h,
  1979         -             p->id, (int)GetCurrentProcessId(), azLkName[desiredLock],
  1980         -             azLkName[p->lockState]));
  1981         -    if( pGotLock ) *pGotLock = p->lockState;
  1982         -    return SQLITE_OK;
  1983         -  }
  1984         -
  1985         -  OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s->%s\n",
  1986         -           pShmNode->hFile.h,
  1987         -           p->id, (int)GetCurrentProcessId(), azLkName[p->lockState], 
  1988         -           azLkName[desiredLock]));
  1989         -  
  1990         -  if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
  1991         -    assert( sqlite3_mutex_notheld(pShmNode->mutex) );
  1992         -    sqlite3_mutex_enter(pShmNode->mutexBuf);
  1993         -    p->hasMutexBuf = 1;
  1994         -  }
  1995   1699     sqlite3_mutex_enter(pShmNode->mutex);
  1996         -  switch( desiredLock ){
  1997         -    case SQLITE_SHM_UNLOCK: {
  1998         -      assert( p->lockState!=SQLITE_SHM_RECOVER );
  1999         -      winShmUnlock(pShmNode, p, WIN_SHM_A|WIN_SHM_B|WIN_SHM_C|WIN_SHM_D);
  2000         -      rc = SQLITE_OK;
  2001         -      p->lockState = SQLITE_SHM_UNLOCK;
  2002         -      break;
  2003         -    }
  2004         -    case SQLITE_SHM_READ: {
  2005         -      if( p->lockState==SQLITE_SHM_UNLOCK ){
  2006         -        int nAttempt;
  2007         -        rc = SQLITE_BUSY;
  2008         -        assert( p->lockState==SQLITE_SHM_UNLOCK );
  2009         -        for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
  2010         -          rc = winShmSharedLock(pShmNode, p, WIN_SHM_A|WIN_SHM_B);
  2011         -          if( rc==SQLITE_BUSY ){
  2012         -            rc = winShmSharedLock(pShmNode, p, WIN_SHM_D);
  2013         -            if( rc==SQLITE_OK ){
  2014         -              p->lockState = SQLITE_SHM_READ_FULL;
  2015         -            }
  2016         -          }else{
  2017         -            winShmUnlock(pShmNode, p, WIN_SHM_B);
  2018         -            p->lockState = SQLITE_SHM_READ;
  2019         -          }
  2020         -        }
  2021         -      }else{
  2022         -       assert( p->lockState==SQLITE_SHM_WRITE
  2023         -               || p->lockState==SQLITE_SHM_RECOVER );
  2024         -        rc = winShmSharedLock(pShmNode, p, WIN_SHM_A);
  2025         -        winShmUnlock(pShmNode, p, WIN_SHM_C|WIN_SHM_D);
  2026         -        p->lockState = SQLITE_SHM_READ;
  2027         -      }
  2028         -      break;
  2029         -    }
  2030         -    case SQLITE_SHM_WRITE: {
  2031         -      assert( p->lockState==SQLITE_SHM_READ 
  2032         -              || p->lockState==SQLITE_SHM_READ_FULL );
  2033         -      rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_C|WIN_SHM_D);
  2034         -      if( rc==SQLITE_OK ){
  2035         -        p->lockState = SQLITE_SHM_WRITE;
  2036         -      }
  2037         -      break;
  2038         -    }
  2039         -    case SQLITE_SHM_CHECKPOINT: {
  2040         -      assert( p->lockState==SQLITE_SHM_UNLOCK
  2041         -           || p->lockState==SQLITE_SHM_PENDING
  2042         -      );
  2043         -      if( p->lockState==SQLITE_SHM_UNLOCK ){
  2044         -        rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_B|WIN_SHM_C);
  2045         -        if( rc==SQLITE_OK ){
  2046         -          p->lockState = SQLITE_SHM_PENDING;
  2047         -        }
  2048         -      }
  2049         -      if( p->lockState==SQLITE_SHM_PENDING ){
  2050         -        rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_A);
  2051         -        if( rc==SQLITE_OK ){
  2052         -          p->lockState = SQLITE_SHM_CHECKPOINT;
  2053         -        }
  2054         -      }
  2055         -      break;
  2056         -    }
  2057         -    default: {
  2058         -      assert( desiredLock==SQLITE_SHM_RECOVER );
  2059         -      assert( p->lockState==SQLITE_SHM_READ
  2060         -           || p->lockState==SQLITE_SHM_READ_FULL
  2061         -      );
  2062         -      assert( sqlite3_mutex_held(pShmNode->mutexBuf) );
  2063         -      rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_C);
  2064         -      if( rc==SQLITE_OK ){
  2065         -        p->lockState = SQLITE_SHM_RECOVER;
  2066         -      }
  2067         -      break;
  2068         -    }
         1700  +  if( flags & SQLITE_SHM_UNLOCK ){
         1701  +    rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
         1702  +  }else if( flags & SQLITE_SHM_SHARED ){
         1703  +    rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
         1704  +  }else{
         1705  +    rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
  2069   1706     }
  2070   1707     sqlite3_mutex_leave(pShmNode->mutex);
  2071         -  OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d got %s\n",
  2072         -           pShmNode->hFile.h, 
  2073         -           p->id, (int)GetCurrentProcessId(), azLkName[p->lockState]));
  2074         -  if( pGotLock ) *pGotLock = p->lockState;
         1708  +  OSTRACE(("SHM-LOCK shmid-%d, pid-%d %s\n",
         1709  +           p->id, (int)GetCurrentProcessId(), rc ? "failed" : "ok"));
  2075   1710     return rc;
  2076   1711   }
  2077   1712   
  2078   1713   /*
  2079   1714   ** Implement a memory barrier or memory fence on shared memory.  
  2080   1715   **
  2081   1716   ** All loads and stores begun before the barrier must complete before

Changes to src/wal.c.

  2019   2019           pWal->nCkpt++;
  2020   2020           pWal->hdr.mxFrame = 0;
  2021   2021           sqlite3Put4byte((u8*)pWal->hdr.aSalt,
  2022   2022                            1 + sqlite3Get4byte((u8*)pWal->hdr.aSalt));
  2023   2023           sqlite3_randomness(4, &pWal->hdr.aSalt[1]);
  2024   2024           walIndexWriteHdr(pWal);
  2025   2025           pInfo->nBackfill = 0;
  2026         -        memset(&pInfo->aReadMark[1], 0, sizeof(pInfo->aReadMark)-sizeof(u32));
         2026  +        memset((void*)&pInfo->aReadMark[1], 0,
         2027  +               sizeof(pInfo->aReadMark)-sizeof(u32));
  2027   2028           rc = sqlite3OsTruncate(pWal->pDbFd, 
  2028   2029                                  ((i64)pWal->hdr.nPage*(i64)pWal->szPage));
  2029   2030           walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
  2030   2031         }
  2031   2032       }
  2032   2033       walUnlockShared(pWal, WAL_READ_LOCK(0));
  2033   2034       pWal->readLock = -1;