diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/pkg/net/fd_mutex.go | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/pkg/net/fd_mutex.go')
-rw-r--r-- | src/pkg/net/fd_mutex.go | 184 |
1 files changed, 0 insertions, 184 deletions
diff --git a/src/pkg/net/fd_mutex.go b/src/pkg/net/fd_mutex.go deleted file mode 100644 index 6d5509d7f..000000000 --- a/src/pkg/net/fd_mutex.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2013 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 net - -import "sync/atomic" - -// fdMutex is a specialized synchronization primitive -// that manages lifetime of an fd and serializes access -// to Read and Write methods on netFD. -type fdMutex struct { - state uint64 - rsema uint32 - wsema uint32 -} - -// fdMutex.state is organized as follows: -// 1 bit - whether netFD is closed, if set all subsequent lock operations will fail. -// 1 bit - lock for read operations. -// 1 bit - lock for write operations. -// 20 bits - total number of references (read+write+misc). -// 20 bits - number of outstanding read waiters. -// 20 bits - number of outstanding write waiters. -const ( - mutexClosed = 1 << 0 - mutexRLock = 1 << 1 - mutexWLock = 1 << 2 - mutexRef = 1 << 3 - mutexRefMask = (1<<20 - 1) << 3 - mutexRWait = 1 << 23 - mutexRMask = (1<<20 - 1) << 23 - mutexWWait = 1 << 43 - mutexWMask = (1<<20 - 1) << 43 -) - -// Read operations must do RWLock(true)/RWUnlock(true). -// 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 -// they operate on the correct fd in presence of a concurrent Close call -// (otherwise fd can be closed under their feet). -// Close operation must do IncrefAndClose/Decref. - -// RWLock/Incref return whether fd is open. -// RWUnlock/Decref return whether fd is closed and there are no remaining references. - -func (mu *fdMutex) Incref() bool { - for { - old := atomic.LoadUint64(&mu.state) - if old&mutexClosed != 0 { - return false - } - new := old + mutexRef - if new&mutexRefMask == 0 { - panic("net: inconsistent fdMutex") - } - if atomic.CompareAndSwapUint64(&mu.state, old, new) { - return true - } - } -} - -func (mu *fdMutex) IncrefAndClose() bool { - for { - old := atomic.LoadUint64(&mu.state) - if old&mutexClosed != 0 { - return false - } - // Mark as closed and acquire a reference. - new := (old | mutexClosed) + mutexRef - if new&mutexRefMask == 0 { - panic("net: inconsistent fdMutex") - } - // Remove all read and write waiters. - new &^= mutexRMask | mutexWMask - if atomic.CompareAndSwapUint64(&mu.state, old, new) { - // Wake all read and write waiters, - // they will observe closed flag after wakeup. - for old&mutexRMask != 0 { - old -= mutexRWait - runtime_Semrelease(&mu.rsema) - } - for old&mutexWMask != 0 { - old -= mutexWWait - runtime_Semrelease(&mu.wsema) - } - return true - } - } -} - -func (mu *fdMutex) Decref() bool { - for { - old := atomic.LoadUint64(&mu.state) - if old&mutexRefMask == 0 { - panic("net: inconsistent fdMutex") - } - new := old - mutexRef - if atomic.CompareAndSwapUint64(&mu.state, old, new) { - return new&(mutexClosed|mutexRefMask) == mutexClosed - } - } -} - -func (mu *fdMutex) RWLock(read bool) bool { - var mutexBit, mutexWait, mutexMask uint64 - var mutexSema *uint32 - if read { - mutexBit = mutexRLock - mutexWait = mutexRWait - mutexMask = mutexRMask - mutexSema = &mu.rsema - } else { - mutexBit = mutexWLock - mutexWait = mutexWWait - mutexMask = mutexWMask - mutexSema = &mu.wsema - } - for { - old := atomic.LoadUint64(&mu.state) - if old&mutexClosed != 0 { - return false - } - var new uint64 - if old&mutexBit == 0 { - // Lock is free, acquire it. - new = (old | mutexBit) + mutexRef - if new&mutexRefMask == 0 { - panic("net: inconsistent fdMutex") - } - } else { - // Wait for lock. - new = old + mutexWait - if new&mutexMask == 0 { - panic("net: inconsistent fdMutex") - } - } - if atomic.CompareAndSwapUint64(&mu.state, old, new) { - if old&mutexBit == 0 { - return true - } - runtime_Semacquire(mutexSema) - // The signaller has subtracted mutexWait. - } - } -} - -func (mu *fdMutex) RWUnlock(read bool) bool { - var mutexBit, mutexWait, mutexMask uint64 - var mutexSema *uint32 - if read { - mutexBit = mutexRLock - mutexWait = mutexRWait - mutexMask = mutexRMask - mutexSema = &mu.rsema - } else { - mutexBit = mutexWLock - mutexWait = mutexWWait - mutexMask = mutexWMask - mutexSema = &mu.wsema - } - for { - old := atomic.LoadUint64(&mu.state) - if old&mutexBit == 0 || old&mutexRefMask == 0 { - panic("net: inconsistent fdMutex") - } - // Drop lock, drop reference and wake read waiter if present. - new := (old &^ mutexBit) - mutexRef - if old&mutexMask != 0 { - new -= mutexWait - } - if atomic.CompareAndSwapUint64(&mu.state, old, new) { - if old&mutexMask != 0 { - runtime_Semrelease(mutexSema) - } - return new&(mutexClosed|mutexRefMask) == mutexClosed - } - } -} - -// Implemented in runtime package. -func runtime_Semacquire(sema *uint32) -func runtime_Semrelease(sema *uint32) |