LEFT | RIGHT |
1 // Copyright 2013 The Go Authors. All rights reserved. | 1 // Copyright 2013 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package net | 5 package net |
6 | 6 |
7 import "sync/atomic" | 7 import "sync/atomic" |
8 | 8 |
9 // fdMutex is a specialized synchronization primitive | 9 // fdMutex is a specialized synchronization primitive |
10 // that manages lifetime of fd and serializes access | 10 // that manages lifetime of an fd and serializes access |
11 // to Read and Write methods on netFD. | 11 // to Read and Write methods on netFD. |
12 type fdMutex struct { | 12 type fdMutex struct { |
13 state uint64 | 13 state uint64 |
14 rsema uint32 | 14 rsema uint32 |
15 wsema uint32 | 15 wsema uint32 |
16 } | 16 } |
17 | 17 |
18 // fdMutex.state is organized as follows: | 18 // fdMutex.state is organized as follows: |
19 // 1 bit - whether netFD is closed, if set all subsequent lock operations will f
ail. | 19 // 1 bit - whether netFD is closed, if set all subsequent lock operations will f
ail. |
20 // 1 bit - lock for read operations. | 20 // 1 bit - lock for read operations. |
(...skipping 14 matching lines...) Expand all Loading... |
35 ) | 35 ) |
36 | 36 |
37 // Read operations must do RWLock(true)/RWUnlock(true). | 37 // Read operations must do RWLock(true)/RWUnlock(true). |
38 // Write operations must do RWLock(false)/RWUnlock(false). | 38 // Write operations must do RWLock(false)/RWUnlock(false). |
39 // Misc operations must do Incref/Decref. Misc operations include functions like | 39 // Misc operations must do Incref/Decref. Misc operations include functions like |
40 // setsockopt and setDeadline. They need to use Incref/Decref to ensure that | 40 // setsockopt and setDeadline. They need to use Incref/Decref to ensure that |
41 // they operate on the correct fd in presence of a concurrent Close call | 41 // they operate on the correct fd in presence of a concurrent Close call |
42 // (otherwise fd can be closed under their feet). | 42 // (otherwise fd can be closed under their feet). |
43 // Close operation must do IncrefAndClose/Decref. | 43 // Close operation must do IncrefAndClose/Decref. |
44 | 44 |
45 // All lock operations return false if fd is closed. | |
46 // All unlock operations return true if fd is closed and it has dropped the last
reference. | |
47 | |
48 // RWLock/Incref return whether fd is open. | 45 // RWLock/Incref return whether fd is open. |
49 // RWUnlock/Decref return whether fd is closed and there are no remaining refere
nces. | 46 // RWUnlock/Decref return whether fd is closed and there are no remaining refere
nces. |
50 | 47 |
51 func (mu *fdMutex) Incref() bool { | 48 func (mu *fdMutex) Incref() bool { |
52 for { | 49 for { |
53 old := atomic.LoadUint64(&mu.state) | 50 old := atomic.LoadUint64(&mu.state) |
54 if old&mutexClosed != 0 { | 51 if old&mutexClosed != 0 { |
55 return false | 52 return false |
56 } | 53 } |
57 new := old + mutexRef | 54 new := old + mutexRef |
(...skipping 11 matching lines...) Expand all Loading... |
69 old := atomic.LoadUint64(&mu.state) | 66 old := atomic.LoadUint64(&mu.state) |
70 if old&mutexClosed != 0 { | 67 if old&mutexClosed != 0 { |
71 return false | 68 return false |
72 } | 69 } |
73 // Mark as closed and acquire a reference. | 70 // Mark as closed and acquire a reference. |
74 new := (old | mutexClosed) + mutexRef | 71 new := (old | mutexClosed) + mutexRef |
75 if new&mutexRefMask == 0 { | 72 if new&mutexRefMask == 0 { |
76 panic("net: inconsistent fdMutex") | 73 panic("net: inconsistent fdMutex") |
77 } | 74 } |
78 // Remove all read and write waiters. | 75 // Remove all read and write waiters. |
79 » » new &= ^uint64(mutexRMask | mutexWMask) | 76 » » new &^= mutexRMask | mutexWMask |
80 if atomic.CompareAndSwapUint64(&mu.state, old, new) { | 77 if atomic.CompareAndSwapUint64(&mu.state, old, new) { |
81 // Wake all read and write waiters, | 78 // Wake all read and write waiters, |
82 // they will observe closed flag after wakeup. | 79 // they will observe closed flag after wakeup. |
83 for old&mutexRMask != 0 { | 80 for old&mutexRMask != 0 { |
84 old -= mutexRWait | 81 old -= mutexRWait |
85 runtime_Semrelease(&mu.rsema) | 82 runtime_Semrelease(&mu.rsema) |
86 } | 83 } |
87 for old&mutexWMask != 0 { | 84 for old&mutexWMask != 0 { |
88 old -= mutexWWait | 85 old -= mutexWWait |
89 runtime_Semrelease(&mu.wsema) | 86 runtime_Semrelease(&mu.wsema) |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 runtime_Semrelease(mutexSema) | 175 runtime_Semrelease(mutexSema) |
179 } | 176 } |
180 return new&(mutexClosed|mutexRef) == mutexClosed | 177 return new&(mutexClosed|mutexRef) == mutexClosed |
181 } | 178 } |
182 } | 179 } |
183 } | 180 } |
184 | 181 |
185 // Implemented in runtime package. | 182 // Implemented in runtime package. |
186 func runtime_Semacquire(sema *uint32) | 183 func runtime_Semacquire(sema *uint32) |
187 func runtime_Semrelease(sema *uint32) | 184 func runtime_Semrelease(sema *uint32) |
LEFT | RIGHT |