Copyright 2017 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package runtime

import (
	
)
This is a copy of sync/rwmutex.go rewritten to work in the runtime.
A rwmutex is a reader/writer mutual exclusion lock. The lock can be held by an arbitrary number of readers or a single writer. This is a variant of sync.RWMutex, for the runtime package. Like mutex, rwmutex blocks the calling M. It does not interact with the goroutine scheduler.
type rwmutex struct {
	rLock      mutex    // protects readers, readerPass, writer
	readers    muintptr // list of pending readers
	readerPass uint32   // number of pending readers to skip readers list

	wLock  mutex    // serializes writers
	writer muintptr // pending writer waiting for completing readers

	readerCount uint32 // number of pending readers
	readerWait  uint32 // number of departing readers
}

const rwmutexMaxReaders = 1 << 30
rlock locks rw for reading.
The reader must not be allowed to lose its P or else other things blocking on the lock may consume all of the Ps and deadlock (issue #20903). Alternatively, we could drop the P while sleeping.
A writer is pending. Park on the reader queue.
Writer finished.
				.readerPass -= 1
				unlock(&.rLock)
Queue this reader to be woken by the writer.
				 := getg().m
				.schedlink = .readers
				.readers.set()
				unlock(&.rLock)
				notesleep(&.park)
				noteclear(&.park)
			}
		})
	}
}
runlock undoes a single rlock call on rw.
func ( *rwmutex) () {
	if  := int32(atomic.Xadd(&.readerCount, -1));  < 0 {
		if +1 == 0 || +1 == -rwmutexMaxReaders {
			throw("runlock of unlocked rwmutex")
A writer is pending.
The last reader unblocks the writer.
			lockWithRank(&.rLock, lockRankRwmutexR)
			 := .writer.ptr()
			if  != nil {
				notewakeup(&.park)
			}
			unlock(&.rLock)
		}
	}
	releasem(getg().m)
}
lock locks rw for writing.
Resolve competition with other writers and stick to our P.
Announce that there is a pending writer.
Wait for any active readers to complete.
Wait for reader to wake us up.
		systemstack(func() {
			.writer.set()
			unlock(&.rLock)
			notesleep(&.park)
			noteclear(&.park)
		})
	} else {
		unlock(&.rLock)
	}
}
unlock unlocks rw for writing.
Announce to readers that there is no active writer.
	 := int32(atomic.Xadd(&.readerCount, rwmutexMaxReaders))
	if  >= rwmutexMaxReaders {
		throw("unlock of unlocked rwmutex")
Unblock blocked readers.
	lockWithRank(&.rLock, lockRankRwmutexR)
	for .readers.ptr() != nil {
		 := .readers.ptr()
		.readers = .schedlink
		.schedlink.set(nil)
		notewakeup(&.park)
		 -= 1
If r > 0, there are pending readers that aren't on the queue. Tell them to skip waiting.
	.readerPass += uint32()
Allow other writers to proceed.
	unlock(&.wLock)