@@ -79,16 +79,17 @@ type pollDesc struct {
79
79
lock mutex // protects the following fields
80
80
fd uintptr
81
81
closing bool
82
- everr bool // marks event scanning error happened
83
- user uint32 // user settable cookie
84
- rseq uintptr // protects from stale read timers
85
- rg uintptr // pdReady, pdWait, G waiting for read or nil
86
- rt timer // read deadline timer (set if rt.f != nil)
87
- rd int64 // read deadline
88
- wseq uintptr // protects from stale write timers
89
- wg uintptr // pdReady, pdWait, G waiting for write or nil
90
- wt timer // write deadline timer
91
- wd int64 // write deadline
82
+ everr bool // marks event scanning error happened
83
+ user uint32 // user settable cookie
84
+ rseq uintptr // protects from stale read timers
85
+ rg uintptr // pdReady, pdWait, G waiting for read or nil
86
+ rt timer // read deadline timer (set if rt.f != nil)
87
+ rd int64 // read deadline
88
+ wseq uintptr // protects from stale write timers
89
+ wg uintptr // pdReady, pdWait, G waiting for write or nil
90
+ wt timer // write deadline timer
91
+ wd int64 // write deadline
92
+ self * pollDesc // storage for indirect interface. See (*pollDesc).makeArg.
92
93
}
93
94
94
95
type pollCache struct {
@@ -157,6 +158,7 @@ func poll_runtime_pollOpen(fd uintptr) (*pollDesc, int) {
157
158
pd .wseq ++
158
159
pd .wg = 0
159
160
pd .wd = 0
161
+ pd .self = pd
160
162
unlock (& pd .lock )
161
163
162
164
var errno int32
@@ -271,14 +273,14 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
271
273
// Copy current seq into the timer arg.
272
274
// Timer func will check the seq against current descriptor seq,
273
275
// if they differ the descriptor was reused or timers were reset.
274
- pd .rt .arg = pd
276
+ pd .rt .arg = pd . makeArg ()
275
277
pd .rt .seq = pd .rseq
276
278
resettimer (& pd .rt , pd .rd )
277
279
}
278
280
} else if pd .rd != rd0 || combo != combo0 {
279
281
pd .rseq ++ // invalidate current timers
280
282
if pd .rd > 0 {
281
- modtimer (& pd .rt , pd .rd , 0 , rtf , pd , pd .rseq )
283
+ modtimer (& pd .rt , pd .rd , 0 , rtf , pd . makeArg () , pd .rseq )
282
284
} else {
283
285
deltimer (& pd .rt )
284
286
pd .rt .f = nil
@@ -287,14 +289,14 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
287
289
if pd .wt .f == nil {
288
290
if pd .wd > 0 && ! combo {
289
291
pd .wt .f = netpollWriteDeadline
290
- pd .wt .arg = pd
292
+ pd .wt .arg = pd . makeArg ()
291
293
pd .wt .seq = pd .wseq
292
294
resettimer (& pd .wt , pd .wd )
293
295
}
294
296
} else if pd .wd != wd0 || combo != combo0 {
295
297
pd .wseq ++ // invalidate current timers
296
298
if pd .wd > 0 && ! combo {
297
- modtimer (& pd .wt , pd .wd , 0 , netpollWriteDeadline , pd , pd .wseq )
299
+ modtimer (& pd .wt , pd .wd , 0 , netpollWriteDeadline , pd . makeArg () , pd .wseq )
298
300
} else {
299
301
deltimer (& pd .wt )
300
302
pd .wt .f = nil
@@ -547,3 +549,20 @@ func (c *pollCache) alloc() *pollDesc {
547
549
unlock (& c .lock )
548
550
return pd
549
551
}
552
+
553
+ // makeArg converts pd to an interface{}.
554
+ // makeArg does not do any allocation. Normally, such
555
+ // a conversion requires an allocation because pointers to
556
+ // go:notinheap types (which pollDesc is) must be stored
557
+ // in interfaces indirectly. See issue 42076.
558
+ func (pd * pollDesc ) makeArg () (i interface {}) {
559
+ x := (* eface )(unsafe .Pointer (& i ))
560
+ x ._type = pdType
561
+ x .data = unsafe .Pointer (& pd .self )
562
+ return
563
+ }
564
+
565
+ var (
566
+ pdEface interface {} = (* pollDesc )(nil )
567
+ pdType * _type = efaceOf (& pdEface )._type
568
+ )
0 commit comments