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.
7
// See malloc.h for an overview.
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).
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.
20
static bool MCentral_Grow(MCentral *c);
21
static void* MCentral_Alloc(MCentral *c);
22
static void MCentral_Free(MCentral *c, void *v);
24
// Initialize a single central free list.
26
runtime·MCentral_Init(MCentral *c, int32 sizeclass)
28
c->sizeclass = sizeclass;
29
runtime·MSpanList_Init(&c->nonempty);
30
runtime·MSpanList_Init(&c->empty);
33
// Allocate up to n 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, *pstart points at the first object and *pend at the last.
38
runtime·MCentral_AllocList(MCentral *c, int32 n, MLink **pfirst)
40
MLink *first, *last, *v;
44
// Replenish central list if empty.
45
if(runtime·MSpanList_IsEmpty(&c->nonempty)) {
46
if(!MCentral_Grow(c)) {
53
// Copy from list, up to n.
54
// First one is guaranteed to work, because we just grew the list.
55
first = MCentral_Alloc(c);
57
for(i=1; i<n && (v = MCentral_Alloc(c)) != nil; i++) {
69
// Helper: allocate one object from the central free list.
71
MCentral_Alloc(MCentral *c)
76
if(runtime·MSpanList_IsEmpty(&c->nonempty))
81
s->freelist = v->next;
82
if(s->freelist == nil) {
83
runtime·MSpanList_Remove(s);
84
runtime·MSpanList_Insert(&c->empty, s);
89
// Free n objects back into the central free list.
90
// Return the number of objects allocated.
91
// The objects are linked together by their first words.
92
// On return, *pstart points at the first object and *pend at the last.
94
runtime·MCentral_FreeList(MCentral *c, int32 n, MLink *start)
98
// Assume next == nil marks end of list.
99
// n and end would be useful if we implemented
100
// the transfer cache optimization in the TODO above.
104
for(v=start; v; v=next) {
111
// Helper: free one object back into the central free list.
113
MCentral_Free(MCentral *c, void *v)
120
s = runtime·MHeap_Lookup(&runtime·mheap, v);
121
if(s == nil || s->ref == 0)
122
runtime·throw("invalid free");
124
// Move to nonempty if necessary.
125
if(s->freelist == nil) {
126
runtime·MSpanList_Remove(s);
127
runtime·MSpanList_Insert(&c->nonempty, s);
130
// Add v back to s's free list.
132
p->next = s->freelist;
136
// If s is completely freed, return it to the heap.
138
size = runtime·class_to_size[c->sizeclass];
139
runtime·MSpanList_Remove(s);
140
runtime·unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift);
141
*(uintptr*)(s->start<<PageShift) = 1; // needs zeroing
143
c->nfree -= (s->npages << PageShift) / size;
145
runtime·MHeap_Free(&runtime·mheap, s, 0);
151
runtime·MGetSizeClassInfo(int32 sizeclass, uintptr *sizep, int32 *npagesp, int32 *nobj)
156
npages = runtime·class_to_allocnpages[sizeclass];
157
size = runtime·class_to_size[sizeclass];
160
*nobj = (npages << PageShift) / size;
163
// Fetch a new span from the heap and
164
// carve into objects for the free list.
166
MCentral_Grow(MCentral *c)
175
runtime·MGetSizeClassInfo(c->sizeclass, &size, &npages, &n);
176
s = runtime·MHeap_Alloc(&runtime·mheap, npages, c->sizeclass, 0);
178
// TODO(rsc): Log out of memory
183
// Carve span into sequence of blocks.
184
tailp = &s->freelist;
185
p = (byte*)(s->start << PageShift);
186
s->limit = p + size*n;
194
runtime·markspan((byte*)(s->start<<PageShift), size, n, size*n < (s->npages<<PageShift));
198
runtime·MSpanList_Insert(&c->nonempty, s);