github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/mcentral.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  // Central free lists.
     6  //
     7  // See malloc.h for an overview.
     8  //
     9  // The MCentral doesn't actually contain the list of free objects; the MSpan does.
    10  // Each MCentral is two lists of MSpans: those with free objects (c->nonempty)
    11  // and those that are completely allocated (c->empty).
    12  //
    13  // TODO(rsc): tcmalloc uses a "transfer cache" to split the list
    14  // into sections of class_to_transfercount[sizeclass] objects
    15  // so that it is faster to move those lists between MCaches and MCentrals.
    16  
    17  #include "runtime.h"
    18  #include "arch_GOARCH.h"
    19  #include "malloc.h"
    20  
    21  static bool MCentral_Grow(MCentral *c);
    22  static void MCentral_Free(MCentral *c, void *v);
    23  
    24  // Initialize a single central free list.
    25  void
    26  runtime·MCentral_Init(MCentral *c, int32 sizeclass)
    27  {
    28  	c->sizeclass = sizeclass;
    29  	runtime·MSpanList_Init(&c->nonempty);
    30  	runtime·MSpanList_Init(&c->empty);
    31  }
    32  
    33  // Allocate a list of objects from the central free list.
    34  // Return the number of objects allocated.
    35  // The objects are linked together by their first words.
    36  // On return, *pfirst points at the first object.
    37  int32
    38  runtime·MCentral_AllocList(MCentral *c, MLink **pfirst)
    39  {
    40  	MSpan *s;
    41  	int32 cap, n;
    42  
    43  	runtime·lock(c);
    44  	// Replenish central list if empty.
    45  	if(runtime·MSpanList_IsEmpty(&c->nonempty)) {
    46  		if(!MCentral_Grow(c)) {
    47  			runtime·unlock(c);
    48  			*pfirst = nil;
    49  			return 0;
    50  		}
    51  	}
    52  	s = c->nonempty.next;
    53  	cap = (s->npages << PageShift) / s->elemsize;
    54  	n = cap - s->ref;
    55  	*pfirst = s->freelist;
    56  	s->freelist = nil;
    57  	s->ref += n;
    58  	c->nfree -= n;
    59  	runtime·MSpanList_Remove(s);
    60  	runtime·MSpanList_Insert(&c->empty, s);
    61  	runtime·unlock(c);
    62  	return n;
    63  }
    64  
    65  // Free the list of objects back into the central free list.
    66  void
    67  runtime·MCentral_FreeList(MCentral *c, MLink *start)
    68  {
    69  	MLink *next;
    70  
    71  	runtime·lock(c);
    72  	for(; start != nil; start = next) {
    73  		next = start->next;
    74  		MCentral_Free(c, start);
    75  	}
    76  	runtime·unlock(c);
    77  }
    78  
    79  // Helper: free one object back into the central free list.
    80  static void
    81  MCentral_Free(MCentral *c, void *v)
    82  {
    83  	MSpan *s;
    84  	MLink *p;
    85  	int32 size;
    86  
    87  	// Find span for v.
    88  	s = runtime·MHeap_Lookup(&runtime·mheap, v);
    89  	if(s == nil || s->ref == 0)
    90  		runtime·throw("invalid free");
    91  
    92  	// Move to nonempty if necessary.
    93  	if(s->freelist == nil) {
    94  		runtime·MSpanList_Remove(s);
    95  		runtime·MSpanList_Insert(&c->nonempty, s);
    96  	}
    97  
    98  	// Add v back to s's free list.
    99  	p = v;
   100  	p->next = s->freelist;
   101  	s->freelist = p;
   102  	c->nfree++;
   103  
   104  	// If s is completely freed, return it to the heap.
   105  	if(--s->ref == 0) {
   106  		size = runtime·class_to_size[c->sizeclass];
   107  		runtime·MSpanList_Remove(s);
   108  		runtime·unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift);
   109  		*(uintptr*)(s->start<<PageShift) = 1;  // needs zeroing
   110  		s->freelist = nil;
   111  		c->nfree -= (s->npages << PageShift) / size;
   112  		runtime·unlock(c);
   113  		runtime·MHeap_Free(&runtime·mheap, s, 0);
   114  		runtime·lock(c);
   115  	}
   116  }
   117  
   118  // Free n objects from a span s back into the central free list c.
   119  // Called from GC.
   120  void
   121  runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end)
   122  {
   123  	int32 size;
   124  
   125  	runtime·lock(c);
   126  
   127  	// Move to nonempty if necessary.
   128  	if(s->freelist == nil) {
   129  		runtime·MSpanList_Remove(s);
   130  		runtime·MSpanList_Insert(&c->nonempty, s);
   131  	}
   132  
   133  	// Add the objects back to s's free list.
   134  	end->next = s->freelist;
   135  	s->freelist = start;
   136  	s->ref -= n;
   137  	c->nfree += n;
   138  
   139  	// If s is completely freed, return it to the heap.
   140  	if(s->ref == 0) {
   141  		size = runtime·class_to_size[c->sizeclass];
   142  		runtime·MSpanList_Remove(s);
   143  		*(uintptr*)(s->start<<PageShift) = 1;  // needs zeroing
   144  		s->freelist = nil;
   145  		c->nfree -= (s->npages << PageShift) / size;
   146  		runtime·unlock(c);
   147  		runtime·unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift);
   148  		runtime·MHeap_Free(&runtime·mheap, s, 0);
   149  	} else {
   150  		runtime·unlock(c);
   151  	}
   152  }
   153  
   154  void
   155  runtime·MGetSizeClassInfo(int32 sizeclass, uintptr *sizep, int32 *npagesp, int32 *nobj)
   156  {
   157  	int32 size;
   158  	int32 npages;
   159  
   160  	npages = runtime·class_to_allocnpages[sizeclass];
   161  	size = runtime·class_to_size[sizeclass];
   162  	*npagesp = npages;
   163  	*sizep = size;
   164  	*nobj = (npages << PageShift) / size;
   165  }
   166  
   167  // Fetch a new span from the heap and
   168  // carve into objects for the free list.
   169  static bool
   170  MCentral_Grow(MCentral *c)
   171  {
   172  	int32 i, n, npages;
   173  	uintptr size;
   174  	MLink **tailp, *v;
   175  	byte *p;
   176  	MSpan *s;
   177  
   178  	runtime·unlock(c);
   179  	runtime·MGetSizeClassInfo(c->sizeclass, &size, &npages, &n);
   180  	s = runtime·MHeap_Alloc(&runtime·mheap, npages, c->sizeclass, 0, 1);
   181  	if(s == nil) {
   182  		// TODO(rsc): Log out of memory
   183  		runtime·lock(c);
   184  		return false;
   185  	}
   186  
   187  	// Carve span into sequence of blocks.
   188  	tailp = &s->freelist;
   189  	p = (byte*)(s->start << PageShift);
   190  	s->limit = p + size*n;
   191  	for(i=0; i<n; i++) {
   192  		v = (MLink*)p;
   193  		*tailp = v;
   194  		tailp = &v->next;
   195  		p += size;
   196  	}
   197  	*tailp = nil;
   198  	runtime·markspan((byte*)(s->start<<PageShift), size, n, size*n < (s->npages<<PageShift));
   199  
   200  	runtime·lock(c);
   201  	c->nfree += n;
   202  	runtime·MSpanList_Insert(&c->nonempty, s);
   203  	return true;
   204  }