From 3763b061873e7420281c2634b43103b1e8b048cc Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Wed, 25 Jan 2023 00:33:01 +0000 Subject: [PATCH] xCheckReservedLock. --- vfs_lock.go | 42 +++++++++++++++++++++++++++++++++--------- vfs_lock_debug.go | 9 ++++++++- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/vfs_lock.go b/vfs_lock.go index c2f0c01..b36a937 100644 --- a/vfs_lock.go +++ b/vfs_lock.go @@ -53,13 +53,16 @@ const ( ) type vfsLocker interface { - LockState() uint32 + LockerState() uint32 + LockShared() uint32 // UNLOCKED -> SHARED LockReserved() uint32 // SHARED -> RESERVED - LockPending() uint32 // SHARED|RESERVED -> (PENDING) + LockPending() uint32 // SHARED|RESERVED -> PENDING LockExclusive() uint32 // PENDING -> EXCLUSIVE DowngradeLock() uint32 // SHARED <- EXCLUSIVE|PENDING|RESERVED ReleaseLock() uint32 // UNLOCKED <- EXCLUSIVE|PENDING|RESERVED|SHARED + + CheckReserved() (bool, uint32) } func vfsLock(ctx context.Context, mod api.Module, pFile, eLock uint32) uint32 { @@ -81,7 +84,7 @@ func vfsLock(ctx context.Context, mod api.Module, pFile, eLock uint32) uint32 { // We never move from unlocked to anything higher than shared lock. panic(assertErr + " [pfa77m]") case cLock != _SHARED_LOCK && eLock == _RESERVED_LOCK: - // A shared lock is always held when a reserve lock is requested. + // A shared lock is always held when a reserved lock is requested. panic(assertErr + " [5cfmsp]") } } @@ -89,7 +92,7 @@ func vfsLock(ctx context.Context, mod api.Module, pFile, eLock uint32) uint32 { vfsOpenFilesMtx.Lock() defer vfsOpenFilesMtx.Unlock() of := vfsOpenFiles[ptr.ID()] - fLock := of.LockState() + fLock := of.LockerState() // If some other connection has a lock that precludes the requested lock, return BUSY. if cLock != fLock && (eLock > _SHARED_LOCK || fLock >= _PENDING_LOCK) { @@ -152,7 +155,7 @@ func vfsLock(ctx context.Context, mod api.Module, pFile, eLock uint32) uint32 { } } -func vfsUnlock(ctx context.Context, mod api.Module, pFile, eLock uint32) (rc uint32) { +func vfsUnlock(ctx context.Context, mod api.Module, pFile, eLock uint32) uint32 { if assert && (eLock != _NO_LOCK && eLock != _SHARED_LOCK) { panic(assertErr + " [7i4jw3]") } @@ -168,7 +171,7 @@ func vfsUnlock(ctx context.Context, mod api.Module, pFile, eLock uint32) (rc uin vfsOpenFilesMtx.Lock() defer vfsOpenFilesMtx.Unlock() of := vfsOpenFiles[ptr.ID()] - fLock := of.LockState() + fLock := of.LockerState() if assert && of.shared <= 0 { panic(assertErr + " [2bhkwg]") @@ -183,8 +186,7 @@ func vfsUnlock(ctx context.Context, mod api.Module, pFile, eLock uint32) (rc uin // process is holding an incompatible lock. If it does, this // indicates that the other process is not following the locking // protocol. If this happens, return IOERR_RDLOCK. Returning - // BUSY would confuse the upper layer (in practice it causes - // an assert to fail). + // BUSY would confuse the upper layer. return uint32(IOERR_RDLOCK) } ptr.SetLock(_SHARED_LOCK) @@ -217,6 +219,28 @@ func vfsUnlock(ctx context.Context, mod api.Module, pFile, eLock uint32) (rc uin } func vfsCheckReservedLock(ctx context.Context, mod api.Module, pFile, pResOut uint32) uint32 { - mod.Memory().WriteUint32Le(pResOut, 0) + ptr := vfsFilePtr{mod, pFile} + cLock := ptr.Lock() + + if assert && cLock > _SHARED_LOCK { + panic(assertErr + " [zarygt]") + } + + vfsOpenFilesMtx.Lock() + defer vfsOpenFilesMtx.Unlock() + of := vfsOpenFiles[ptr.ID()] + + locked, rc := of.CheckReserved() + if rc != _OK { + return uint32(IOERR_CHECKRESERVEDLOCK) + } + + var res uint32 + if locked { + res = 1 + } + if ok := mod.Memory().WriteUint32Le(pResOut, res); !ok { + panic(rangeErr) + } return _OK } diff --git a/vfs_lock_debug.go b/vfs_lock_debug.go index f5fa883..4b1ba31 100644 --- a/vfs_lock_debug.go +++ b/vfs_lock_debug.go @@ -8,7 +8,7 @@ type vfsDebugLocker struct { var _ vfsLocker = &vfsDebugLocker{} -func (l *vfsDebugLocker) LockState() uint32 { +func (l *vfsDebugLocker) LockerState() uint32 { return l.state } @@ -59,3 +59,10 @@ func (l *vfsDebugLocker) ReleaseLock() uint32 { l.state = _NO_LOCK return _OK } + +func (l *vfsDebugLocker) CheckReserved() (bool, uint32) { + if l.state > _SHARED_LOCK { + return true, _OK + } + return false, _OK +}