mirror of
https://github.com/golang/go
synced 2024-11-19 03:54:42 -07:00
net: factor out fdMutex-related methods on netFD
Also updates documentation. Change-Id: Idb0fc0feed61407f7f07eab81ce82b55ffde5040 Reviewed-on: https://go-review.googlesource.com/21446 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
2ae749c13f
commit
86e7a5b92a
@ -6,9 +6,9 @@ package net
|
|||||||
|
|
||||||
import "sync/atomic"
|
import "sync/atomic"
|
||||||
|
|
||||||
// fdMutex is a specialized synchronization primitive
|
// fdMutex is a specialized synchronization primitive that manages
|
||||||
// that manages lifetime of an fd and serializes access
|
// lifetime of an fd and serializes access to Read, Write and Close
|
||||||
// to Read and Write methods on netFD.
|
// methods on netFD.
|
||||||
type fdMutex struct {
|
type fdMutex struct {
|
||||||
state uint64
|
state uint64
|
||||||
rsema uint32
|
rsema uint32
|
||||||
@ -35,16 +35,19 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Read operations must do rwlock(true)/rwunlock(true).
|
// Read operations must do rwlock(true)/rwunlock(true).
|
||||||
|
//
|
||||||
// Write operations must do rwlock(false)/rwunlock(false).
|
// Write operations must do rwlock(false)/rwunlock(false).
|
||||||
// Misc operations must do incref/decref. Misc operations include functions like
|
//
|
||||||
// setsockopt and setDeadline. They need to use incref/decref to ensure that
|
// Misc operations must do incref/decref.
|
||||||
// they operate on the correct fd in presence of a concurrent close call
|
// Misc operations include functions like setsockopt and setDeadline.
|
||||||
// (otherwise fd can be closed under their feet).
|
// They need to use incref/decref to ensure that they operate on the
|
||||||
// Close operation must do increfAndClose/decref.
|
// correct fd in presence of a concurrent close call (otherwise fd can
|
||||||
|
// be closed under their feet).
|
||||||
// rwlock/incref return whether fd is open.
|
//
|
||||||
// rwunlock/decref return whether fd is closed and there are no remaining references.
|
// Close operations must do increfAndClose/decref.
|
||||||
|
|
||||||
|
// incref adds a reference to mu.
|
||||||
|
// It reports whether mu is available for reading or writing.
|
||||||
func (mu *fdMutex) incref() bool {
|
func (mu *fdMutex) incref() bool {
|
||||||
for {
|
for {
|
||||||
old := atomic.LoadUint64(&mu.state)
|
old := atomic.LoadUint64(&mu.state)
|
||||||
@ -61,6 +64,8 @@ func (mu *fdMutex) incref() bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// increfAndClose sets the state of mu to closed.
|
||||||
|
// It reports whether there is no remaining reference.
|
||||||
func (mu *fdMutex) increfAndClose() bool {
|
func (mu *fdMutex) increfAndClose() bool {
|
||||||
for {
|
for {
|
||||||
old := atomic.LoadUint64(&mu.state)
|
old := atomic.LoadUint64(&mu.state)
|
||||||
@ -90,6 +95,8 @@ func (mu *fdMutex) increfAndClose() bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decref removes a reference from mu.
|
||||||
|
// It reports whether there is no remaining reference.
|
||||||
func (mu *fdMutex) decref() bool {
|
func (mu *fdMutex) decref() bool {
|
||||||
for {
|
for {
|
||||||
old := atomic.LoadUint64(&mu.state)
|
old := atomic.LoadUint64(&mu.state)
|
||||||
@ -103,6 +110,8 @@ func (mu *fdMutex) decref() bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lock adds a reference to mu and locks mu.
|
||||||
|
// It reports whether mu is available for reading or writing.
|
||||||
func (mu *fdMutex) rwlock(read bool) bool {
|
func (mu *fdMutex) rwlock(read bool) bool {
|
||||||
var mutexBit, mutexWait, mutexMask uint64
|
var mutexBit, mutexWait, mutexMask uint64
|
||||||
var mutexSema *uint32
|
var mutexSema *uint32
|
||||||
@ -146,6 +155,8 @@ func (mu *fdMutex) rwlock(read bool) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unlock removes a reference from mu and unlocks mu.
|
||||||
|
// It reports whether there is no remaining reference.
|
||||||
func (mu *fdMutex) rwunlock(read bool) bool {
|
func (mu *fdMutex) rwunlock(read bool) bool {
|
||||||
var mutexBit, mutexWait, mutexMask uint64
|
var mutexBit, mutexWait, mutexMask uint64
|
||||||
var mutexSema *uint32
|
var mutexSema *uint32
|
||||||
@ -182,3 +193,57 @@ func (mu *fdMutex) rwunlock(read bool) bool {
|
|||||||
// Implemented in runtime package.
|
// Implemented in runtime package.
|
||||||
func runtime_Semacquire(sema *uint32)
|
func runtime_Semacquire(sema *uint32)
|
||||||
func runtime_Semrelease(sema *uint32)
|
func runtime_Semrelease(sema *uint32)
|
||||||
|
|
||||||
|
// incref adds a reference to fd.
|
||||||
|
// It returns an error when fd cannot be used.
|
||||||
|
func (fd *netFD) incref() error {
|
||||||
|
if !fd.fdmu.incref() {
|
||||||
|
return errClosing
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decref removes a reference from fd.
|
||||||
|
// It also closes fd when the state of fd is set to closed and there
|
||||||
|
// is no remaining reference.
|
||||||
|
func (fd *netFD) decref() {
|
||||||
|
if fd.fdmu.decref() {
|
||||||
|
fd.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readLock adds a reference to fd and locks fd for reading.
|
||||||
|
// It returns an error when fd cannot be used for reading.
|
||||||
|
func (fd *netFD) readLock() error {
|
||||||
|
if !fd.fdmu.rwlock(true) {
|
||||||
|
return errClosing
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// readUnlock removes a reference from fd and unlocks fd for reading.
|
||||||
|
// It also closes fd when the state of fd is set to closed and there
|
||||||
|
// is no remaining reference.
|
||||||
|
func (fd *netFD) readUnlock() {
|
||||||
|
if fd.fdmu.rwunlock(true) {
|
||||||
|
fd.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeLock adds a reference to fd and locks fd for writing.
|
||||||
|
// It returns an error when fd cannot be used for writing.
|
||||||
|
func (fd *netFD) writeLock() error {
|
||||||
|
if !fd.fdmu.rwlock(false) {
|
||||||
|
return errClosing
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeUnlock removes a reference from fd and unlocks fd for writing.
|
||||||
|
// It also closes fd when the state of fd is set to closed and there
|
||||||
|
// is no remaining reference.
|
||||||
|
func (fd *netFD) writeUnlock() {
|
||||||
|
if fd.fdmu.rwunlock(false) {
|
||||||
|
fd.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -74,55 +74,6 @@ func (fd *netFD) destroy() {
|
|||||||
fd.data = nil
|
fd.data = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a reference to this fd.
|
|
||||||
// Returns an error if the fd cannot be used.
|
|
||||||
func (fd *netFD) incref() error {
|
|
||||||
if !fd.fdmu.incref() {
|
|
||||||
return errClosing
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove a reference to this FD and close if we've been asked to do so
|
|
||||||
// (and there are no references left).
|
|
||||||
func (fd *netFD) decref() {
|
|
||||||
if fd.fdmu.decref() {
|
|
||||||
fd.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a reference to this fd and lock for reading.
|
|
||||||
// Returns an error if the fd cannot be used.
|
|
||||||
func (fd *netFD) readLock() error {
|
|
||||||
if !fd.fdmu.rwlock(true) {
|
|
||||||
return errClosing
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlock for reading and remove a reference to this FD.
|
|
||||||
func (fd *netFD) readUnlock() {
|
|
||||||
if fd.fdmu.rwunlock(true) {
|
|
||||||
fd.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a reference to this fd and lock for writing.
|
|
||||||
// Returns an error if the fd cannot be used.
|
|
||||||
func (fd *netFD) writeLock() error {
|
|
||||||
if !fd.fdmu.rwlock(false) {
|
|
||||||
return errClosing
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlock for writing and remove a reference to this FD.
|
|
||||||
func (fd *netFD) writeUnlock() {
|
|
||||||
if fd.fdmu.rwunlock(false) {
|
|
||||||
fd.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fd *netFD) Read(b []byte) (n int, err error) {
|
func (fd *netFD) Read(b []byte) (n int, err error) {
|
||||||
if !fd.ok() || fd.data == nil {
|
if !fd.ok() || fd.data == nil {
|
||||||
return 0, syscall.EINVAL
|
return 0, syscall.EINVAL
|
||||||
|
@ -164,55 +164,6 @@ func (fd *netFD) destroy() {
|
|||||||
runtime.SetFinalizer(fd, nil)
|
runtime.SetFinalizer(fd, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a reference to this fd.
|
|
||||||
// Returns an error if the fd cannot be used.
|
|
||||||
func (fd *netFD) incref() error {
|
|
||||||
if !fd.fdmu.incref() {
|
|
||||||
return errClosing
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove a reference to this FD and close if we've been asked to do so
|
|
||||||
// (and there are no references left).
|
|
||||||
func (fd *netFD) decref() {
|
|
||||||
if fd.fdmu.decref() {
|
|
||||||
fd.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a reference to this fd and lock for reading.
|
|
||||||
// Returns an error if the fd cannot be used.
|
|
||||||
func (fd *netFD) readLock() error {
|
|
||||||
if !fd.fdmu.rwlock(true) {
|
|
||||||
return errClosing
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlock for reading and remove a reference to this FD.
|
|
||||||
func (fd *netFD) readUnlock() {
|
|
||||||
if fd.fdmu.rwunlock(true) {
|
|
||||||
fd.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a reference to this fd and lock for writing.
|
|
||||||
// Returns an error if the fd cannot be used.
|
|
||||||
func (fd *netFD) writeLock() error {
|
|
||||||
if !fd.fdmu.rwlock(false) {
|
|
||||||
return errClosing
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlock for writing and remove a reference to this FD.
|
|
||||||
func (fd *netFD) writeUnlock() {
|
|
||||||
if fd.fdmu.rwunlock(false) {
|
|
||||||
fd.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fd *netFD) Close() error {
|
func (fd *netFD) Close() error {
|
||||||
if !fd.fdmu.increfAndClose() {
|
if !fd.fdmu.increfAndClose() {
|
||||||
return errClosing
|
return errClosing
|
||||||
|
@ -395,55 +395,6 @@ func (fd *netFD) destroy() {
|
|||||||
runtime.SetFinalizer(fd, nil)
|
runtime.SetFinalizer(fd, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a reference to this fd.
|
|
||||||
// Returns an error if the fd cannot be used.
|
|
||||||
func (fd *netFD) incref() error {
|
|
||||||
if !fd.fdmu.incref() {
|
|
||||||
return errClosing
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove a reference to this FD and close if we've been asked to do so
|
|
||||||
// (and there are no references left).
|
|
||||||
func (fd *netFD) decref() {
|
|
||||||
if fd.fdmu.decref() {
|
|
||||||
fd.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a reference to this fd and lock for reading.
|
|
||||||
// Returns an error if the fd cannot be used.
|
|
||||||
func (fd *netFD) readLock() error {
|
|
||||||
if !fd.fdmu.rwlock(true) {
|
|
||||||
return errClosing
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlock for reading and remove a reference to this FD.
|
|
||||||
func (fd *netFD) readUnlock() {
|
|
||||||
if fd.fdmu.rwunlock(true) {
|
|
||||||
fd.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a reference to this fd and lock for writing.
|
|
||||||
// Returns an error if the fd cannot be used.
|
|
||||||
func (fd *netFD) writeLock() error {
|
|
||||||
if !fd.fdmu.rwlock(false) {
|
|
||||||
return errClosing
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlock for writing and remove a reference to this FD.
|
|
||||||
func (fd *netFD) writeUnlock() {
|
|
||||||
if fd.fdmu.rwunlock(false) {
|
|
||||||
fd.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fd *netFD) Close() error {
|
func (fd *netFD) Close() error {
|
||||||
if !fd.fdmu.increfAndClose() {
|
if !fd.fdmu.increfAndClose() {
|
||||||
return errClosing
|
return errClosing
|
||||||
|
Loading…
Reference in New Issue
Block a user