github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/runtime/mcache.go (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 package runtime 10 11 import "unsafe" 12 13 // dummy MSpan that contains no free objects. 14 var emptymspan mspan 15 16 func allocmcache() *mcache { 17 lock(&mheap_.lock) 18 c := (*mcache)(fixAlloc_Alloc(&mheap_.cachealloc)) 19 unlock(&mheap_.lock) 20 memclr(unsafe.Pointer(c), unsafe.Sizeof(*c)) 21 for i := 0; i < _NumSizeClasses; i++ { 22 c.alloc[i] = &emptymspan 23 } 24 25 // Set first allocation sample size. 26 rate := MemProfileRate 27 if rate > 0x3fffffff { // make 2*rate not overflow 28 rate = 0x3fffffff 29 } 30 if rate != 0 { 31 c.next_sample = int32(int(fastrand1()) % (2 * rate)) 32 } 33 34 return c 35 } 36 37 func freemcache(c *mcache) { 38 systemstack(func() { 39 mCache_ReleaseAll(c) 40 stackcache_clear(c) 41 42 // NOTE(rsc,rlh): If gcworkbuffree comes back, we need to coordinate 43 // with the stealing of gcworkbufs during garbage collection to avoid 44 // a race where the workbuf is double-freed. 45 // gcworkbuffree(c.gcworkbuf) 46 47 lock(&mheap_.lock) 48 purgecachedstats(c) 49 fixAlloc_Free(&mheap_.cachealloc, unsafe.Pointer(c)) 50 unlock(&mheap_.lock) 51 }) 52 } 53 54 // Gets a span that has a free object in it and assigns it 55 // to be the cached span for the given sizeclass. Returns this span. 56 func mCache_Refill(c *mcache, sizeclass int32) *mspan { 57 _g_ := getg() 58 59 _g_.m.locks++ 60 // Return the current cached span to the central lists. 61 s := c.alloc[sizeclass] 62 if s.freelist.ptr() != nil { 63 gothrow("refill on a nonempty span") 64 } 65 if s != &emptymspan { 66 s.incache = false 67 } 68 69 // Get a new cached span from the central lists. 70 s = mCentral_CacheSpan(&mheap_.central[sizeclass].mcentral) 71 if s == nil { 72 gothrow("out of memory") 73 } 74 if s.freelist.ptr() == nil { 75 println(s.ref, (s.npages<<_PageShift)/s.elemsize) 76 gothrow("empty span") 77 } 78 c.alloc[sizeclass] = s 79 _g_.m.locks-- 80 return s 81 } 82 83 func mCache_ReleaseAll(c *mcache) { 84 for i := 0; i < _NumSizeClasses; i++ { 85 s := c.alloc[i] 86 if s != &emptymspan { 87 mCentral_UncacheSpan(&mheap_.central[i].mcentral, s) 88 c.alloc[i] = &emptymspan 89 } 90 } 91 }