Locking improvements.

This commit is contained in:
Nuno Cruces
2024-03-15 16:14:49 +00:00
parent ec96c77715
commit fd3a3a3499
4 changed files with 37 additions and 17 deletions

View File

@@ -65,14 +65,20 @@ func (f *vfsFile) Lock(lock LockLevel) error {
if f.lock <= LOCK_NONE || f.lock >= LOCK_EXCLUSIVE {
panic(util.AssertErr())
}
reserved := f.lock == LOCK_RESERVED
// A PENDING lock is needed before acquiring an EXCLUSIVE lock.
if f.lock < LOCK_PENDING {
if rc := osGetPendingLock(f.File, f.lock); rc != _OK {
// If we're already RESERVED, we can block indefinitely,
// since only new readers may briefly hold the PENDING lock.
if rc := osGetPendingLock(f.File, reserved /* block */); rc != _OK {
return rc
}
f.lock = LOCK_PENDING
}
if rc := osGetExclusiveLock(f.File); rc != _OK {
// We already have PENDING, so we're just waiting for readers to leave.
// If we were RESERVED, we can wait for a little while, before invoking
// the busy handler; we will only do this once.
if rc := osGetExclusiveLock(f.File, reserved /* wait */); rc != _OK {
return rc
}
f.lock = LOCK_EXCLUSIVE

View File

@@ -20,11 +20,11 @@ func osGetReservedLock(_ *os.File) _ErrorCode {
return _IOERR_LOCK
}
func osGetPendingLock(_ *os.File, _ LockLevel) _ErrorCode {
func osGetPendingLock(_ *os.File, _ bool) _ErrorCode {
return _IOERR_LOCK
}
func osGetExclusiveLock(_ *os.File) _ErrorCode {
func osGetExclusiveLock(_ *os.File, _ bool) _ErrorCode {
return _IOERR_LOCK
}

View File

@@ -31,18 +31,22 @@ func osGetReservedLock(file *os.File) _ErrorCode {
return osWriteLock(file, _RESERVED_BYTE, 1, 0)
}
func osGetPendingLock(file *os.File, state LockLevel) _ErrorCode {
// Acquire the PENDING lock.
func osGetPendingLock(file *os.File, block bool) _ErrorCode {
var timeout time.Duration
if state >= LOCK_RESERVED {
if block {
timeout = -1
}
// Acquire the PENDING lock.
return osWriteLock(file, _PENDING_BYTE, 1, timeout)
}
func osGetExclusiveLock(file *os.File) _ErrorCode {
func osGetExclusiveLock(file *os.File, wait bool) _ErrorCode {
var timeout time.Duration
if wait {
timeout = time.Millisecond
}
// Acquire the EXCLUSIVE lock.
return osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, time.Millisecond)
return osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, timeout)
}
func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode {

View File

@@ -36,21 +36,27 @@ func osGetReservedLock(file *os.File) _ErrorCode {
return osWriteLock(file, _RESERVED_BYTE, 1, 0)
}
func osGetPendingLock(file *os.File, state LockLevel) _ErrorCode {
// Acquire the PENDING lock.
func osGetPendingLock(file *os.File, block bool) _ErrorCode {
var timeout time.Duration
if state >= LOCK_RESERVED {
if block {
timeout = -1
}
// Acquire the PENDING lock.
return osWriteLock(file, _PENDING_BYTE, 1, timeout)
}
func osGetExclusiveLock(file *os.File) _ErrorCode {
func osGetExclusiveLock(file *os.File, wait bool) _ErrorCode {
var timeout time.Duration
if wait {
timeout = time.Millisecond
}
// Release the SHARED lock.
osUnlock(file, _SHARED_FIRST, _SHARED_SIZE)
// Acquire the EXCLUSIVE lock.
rc := osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, time.Millisecond)
rc := osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, timeout)
if rc != _OK {
// Reacquire the SHARED lock.
@@ -179,9 +185,13 @@ func osLockErrorCode(err error, def _ErrorCode) _ErrorCode {
func osSleep(d time.Duration) {
if d > 0 {
period := uint32(max(1, min(d/(2*time.Millisecond), 16)))
windows.TimeBeginPeriod(period)
period := max(1, d/(5*time.Millisecond))
if period < 16 {
windows.TimeBeginPeriod(uint32(period))
}
time.Sleep(d)
windows.TimeEndPeriod(period)
if period < 16 {
windows.TimeEndPeriod(uint32(period))
}
}
}