diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2023-02-13 15:42:58 -0700 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2023-02-13 15:42:58 -0700 |
commit | 2098ac287002f090a02baf82fd5dda1bc3753e25 (patch) | |
tree | 103618be679f606fde39c07173534a38ddd2f38a /lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/nestedlock.go | |
parent | a29f4c3421cd8deb2b0f578acb195442569236b7 (diff) | |
parent | 25cbf5fbe8c5be5f3c3dabd694668fa7454a05b9 (diff) |
Merge branch 'lukeshu/rebuild-nodes-take5'
Diffstat (limited to 'lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/nestedlock.go')
-rw-r--r-- | lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/nestedlock.go | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/nestedlock.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/nestedlock.go new file mode 100644 index 0000000..c1ffa18 --- /dev/null +++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/nestedlock.go @@ -0,0 +1,45 @@ +// Copyright (C) 2023 Luke Shumaker <lukeshu@lukeshu.com> +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package btrees + +import ( + "context" + "sync" +) + +// A nestedMutex is like a sync.Mutex, but while it is locked by call +// 'A', may be simultaneously locked by subsequent calls if the +// subsequent calls use a Context descended from the one returned by +// the 'A' call to .Lock(). +type nestedMutex struct { + inner sync.Mutex + depth int +} + +type nestedMutexCtxKey struct{} + +// Lock locks the mutex. It is invalid to use a Context returned from +// Lock in a different goroutine than the one it was created in. It +// is invalid to use a Context returned from Lock after the mutex has +// subsequently become unlocked. +func (m *nestedMutex) Lock(ctx context.Context) context.Context { + if other, ok := ctx.Value(nestedMutexCtxKey{}).(*nestedMutex); ok && other == m { + m.depth++ + return ctx + } + m.inner.Lock() + return context.WithValue(ctx, nestedMutexCtxKey{}, m) +} + +// Unlock unlocks the mutex. It is invalid to call Unlock if the +// mutex is not already locked. It is invalid to call Unlock from +// multiple goroutines simultaneously. +func (m *nestedMutex) Unlock() { + if m.depth > 0 { + m.depth-- + } else { + m.inner.Unlock() + } +} |