gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sync/locking/generic_rwmutex.go (about) 1 // Copyright 2022 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package locking 16 17 import ( 18 "reflect" 19 20 "gvisor.dev/gvisor/pkg/sync" 21 "gvisor.dev/gvisor/pkg/sync/locking" 22 ) 23 24 // RWMutex is sync.RWMutex with the correctness validator. 25 type RWMutex struct { 26 mu sync.RWMutex 27 } 28 29 // lockNames is a list of user-friendly lock names. 30 // Populated in init. 31 var lockNames []string 32 33 // lockNameIndex is used as an index passed to NestedLock and NestedUnlock, 34 // referring to an index within lockNames. 35 // Values are specified using the "consts" field of go_template_instance. 36 type lockNameIndex int 37 38 // DO NOT REMOVE: The following function automatically replaced with lock index constants. 39 // LOCK_NAME_INDEX_CONSTANTS 40 const () 41 42 // Lock locks m. 43 // +checklocksignore 44 func (m *RWMutex) Lock() { 45 locking.AddGLock(genericMarkIndex, -1) 46 m.mu.Lock() 47 } 48 49 // NestedLock locks m knowing that another lock of the same type is held. 50 // +checklocksignore 51 func (m *RWMutex) NestedLock(i lockNameIndex) { 52 locking.AddGLock(genericMarkIndex, int(i)) 53 m.mu.Lock() 54 } 55 56 // Unlock unlocks m. 57 // +checklocksignore 58 func (m *RWMutex) Unlock() { 59 m.mu.Unlock() 60 locking.DelGLock(genericMarkIndex, -1) 61 } 62 63 // NestedUnlock unlocks m knowing that another lock of the same type is held. 64 // +checklocksignore 65 func (m *RWMutex) NestedUnlock(i lockNameIndex) { 66 m.mu.Unlock() 67 locking.DelGLock(genericMarkIndex, int(i)) 68 } 69 70 // RLock locks m for reading. 71 // +checklocksignore 72 func (m *RWMutex) RLock() { 73 locking.AddGLock(genericMarkIndex, -1) 74 m.mu.RLock() 75 } 76 77 // RUnlock undoes a single RLock call. 78 // +checklocksignore 79 func (m *RWMutex) RUnlock() { 80 m.mu.RUnlock() 81 locking.DelGLock(genericMarkIndex, -1) 82 } 83 84 // RLockBypass locks m for reading without executing the validator. 85 // +checklocksignore 86 func (m *RWMutex) RLockBypass() { 87 m.mu.RLock() 88 } 89 90 // RUnlockBypass undoes a single RLockBypass call. 91 // +checklocksignore 92 func (m *RWMutex) RUnlockBypass() { 93 m.mu.RUnlock() 94 } 95 96 // DowngradeLock atomically unlocks rw for writing and locks it for reading. 97 // +checklocksignore 98 func (m *RWMutex) DowngradeLock() { 99 m.mu.DowngradeLock() 100 } 101 102 var genericMarkIndex *locking.MutexClass 103 104 // DO NOT REMOVE: The following function is automatically replaced. 105 func initLockNames() {} 106 107 func init() { 108 initLockNames() 109 genericMarkIndex = locking.NewMutexClass(reflect.TypeOf(RWMutex{}), lockNames) 110 }