diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/runtime/mcache.c | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/runtime/mcache.c')
-rw-r--r-- | src/runtime/mcache.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/runtime/mcache.c b/src/runtime/mcache.c new file mode 100644 index 000000000..5fdbe3266 --- /dev/null +++ b/src/runtime/mcache.c @@ -0,0 +1,115 @@ +// 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. + +// Per-P malloc cache for small objects. +// +// See malloc.h for an overview. + +#include "runtime.h" +#include "arch_GOARCH.h" +#include "malloc.h" + +extern volatile intgo runtime·MemProfileRate; + +// dummy MSpan that contains no free objects. +MSpan runtime·emptymspan; + +MCache* +runtime·allocmcache(void) +{ + intgo rate; + MCache *c; + int32 i; + + runtime·lock(&runtime·mheap.lock); + c = runtime·FixAlloc_Alloc(&runtime·mheap.cachealloc); + runtime·unlock(&runtime·mheap.lock); + runtime·memclr((byte*)c, sizeof(*c)); + for(i = 0; i < NumSizeClasses; i++) + c->alloc[i] = &runtime·emptymspan; + + // Set first allocation sample size. + rate = runtime·MemProfileRate; + if(rate > 0x3fffffff) // make 2*rate not overflow + rate = 0x3fffffff; + if(rate != 0) + c->next_sample = runtime·fastrand1() % (2*rate); + + return c; +} + +static void +freemcache(MCache *c) +{ + runtime·MCache_ReleaseAll(c); + runtime·stackcache_clear(c); + runtime·gcworkbuffree(c->gcworkbuf); + runtime·lock(&runtime·mheap.lock); + runtime·purgecachedstats(c); + runtime·FixAlloc_Free(&runtime·mheap.cachealloc, c); + runtime·unlock(&runtime·mheap.lock); +} + +static void +freemcache_m(void) +{ + MCache *c; + + c = g->m->ptrarg[0]; + g->m->ptrarg[0] = nil; + freemcache(c); +} + +void +runtime·freemcache(MCache *c) +{ + void (*fn)(void); + + g->m->ptrarg[0] = c; + fn = freemcache_m; + runtime·onM(&fn); +} + +// Gets a span that has a free object in it and assigns it +// to be the cached span for the given sizeclass. Returns this span. +MSpan* +runtime·MCache_Refill(MCache *c, int32 sizeclass) +{ + MSpan *s; + + g->m->locks++; + // Return the current cached span to the central lists. + s = c->alloc[sizeclass]; + if(s->freelist != nil) + runtime·throw("refill on a nonempty span"); + if(s != &runtime·emptymspan) + s->incache = false; + + // Get a new cached span from the central lists. + s = runtime·MCentral_CacheSpan(&runtime·mheap.central[sizeclass].mcentral); + if(s == nil) + runtime·throw("out of memory"); + if(s->freelist == nil) { + runtime·printf("%d %d\n", s->ref, (int32)((s->npages << PageShift) / s->elemsize)); + runtime·throw("empty span"); + } + c->alloc[sizeclass] = s; + g->m->locks--; + return s; +} + +void +runtime·MCache_ReleaseAll(MCache *c) +{ + int32 i; + MSpan *s; + + for(i=0; i<NumSizeClasses; i++) { + s = c->alloc[i]; + if(s != &runtime·emptymspan) { + runtime·MCentral_UncacheSpan(&runtime·mheap.central[i].mcentral, s); + c->alloc[i] = &runtime·emptymspan; + } + } +} |