]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/mcache.go
[dev.garbage] all: merge dev.cc into dev.garbage
[gostls13.git] / 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 // Per-P malloc cache for small objects.
6 //
7 // See malloc.h for an overview.
8
9 package runtime
10
11 import "unsafe"
12
13 // dummy MSpan that contains no free objects.
14 var emptymspan mspan
15
16 func allocmcache() *mcache {
17         lock(&mheap_.lock)
18         c := (*mcache)(fixAlloc_Alloc(&mheap_.cachealloc))
19         unlock(&mheap_.lock)
20         memclr(unsafe.Pointer(c), unsafe.Sizeof(*c))
21         for i := 0; i < _NumSizeClasses; i++ {
22                 c.alloc[i] = &emptymspan
23         }
24
25         // Set first allocation sample size.
26         rate := MemProfileRate
27         if rate > 0x3fffffff { // make 2*rate not overflow
28                 rate = 0x3fffffff
29         }
30         if rate != 0 {
31                 c.next_sample = int32(int(fastrand1()) % (2 * rate))
32         }
33
34         return c
35 }
36
37 func freemcache(c *mcache) {
38         systemstack(func() {
39                 mCache_ReleaseAll(c)
40                 stackcache_clear(c)
41
42                 // NOTE(rsc,rlh): If gcworkbuffree comes back, we need to coordinate
43                 // with the stealing of gcworkbufs during garbage collection to avoid
44                 // a race where the workbuf is double-freed.
45                 // gcworkbuffree(c.gcworkbuf)
46
47                 lock(&mheap_.lock)
48                 purgecachedstats(c)
49                 fixAlloc_Free(&mheap_.cachealloc, unsafe.Pointer(c))
50                 unlock(&mheap_.lock)
51         })
52 }
53
54 // Gets a span that has a free object in it and assigns it
55 // to be the cached span for the given sizeclass.  Returns this span.
56 func mCache_Refill(c *mcache, sizeclass int32) *mspan {
57         _g_ := getg()
58
59         _g_.m.locks++
60         // Return the current cached span to the central lists.
61         s := c.alloc[sizeclass]
62         if s.freelist != nil {
63                 gothrow("refill on a nonempty span")
64         }
65         if s != &emptymspan {
66                 s.incache = false
67         }
68
69         // Get a new cached span from the central lists.
70         s = mCentral_CacheSpan(&mheap_.central[sizeclass].mcentral)
71         if s == nil {
72                 gothrow("out of memory")
73         }
74         if s.freelist == nil {
75                 println(s.ref, (s.npages<<_PageShift)/s.elemsize)
76                 gothrow("empty span")
77         }
78         c.alloc[sizeclass] = s
79         _g_.m.locks--
80         return s
81 }
82
83 func mCache_ReleaseAll(c *mcache) {
84         for i := 0; i < _NumSizeClasses; i++ {
85                 s := c.alloc[i]
86                 if s != &emptymspan {
87                         mCentral_UncacheSpan(&mheap_.central[i].mcentral, s)
88                         c.alloc[i] = &emptymspan
89                 }
90         }
91 }