{
uint32 sg;
+ // Caller must disable preemption.
+ // Otherwise when this function returns the span can become unswept again
+ // (if GC is triggered on another goroutine).
+ if(m->locks == 0 && m->mallocing == 0)
+ runtime·throw("MSpan_EnsureSwept: m is not locked");
+
sg = runtime·mheap.sweepgen;
if(runtime·atomicload(&s->sweepgen) == sg)
return;
- m->locks++;
if(runtime·cas(&s->sweepgen, sg-2, sg-1)) {
runtime·MSpan_Sweep(s);
- m->locks--;
return;
}
- m->locks--;
// unfortunate condition, and we don't have efficient means to wait
while(runtime·atomicload(&s->sweepgen) != sg)
runtime·osyield();
// Ensure that the span is swept.
// GC accesses specials list w/o locks. And it's just much safer.
+ m->locks++;
runtime·MSpan_EnsureSwept(span);
offset = (uintptr)p - (span->start << PageShift);
while((x = *t) != nil) {
if(offset == x->offset && kind == x->kind) {
runtime·unlock(&span->specialLock);
+ m->locks--;
return false; // already exists
}
if(offset < x->offset || (offset == x->offset && kind < x->kind))
s->next = x;
*t = s;
runtime·unlock(&span->specialLock);
+ m->locks--;
return true;
}
// Ensure that the span is swept.
// GC accesses specials list w/o locks. And it's just much safer.
+ m->locks++;
runtime·MSpan_EnsureSwept(span);
offset = (uintptr)p - (span->start << PageShift);
if(offset == s->offset && kind == s->kind) {
*t = s->next;
runtime·unlock(&span->specialLock);
+ m->locks--;
return s;
}
t = &s->next;
}
runtime·unlock(&span->specialLock);
+ m->locks--;
return nil;
}
Special *s, **t, *list;
uintptr offset;
+ if(span->sweepgen != runtime·mheap.sweepgen)
+ runtime·throw("runtime: freeallspecials: unswept span");
// first, collect all specials into the list; then, free them
// this is required to not cause deadlock between span->specialLock and proflock
list = nil;