github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/runtime/mcache.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Per-P malloc cache for small objects. 6 // 7 // See malloc.h for an overview. 8 9 #include "runtime.h" 10 #include "arch.h" 11 #include "malloc.h" 12 13 extern volatile intgo runtime_MemProfileRate 14 __asm__ (GOSYM_PREFIX "runtime.MemProfileRate"); 15 16 // dummy MSpan that contains no free objects. 17 static MSpan emptymspan; 18 19 MCache* 20 runtime_allocmcache(void) 21 { 22 intgo rate; 23 MCache *c; 24 int32 i; 25 26 runtime_lock(&runtime_mheap.lock); 27 c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc); 28 runtime_unlock(&runtime_mheap.lock); 29 runtime_memclr((byte*)c, sizeof(*c)); 30 for(i = 0; i < NumSizeClasses; i++) 31 c->alloc[i] = &emptymspan; 32 33 // Set first allocation sample size. 34 rate = runtime_MemProfileRate; 35 if(rate > 0x3fffffff) // make 2*rate not overflow 36 rate = 0x3fffffff; 37 if(rate != 0) 38 c->next_sample = runtime_fastrand1() % (2*rate); 39 40 return c; 41 } 42 43 void 44 runtime_freemcache(MCache *c) 45 { 46 runtime_MCache_ReleaseAll(c); 47 runtime_lock(&runtime_mheap.lock); 48 runtime_purgecachedstats(c); 49 runtime_FixAlloc_Free(&runtime_mheap.cachealloc, c); 50 runtime_unlock(&runtime_mheap.lock); 51 } 52 53 // Gets a span that has a free object in it and assigns it 54 // to be the cached span for the given sizeclass. Returns this span. 55 MSpan* 56 runtime_MCache_Refill(MCache *c, int32 sizeclass) 57 { 58 MCacheList *l; 59 MSpan *s; 60 61 runtime_m()->locks++; 62 // Return the current cached span to the central lists. 63 s = c->alloc[sizeclass]; 64 if(s->freelist != nil) 65 runtime_throw("refill on a nonempty span"); 66 if(s != &emptymspan) 67 runtime_MCentral_UncacheSpan(&runtime_mheap.central[sizeclass].mcentral, s); 68 69 // Push any explicitly freed objects to the central lists. 70 // Not required, but it seems like a good time to do it. 71 l = &c->free[sizeclass]; 72 if(l->nlist > 0) { 73 runtime_MCentral_FreeList(&runtime_mheap.central[sizeclass].mcentral, l->list); 74 l->list = nil; 75 l->nlist = 0; 76 } 77 78 // Get a new cached span from the central lists. 79 s = runtime_MCentral_CacheSpan(&runtime_mheap.central[sizeclass].mcentral); 80 if(s == nil) 81 runtime_throw("out of memory"); 82 if(s->freelist == nil) { 83 runtime_printf("%d %d\n", s->ref, (int32)((s->npages << PageShift) / s->elemsize)); 84 runtime_throw("empty span"); 85 } 86 c->alloc[sizeclass] = s; 87 runtime_m()->locks--; 88 return s; 89 } 90 91 void 92 runtime_MCache_Free(MCache *c, MLink *p, int32 sizeclass, uintptr size) 93 { 94 MCacheList *l; 95 96 // Put on free list. 97 l = &c->free[sizeclass]; 98 p->next = l->list; 99 l->list = p; 100 l->nlist++; 101 102 // We transfer a span at a time from MCentral to MCache, 103 // so we'll do the same in the other direction. 104 if(l->nlist >= (runtime_class_to_allocnpages[sizeclass]<<PageShift)/size) { 105 runtime_MCentral_FreeList(&runtime_mheap.central[sizeclass].mcentral, l->list); 106 l->list = nil; 107 l->nlist = 0; 108 } 109 } 110 111 void 112 runtime_MCache_ReleaseAll(MCache *c) 113 { 114 int32 i; 115 MSpan *s; 116 MCacheList *l; 117 118 for(i=0; i<NumSizeClasses; i++) { 119 s = c->alloc[i]; 120 if(s != &emptymspan) { 121 runtime_MCentral_UncacheSpan(&runtime_mheap.central[i].mcentral, s); 122 c->alloc[i] = &emptymspan; 123 } 124 l = &c->free[i]; 125 if(l->nlist > 0) { 126 runtime_MCentral_FreeList(&runtime_mheap.central[i].mcentral, l->list); 127 l->list = nil; 128 l->nlist = 0; 129 } 130 } 131 }