...
Run Format

Source file src/runtime/mcache.go

     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	package runtime
     6	
     7	import "unsafe"
     8	
     9	// Per-thread (in Go, per-P) cache for small objects.
    10	// No locking needed because it is per-thread (per-P).
    11	//
    12	// mcaches are allocated from non-GC'd memory, so any heap pointers
    13	// must be specially handled.
    14	type mcache struct {
    15		// The following members are accessed on every malloc,
    16		// so they are grouped here for better caching.
    17		next_sample int32   // trigger heap sample after allocating this many bytes
    18		local_scan  uintptr // bytes of scannable heap allocated
    19	
    20		// Allocator cache for tiny objects w/o pointers.
    21		// See "Tiny allocator" comment in malloc.go.
    22	
    23		// tiny points to the beginning of the current tiny block, or
    24		// nil if there is no current tiny block.
    25		//
    26		// tiny is a heap pointer. Since mcache is in non-GC'd memory,
    27		// we handle it by clearing it in releaseAll during mark
    28		// termination.
    29		tiny             uintptr
    30		tinyoffset       uintptr
    31		local_tinyallocs uintptr // number of tiny allocs not counted in other stats
    32	
    33		// The rest is not accessed on every malloc.
    34		alloc [_NumSizeClasses]*mspan // spans to allocate from
    35	
    36		stackcache [_NumStackOrders]stackfreelist
    37	
    38		// Local allocator stats, flushed during GC.
    39		local_nlookup    uintptr                  // number of pointer lookups
    40		local_largefree  uintptr                  // bytes freed for large objects (>maxsmallsize)
    41		local_nlargefree uintptr                  // number of frees for large objects (>maxsmallsize)
    42		local_nsmallfree [_NumSizeClasses]uintptr // number of frees for small objects (<=maxsmallsize)
    43	}
    44	
    45	// A gclink is a node in a linked list of blocks, like mlink,
    46	// but it is opaque to the garbage collector.
    47	// The GC does not trace the pointers during collection,
    48	// and the compiler does not emit write barriers for assignments
    49	// of gclinkptr values. Code should store references to gclinks
    50	// as gclinkptr, not as *gclink.
    51	type gclink struct {
    52		next gclinkptr
    53	}
    54	
    55	// A gclinkptr is a pointer to a gclink, but it is opaque
    56	// to the garbage collector.
    57	type gclinkptr uintptr
    58	
    59	// ptr returns the *gclink form of p.
    60	// The result should be used for accessing fields, not stored
    61	// in other data structures.
    62	func (p gclinkptr) ptr() *gclink {
    63		return (*gclink)(unsafe.Pointer(p))
    64	}
    65	
    66	type stackfreelist struct {
    67		list gclinkptr // linked list of free stacks
    68		size uintptr   // total size of stacks in list
    69	}
    70	
    71	// dummy MSpan that contains no free objects.
    72	var emptymspan mspan
    73	
    74	func allocmcache() *mcache {
    75		lock(&mheap_.lock)
    76		c := (*mcache)(mheap_.cachealloc.alloc())
    77		unlock(&mheap_.lock)
    78		memclr(unsafe.Pointer(c), unsafe.Sizeof(*c))
    79		for i := 0; i < _NumSizeClasses; i++ {
    80			c.alloc[i] = &emptymspan
    81		}
    82		c.next_sample = nextSample()
    83		return c
    84	}
    85	
    86	func freemcache(c *mcache) {
    87		systemstack(func() {
    88			c.releaseAll()
    89			stackcache_clear(c)
    90	
    91			// NOTE(rsc,rlh): If gcworkbuffree comes back, we need to coordinate
    92			// with the stealing of gcworkbufs during garbage collection to avoid
    93			// a race where the workbuf is double-freed.
    94			// gcworkbuffree(c.gcworkbuf)
    95	
    96			lock(&mheap_.lock)
    97			purgecachedstats(c)
    98			mheap_.cachealloc.free(unsafe.Pointer(c))
    99			unlock(&mheap_.lock)
   100		})
   101	}
   102	
   103	// Gets a span that has a free object in it and assigns it
   104	// to be the cached span for the given sizeclass. Returns this span.
   105	func (c *mcache) refill(sizeclass int32) *mspan {
   106		_g_ := getg()
   107	
   108		_g_.m.locks++
   109		// Return the current cached span to the central lists.
   110		s := c.alloc[sizeclass]
   111	
   112		if uintptr(s.allocCount) != s.nelems {
   113			throw("refill of span with free space remaining")
   114		}
   115	
   116		if s != &emptymspan {
   117			s.incache = false
   118		}
   119	
   120		// Get a new cached span from the central lists.
   121		s = mheap_.central[sizeclass].mcentral.cacheSpan()
   122		if s == nil {
   123			throw("out of memory")
   124		}
   125	
   126		if uintptr(s.allocCount) == s.nelems {
   127			throw("span has no free space")
   128		}
   129	
   130		c.alloc[sizeclass] = s
   131		_g_.m.locks--
   132		return s
   133	}
   134	
   135	func (c *mcache) releaseAll() {
   136		for i := 0; i < _NumSizeClasses; i++ {
   137			s := c.alloc[i]
   138			if s != &emptymspan {
   139				mheap_.central[i].mcentral.uncacheSpan(s)
   140				c.alloc[i] = &emptymspan
   141			}
   142		}
   143		// Clear tinyalloc pool.
   144		c.tiny = 0
   145		c.tinyoffset = 0
   146	}
   147	

View as plain text