@@ -638,8 +638,8 @@ func (pd *pollDesc) wait(mode int, isFile bool) error {
638
638
#### 就续通知
639
639
640
640
``` go
641
- // polls for ready network connections
642
- // returns list of goroutines that become runnable
641
+ // poll 已经就绪的网络连接
642
+ // 返回那些已经可以跑的 goroutine 列表
643
643
func netpoll (block bool ) *g {
644
644
if epfd == -1 {
645
645
return nil
@@ -683,7 +683,7 @@ retry:
683
683
return gp.ptr ()
684
684
}
685
685
686
- // make pd ready, newly runnable goroutines (if any) are returned in rg/wg
686
+ // 让 pd 就续,新的可以运行的 goroutine 会 set 到 wg/rg
687
687
// May run during STW, so write barriers are not allowed.
688
688
// go:nowritebarrier
689
689
func netpollready (gpp *guintptr , pd *pollDesc , mode int32 ) {
@@ -1121,3 +1121,96 @@ func ready(gp *g, traceskip int, next bool) {
1121
1121
```
1122
1122
1123
1123
### 连接关闭
1124
+
1125
+ ``` go
1126
+ // Close closes the connection.
1127
+ func (c *conn ) Close () error {
1128
+ if !c.ok () {
1129
+ return syscall.EINVAL
1130
+ }
1131
+ err := c.fd .Close ()
1132
+ if err != nil {
1133
+ err = &OpError{Op: " close" , Net: c.fd .net , Source: c.fd .laddr , Addr: c.fd .raddr , Err: err}
1134
+ }
1135
+ return err
1136
+ }
1137
+ ```
1138
+
1139
+ ``` go
1140
+ func (fd *netFD ) Close () error {
1141
+ runtime.SetFinalizer (fd, nil )
1142
+ return fd.pfd .Close ()
1143
+ }
1144
+ ```
1145
+
1146
+ ``` go
1147
+ // Close closes the FD. The underlying file descriptor is closed by the
1148
+ // destroy method when there are no remaining references.
1149
+ func (fd *FD ) Close () error {
1150
+ if !fd.fdmu .increfAndClose () {
1151
+ return errClosing (fd.isFile )
1152
+ }
1153
+
1154
+ // Unblock any I/O. Once it all unblocks and returns,
1155
+ // so that it cannot be referring to fd.sysfd anymore,
1156
+ // the final decref will close fd.sysfd. This should happen
1157
+ // fairly quickly, since all the I/O is non-blocking, and any
1158
+ // attempts to block in the pollDesc will return errClosing(fd.isFile).
1159
+ fd.pd .evict ()
1160
+
1161
+ // The call to decref will call destroy if there are no other
1162
+ // references.
1163
+ err := fd.decref ()
1164
+
1165
+ // Wait until the descriptor is closed. If this was the only
1166
+ // reference, it is already closed. Only wait if the file has
1167
+ // not been set to blocking mode, as otherwise any current I/O
1168
+ // may be blocking, and that would block the Close.
1169
+ if !fd.isBlocking {
1170
+ runtime_Semacquire (&fd.csema )
1171
+ }
1172
+
1173
+ return err
1174
+ }
1175
+ ```
1176
+
1177
+ ``` go
1178
+ // Evict evicts fd from the pending list, unblocking any I/O running on fd.
1179
+ func (pd *pollDesc ) evict () {
1180
+ if pd.runtimeCtx == 0 {
1181
+ return
1182
+ }
1183
+ runtime_pollUnblock (pd.runtimeCtx )
1184
+ }
1185
+ ```
1186
+
1187
+ ``` go
1188
+ // go:linkname poll_runtime_pollUnblock internal/poll.runtime_pollUnblock
1189
+ func poll_runtime_pollUnblock (pd *pollDesc ) {
1190
+ lock (&pd.lock )
1191
+ if pd.closing {
1192
+ throw (" runtime: unblock on closing polldesc" )
1193
+ }
1194
+ pd.closing = true
1195
+ pd.seq ++
1196
+ var rg , wg *g
1197
+ atomicstorep (unsafe.Pointer (&rg), nil ) // full memory barrier between store to closing and read of rg/wg in netpollunblock
1198
+ rg = netpollunblock (pd, ' r' , false )
1199
+ wg = netpollunblock (pd, ' w' , false )
1200
+ if pd.rt .f != nil {
1201
+ deltimer (&pd.rt )
1202
+ pd.rt .f = nil
1203
+ }
1204
+ if pd.wt .f != nil {
1205
+ deltimer (&pd.wt )
1206
+ pd.wt .f = nil
1207
+ }
1208
+ unlock (&pd.lock )
1209
+ if rg != nil {
1210
+ netpollgoready (rg, 3 )
1211
+ }
1212
+ if wg != nil {
1213
+ netpollgoready (wg, 3 )
1214
+ }
1215
+ }
1216
+ ```
0 commit comments