iter, exists := span.specialFindSplicePoint(offset, _KindSpecialCleanup)
if exists {
- for s := *iter; s != nil && offset == uintptr(s.offset); iter = &s.next {
- if (*specialCleanup)(unsafe.Pointer(s)).id == c.id {
+ for {
+ s := *iter
+ if s == nil {
+ // Reached the end of the linked list. Stop searching at this point.
+ break
+ }
+ if offset == uintptr(s.offset) && _KindSpecialCleanup == s.kind &&
+ (*specialCleanup)(unsafe.Pointer(s)).id == c.id {
+ // The special is a cleanup and contains a matching cleanup id.
*iter = s.next
found = s
break
}
+ if offset < uintptr(s.offset) || (offset == uintptr(s.offset) && _KindSpecialCleanup < s.kind) {
+ // The special is outside the region specified for that kind of
+ // special. The specials are sorted by kind.
+ break
+ }
+ // Try the next special.
+ iter = &s.next
}
}
if span.specials == nil {
mp := acquirem()
addspecial(p, &s.special, true)
- releasem(mp)
// This is responsible for maintaining the same
// GC-related invariants as markrootSpans in any
// situation where it's possible that markrootSpans
// special isn't part of the GC'd heap.
scanblock(uintptr(unsafe.Pointer(&s.fn)), goarch.PtrSize, &oneptrmask[0], gcw, nil)
}
+ releasem(mp)
// Keep f alive. There's a window in this function where it's
// only reachable via the special while the special hasn't been
// added to the specials list yet. This is similar to a bug