type rwmutex … // Lock ranking an rwmutex has two aspects: // // Semantic ranking: this rwmutex represents some higher level lock that // protects some resource (e.g., allocmLock protects creation of new Ms). The // read and write locks of that resource need to be represented in the lock // rank. // // Internal ranking: as an implementation detail, rwmutex uses two mutexes: // rLock and wLock. These have lock order requirements: wLock must be locked // before rLock. This also needs to be represented in the lock rank. // // Semantic ranking is represented by acquiring readRank during read lock and // writeRank during write lock. // // wLock is held for the duration of a write lock, so it uses writeRank // directly, both for semantic and internal ranking. rLock is only held // temporarily inside the rlock/lock methods, so it uses readRankInternal to // represent internal ranking. Semantic ranking is represented by a separate // acquire of readRank for the duration of a read lock. // // The lock ranking must document this ordering: // - readRankInternal is a leaf lock. // - readRank is taken before readRankInternal. // - writeRank is taken before readRankInternal. // - readRank is placed in the lock order wherever a read lock of this rwmutex // belongs. // - writeRank is placed in the lock order wherever a write lock of this // rwmutex belongs. func (rw *rwmutex) init(readRank, readRankInternal, writeRank lockRank) { … } const rwmutexMaxReaders … // rlock locks rw for reading. func (rw *rwmutex) rlock() { … } // runlock undoes a single rlock call on rw. func (rw *rwmutex) runlock() { … } // lock locks rw for writing. func (rw *rwmutex) lock() { … } // unlock unlocks rw for writing. func (rw *rwmutex) unlock() { … }