diff options
Diffstat (limited to 'src/runtime/mcentral.c')
-rw-r--r-- | src/runtime/mcentral.c | 214 |
1 files changed, 0 insertions, 214 deletions
diff --git a/src/runtime/mcentral.c b/src/runtime/mcentral.c deleted file mode 100644 index fe6bcfeb1..000000000 --- a/src/runtime/mcentral.c +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Central free lists. -// -// See malloc.h for an overview. -// -// The MCentral doesn't actually contain the list of free objects; the MSpan does. -// Each MCentral is two lists of MSpans: those with free objects (c->nonempty) -// and those that are completely allocated (c->empty). - -#include "runtime.h" -#include "arch_GOARCH.h" -#include "malloc.h" - -static MSpan* MCentral_Grow(MCentral *c); - -// Initialize a single central free list. -void -runtime·MCentral_Init(MCentral *c, int32 sizeclass) -{ - c->sizeclass = sizeclass; - runtime·MSpanList_Init(&c->nonempty); - runtime·MSpanList_Init(&c->empty); -} - -// Allocate a span to use in an MCache. -MSpan* -runtime·MCentral_CacheSpan(MCentral *c) -{ - MSpan *s; - int32 cap, n; - uint32 sg; - - runtime·lock(&c->lock); - sg = runtime·mheap.sweepgen; -retry: - for(s = c->nonempty.next; s != &c->nonempty; s = s->next) { - if(s->sweepgen == sg-2 && runtime·cas(&s->sweepgen, sg-2, sg-1)) { - runtime·MSpanList_Remove(s); - runtime·MSpanList_InsertBack(&c->empty, s); - runtime·unlock(&c->lock); - runtime·MSpan_Sweep(s, true); - goto havespan; - } - if(s->sweepgen == sg-1) { - // the span is being swept by background sweeper, skip - continue; - } - // we have a nonempty span that does not require sweeping, allocate from it - runtime·MSpanList_Remove(s); - runtime·MSpanList_InsertBack(&c->empty, s); - runtime·unlock(&c->lock); - goto havespan; - } - - for(s = c->empty.next; s != &c->empty; s = s->next) { - if(s->sweepgen == sg-2 && runtime·cas(&s->sweepgen, sg-2, sg-1)) { - // we have an empty span that requires sweeping, - // sweep it and see if we can free some space in it - runtime·MSpanList_Remove(s); - // swept spans are at the end of the list - runtime·MSpanList_InsertBack(&c->empty, s); - runtime·unlock(&c->lock); - runtime·MSpan_Sweep(s, true); - if(s->freelist != nil) - goto havespan; - runtime·lock(&c->lock); - // the span is still empty after sweep - // it is already in the empty list, so just retry - goto retry; - } - if(s->sweepgen == sg-1) { - // the span is being swept by background sweeper, skip - continue; - } - // already swept empty span, - // all subsequent ones must also be either swept or in process of sweeping - break; - } - runtime·unlock(&c->lock); - - // Replenish central list if empty. - s = MCentral_Grow(c); - if(s == nil) - return nil; - runtime·lock(&c->lock); - runtime·MSpanList_InsertBack(&c->empty, s); - runtime·unlock(&c->lock); - -havespan: - // At this point s is a non-empty span, queued at the end of the empty list, - // c is unlocked. - cap = (s->npages << PageShift) / s->elemsize; - n = cap - s->ref; - if(n == 0) - runtime·throw("empty span"); - if(s->freelist == nil) - runtime·throw("freelist empty"); - s->incache = true; - return s; -} - -// Return span from an MCache. -void -runtime·MCentral_UncacheSpan(MCentral *c, MSpan *s) -{ - int32 cap, n; - - runtime·lock(&c->lock); - - s->incache = false; - - if(s->ref == 0) - runtime·throw("uncaching full span"); - - cap = (s->npages << PageShift) / s->elemsize; - n = cap - s->ref; - if(n > 0) { - runtime·MSpanList_Remove(s); - runtime·MSpanList_Insert(&c->nonempty, s); - } - runtime·unlock(&c->lock); -} - -// Free n objects from a span s back into the central free list c. -// Called during sweep. -// Returns true if the span was returned to heap. Sets sweepgen to -// the latest generation. -// If preserve=true, don't return the span to heap nor relink in MCentral lists; -// caller takes care of it. -bool -runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end, bool preserve) -{ - bool wasempty; - - if(s->incache) - runtime·throw("freespan into cached span"); - - // Add the objects back to s's free list. - wasempty = s->freelist == nil; - end->next = s->freelist; - s->freelist = start; - s->ref -= n; - - if(preserve) { - // preserve is set only when called from MCentral_CacheSpan above, - // the span must be in the empty list. - if(s->next == nil) - runtime·throw("can't preserve unlinked span"); - runtime·atomicstore(&s->sweepgen, runtime·mheap.sweepgen); - return false; - } - - runtime·lock(&c->lock); - - // Move to nonempty if necessary. - if(wasempty) { - runtime·MSpanList_Remove(s); - runtime·MSpanList_Insert(&c->nonempty, s); - } - - // delay updating sweepgen until here. This is the signal that - // the span may be used in an MCache, so it must come after the - // linked list operations above (actually, just after the - // lock of c above.) - runtime·atomicstore(&s->sweepgen, runtime·mheap.sweepgen); - - if(s->ref != 0) { - runtime·unlock(&c->lock); - return false; - } - - // s is completely freed, return it to the heap. - runtime·MSpanList_Remove(s); - s->needzero = 1; - s->freelist = nil; - runtime·unlock(&c->lock); - runtime·unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift); - runtime·MHeap_Free(&runtime·mheap, s, 0); - return true; -} - -// Fetch a new span from the heap and carve into objects for the free list. -static MSpan* -MCentral_Grow(MCentral *c) -{ - uintptr size, npages, i, n; - MLink **tailp, *v; - byte *p; - MSpan *s; - - npages = runtime·class_to_allocnpages[c->sizeclass]; - size = runtime·class_to_size[c->sizeclass]; - n = (npages << PageShift) / size; - s = runtime·MHeap_Alloc(&runtime·mheap, npages, c->sizeclass, 0, 1); - if(s == nil) - return nil; - - // Carve span into sequence of blocks. - tailp = &s->freelist; - p = (byte*)(s->start << PageShift); - s->limit = p + size*n; - for(i=0; i<n; i++) { - v = (MLink*)p; - *tailp = v; - tailp = &v->next; - p += size; - } - *tailp = nil; - runtime·markspan((byte*)(s->start<<PageShift), size, n, size*n < (s->npages<<PageShift)); - return s; -} |