gcc/ChangeLog:
[official-gcc.git] / libgo / runtime / mcache.c
blob746711a0d3bdba2adcce4077a3512350a4cfa1a8
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.
5 // Per-P malloc cache for small objects.
6 //
7 // See malloc.h for an overview.
9 #include "runtime.h"
10 #include "arch.h"
11 #include "malloc.h"
13 extern volatile intgo runtime_MemProfileRate
14 __asm__ (GOSYM_PREFIX "runtime.MemProfileRate");
16 // dummy MSpan that contains no free objects.
17 static MSpan emptymspan;
19 MCache*
20 runtime_allocmcache(void)
22 intgo rate;
23 MCache *c;
24 int32 i;
26 runtime_lock(&runtime_mheap);
27 c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc);
28 runtime_unlock(&runtime_mheap);
29 runtime_memclr((byte*)c, sizeof(*c));
30 for(i = 0; i < NumSizeClasses; i++)
31 c->alloc[i] = &emptymspan;
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);
40 return c;
43 void
44 runtime_freemcache(MCache *c)
46 runtime_MCache_ReleaseAll(c);
47 runtime_lock(&runtime_mheap);
48 runtime_purgecachedstats(c);
49 runtime_FixAlloc_Free(&runtime_mheap.cachealloc, c);
50 runtime_unlock(&runtime_mheap);
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)
58 MCacheList *l;
59 MSpan *s;
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], s);
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], l->list);
74 l->list = nil;
75 l->nlist = 0;
78 // Get a new cached span from the central lists.
79 s = runtime_MCentral_CacheSpan(&runtime_mheap.central[sizeclass]);
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");
86 c->alloc[sizeclass] = s;
87 runtime_m()->locks--;
88 return s;
91 void
92 runtime_MCache_Free(MCache *c, MLink *p, int32 sizeclass, uintptr size)
94 MCacheList *l;
96 // Put on free list.
97 l = &c->free[sizeclass];
98 p->next = l->list;
99 l->list = p;
100 l->nlist++;
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], l->list);
106 l->list = nil;
107 l->nlist = 0;
111 void
112 runtime_MCache_ReleaseAll(MCache *c)
114 int32 i;
115 MSpan *s;
116 MCacheList *l;
118 for(i=0; i<NumSizeClasses; i++) {
119 s = c->alloc[i];
120 if(s != &emptymspan) {
121 runtime_MCentral_UncacheSpan(&runtime_mheap.central[i], s);
122 c->alloc[i] = &emptymspan;
124 l = &c->free[i];
125 if(l->nlist > 0) {
126 runtime_MCentral_FreeList(&runtime_mheap.central[i], l->list);
127 l->list = nil;
128 l->nlist = 0;