LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // See malloc.h for overview. | 5 // See malloc.h for overview. |
6 // | 6 // |
7 // TODO(rsc): double-check stats. | 7 // TODO(rsc): double-check stats. |
8 | 8 |
9 package runtime | 9 package runtime |
10 #include "runtime.h" | 10 #include "runtime.h" |
11 #include "arch_GOARCH.h" | 11 #include "arch_GOARCH.h" |
12 #include "malloc.h" | 12 #include "malloc.h" |
13 #include "type.h" | 13 #include "type.h" |
14 #include "typekind.h" | 14 #include "typekind.h" |
15 #include "race.h" | 15 #include "race.h" |
16 | 16 #include "stack.h" |
| 17 |
| 18 // Mark mheap as 'no pointers', it does not contain interesting pointers but occ
upies ~45K. |
| 19 #pragma dataflag 16 |
17 MHeap runtime·mheap; | 20 MHeap runtime·mheap; |
18 | 21 |
19 int32 runtime·checking; | 22 int32 runtime·checking; |
20 | 23 |
21 extern MStats mstats; // defined in zruntime_def_$GOOS_$GOARCH.go | 24 extern MStats mstats; // defined in zruntime_def_$GOOS_$GOARCH.go |
22 | 25 |
23 extern volatile intgo runtime·MemProfileRate; | 26 extern volatile intgo runtime·MemProfileRate; |
24 | 27 |
25 // Allocate an object of at least size bytes. | 28 // Allocate an object of at least size bytes. |
26 // Small objects are allocated from the per-thread cache's free lists. | 29 // Small objects are allocated from the per-thread cache's free lists. |
27 // Large objects (> 32 kB) are allocated straight from the heap. | 30 // Large objects (> 32 kB) are allocated straight from the heap. |
28 // If the block will be freed with runtime·free(), typ must be 0. | 31 // If the block will be freed with runtime·free(), typ must be 0. |
29 void* | 32 void* |
30 runtime·mallocgc(uintptr size, uintptr typ, uint32 flag) | 33 runtime·mallocgc(uintptr size, uintptr typ, uint32 flag) |
31 { | 34 { |
32 int32 sizeclass; | 35 int32 sizeclass; |
33 intgo rate; | 36 intgo rate; |
34 MCache *c; | 37 MCache *c; |
35 MCacheList *l; | 38 MCacheList *l; |
36 uintptr npages; | 39 uintptr npages; |
37 MSpan *s; | 40 MSpan *s; |
38 MLink *v; | 41 MLink *v; |
39 | 42 |
40 if(runtime·gcwaiting && g != m->g0 && m->locks == 0 && !(flag & FlagNoIn
vokeGC)) | 43 if(runtime·gcwaiting && g != m->g0 && m->locks == 0 && !(flag & FlagNoIn
vokeGC)) |
41 runtime·gosched(); | 44 runtime·gosched(); |
42 if(size == 0) { | 45 if(size == 0) { |
43 // All 0-length allocations use this pointer. | 46 // All 0-length allocations use this pointer. |
44 // The language does not require the allocations to | 47 // The language does not require the allocations to |
45 // have distinct values. | 48 // have distinct values. |
46 return &runtime·zerobase; | 49 return &runtime·zerobase; |
47 } | 50 } |
48 if(m->mallocing) | 51 if(m->mallocing) |
49 runtime·throw("malloc/free - deadlock"); | 52 runtime·throw("malloc/free - deadlock"); |
| 53 // Disable preemption during settype_flush. |
| 54 // We can not use m->mallocing for this, because settype_flush calls mal
locgc. |
| 55 m->locks++; |
50 m->mallocing = 1; | 56 m->mallocing = 1; |
51 | 57 |
52 if(DebugTypeAtBlockEnd) | 58 if(DebugTypeAtBlockEnd) |
53 size += sizeof(uintptr); | 59 size += sizeof(uintptr); |
54 | 60 |
55 c = m->mcache; | 61 c = m->mcache; |
56 if(size <= MaxSmallSize) { | 62 if(size <= MaxSmallSize) { |
57 // Allocate from mcache free lists. | 63 // Allocate from mcache free lists. |
58 // Inlined version of SizeToClass(). | 64 // Inlined version of SizeToClass(). |
59 if(size <= 1024-8) | 65 if(size <= 1024-8) |
60 sizeclass = runtime·size_to_class8[(size+7)>>3]; | 66 sizeclass = runtime·size_to_class8[(size+7)>>3]; |
61 else | 67 else |
62 sizeclass = runtime·size_to_class128[(size-1024+127) >>
7]; | 68 sizeclass = runtime·size_to_class128[(size-1024+127) >>
7]; |
63 size = runtime·class_to_size[sizeclass]; | 69 size = runtime·class_to_size[sizeclass]; |
64 l = &c->list[sizeclass]; | 70 l = &c->list[sizeclass]; |
65 if(l->list == nil) | 71 if(l->list == nil) |
66 runtime·MCache_Refill(c, sizeclass); | 72 runtime·MCache_Refill(c, sizeclass); |
67 v = l->list; | 73 v = l->list; |
68 l->list = v->next; | 74 l->list = v->next; |
69 l->nlist--; | 75 l->nlist--; |
70 » » if(!(flag & FlagNoZeroize)) { | 76 » » if(!(flag & FlagNoZero)) { |
71 v->next = nil; | 77 v->next = nil; |
72 // block is zeroed iff second word is zero ... | 78 // block is zeroed iff second word is zero ... |
73 if(size > sizeof(uintptr) && ((uintptr*)v)[1] != 0) | 79 if(size > sizeof(uintptr) && ((uintptr*)v)[1] != 0) |
74 runtime·memclr((byte*)v, size); | 80 runtime·memclr((byte*)v, size); |
75 } | 81 } |
76 c->local_cachealloc += size; | 82 c->local_cachealloc += size; |
77 } else { | 83 } else { |
78 // TODO(rsc): Report tracebacks for very large allocations. | 84 // TODO(rsc): Report tracebacks for very large allocations. |
79 | 85 |
80 // Allocate directly from heap. | 86 // Allocate directly from heap. |
81 npages = size >> PageShift; | 87 npages = size >> PageShift; |
82 if((size & PageMask) != 0) | 88 if((size & PageMask) != 0) |
83 npages++; | 89 npages++; |
84 » » s = runtime·MHeap_Alloc(&runtime·mheap, npages, 0, 1, !(flag & F
lagNoZeroize)); | 90 » » s = runtime·MHeap_Alloc(&runtime·mheap, npages, 0, 1, !(flag & F
lagNoZero)); |
85 if(s == nil) | 91 if(s == nil) |
86 runtime·throw("out of memory"); | 92 runtime·throw("out of memory"); |
87 s->limit = (byte*)(s->start<<PageShift) + size; | 93 s->limit = (byte*)(s->start<<PageShift) + size; |
88 size = npages<<PageShift; | 94 size = npages<<PageShift; |
89 v = (void*)(s->start << PageShift); | 95 v = (void*)(s->start << PageShift); |
90 | 96 |
91 // setup for mark sweep | 97 // setup for mark sweep |
92 runtime·markspan(v, 0, 0, true); | 98 runtime·markspan(v, 0, 0, true); |
93 } | 99 } |
94 | 100 |
95 if(!(flag & FlagNoGC)) | 101 if(!(flag & FlagNoGC)) |
96 runtime·markallocated(v, size, (flag&FlagNoPointers) != 0); | 102 runtime·markallocated(v, size, (flag&FlagNoPointers) != 0); |
97 | 103 |
98 if(DebugTypeAtBlockEnd) | 104 if(DebugTypeAtBlockEnd) |
99 *(uintptr*)((uintptr)v+size-sizeof(uintptr)) = typ; | 105 *(uintptr*)((uintptr)v+size-sizeof(uintptr)) = typ; |
100 | 106 |
101 if(UseSpanType && !(flag & FlagNoPointers) && typ != 0) { | 107 if(UseSpanType && !(flag & FlagNoPointers) && typ != 0) { |
102 uintptr *buf, i; | 108 uintptr *buf, i; |
103 | 109 |
104 buf = m->settype_buf; | 110 buf = m->settype_buf; |
105 i = m->settype_bufsize; | 111 i = m->settype_bufsize; |
106 buf[i++] = (uintptr)v; | 112 buf[i++] = (uintptr)v; |
107 buf[i++] = typ; | 113 buf[i++] = typ; |
108 m->settype_bufsize = i; | 114 m->settype_bufsize = i; |
109 } | 115 } |
110 | 116 |
111 m->mallocing = 0; | 117 m->mallocing = 0; |
112 | |
113 if(UseSpanType && !(flag & FlagNoPointers) && typ != 0 && m->settype_buf
size == nelem(m->settype_buf)) | 118 if(UseSpanType && !(flag & FlagNoPointers) && typ != 0 && m->settype_buf
size == nelem(m->settype_buf)) |
114 runtime·settype_flush(m, false); | 119 runtime·settype_flush(m, false); |
| 120 m->locks--; |
| 121 if(m->locks == 0 && g->preempt) // restore the preemption request in ca
se we've cleared it in newstack |
| 122 g->stackguard0 = StackPreempt; |
115 | 123 |
116 if(!(flag & FlagNoProfiling) && (rate = runtime·MemProfileRate) > 0) { | 124 if(!(flag & FlagNoProfiling) && (rate = runtime·MemProfileRate) > 0) { |
117 if(size >= rate) | 125 if(size >= rate) |
118 goto profile; | 126 goto profile; |
119 if(m->mcache->next_sample > size) | 127 if(m->mcache->next_sample > size) |
120 m->mcache->next_sample -= size; | 128 m->mcache->next_sample -= size; |
121 else { | 129 else { |
122 // pick next profile time | 130 // pick next profile time |
123 // If you change this, also change allocmcache. | 131 // If you change this, also change allocmcache. |
124 if(rate > 0x3fffffff) // make 2*rate not overflow | 132 if(rate > 0x3fffffff) // make 2*rate not overflow |
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 runtime·printf("runtime.SetFinalizer: finalizer already set\n"); | 832 runtime·printf("runtime.SetFinalizer: finalizer already set\n"); |
825 goto throw; | 833 goto throw; |
826 } | 834 } |
827 return; | 835 return; |
828 | 836 |
829 badfunc: | 837 badfunc: |
830 runtime·printf("runtime.SetFinalizer: second argument is %S, not func(%S
)\n", *finalizer.type->string, *obj.type->string); | 838 runtime·printf("runtime.SetFinalizer: second argument is %S, not func(%S
)\n", *finalizer.type->string, *obj.type->string); |
831 throw: | 839 throw: |
832 runtime·throw("runtime.SetFinalizer"); | 840 runtime·throw("runtime.SetFinalizer"); |
833 } | 841 } |
LEFT | RIGHT |