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  }