github.com/shijuvar/go@v0.0.0-20141209052335-e8f13700b70c/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  }