Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: third_party/tcmalloc/chromium/src/central_freelist.cc

Issue 7671034: doubly-linked free-lists for thread caches and page heaps (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: code style fixes Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2008, Google Inc. 1 // Copyright (c) 2011, Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer 11 // copyright notice, this list of conditions and the following disclaimer
(...skipping 13 matching lines...) Expand all
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 29
30 // --- 30 // ---
31 // Author: Sanjay Ghemawat <opensource@google.com> 31 // Author: Sanjay Ghemawat <opensource@google.com>
32 32
33 #include "config.h" 33 #include "config.h"
34 #include "central_freelist.h" 34 #include "central_freelist.h"
35 35 #include "free_list.h" // for FL_Next, FL_Push, etc
36 #include "internal_logging.h" // for ASSERT, MESSAGE 36 #include "internal_logging.h" // for ASSERT, MESSAGE
37 #include "linked_list.h" // for SLL_Next, SLL_Push, etc
38 #include "page_heap.h" // for PageHeap 37 #include "page_heap.h" // for PageHeap
39 #include "static_vars.h" // for Static 38 #include "static_vars.h" // for Static
40 39
41 namespace tcmalloc { 40 namespace tcmalloc {
42 41
43 void CentralFreeList::Init(size_t cl) { 42 void CentralFreeList::Init(size_t cl) {
44 size_class_ = cl; 43 size_class_ = cl;
45 tcmalloc::DLL_Init(&empty_); 44 tcmalloc::DLL_Init(&empty_);
46 tcmalloc::DLL_Init(&nonempty_); 45 tcmalloc::DLL_Init(&nonempty_);
47 counter_ = 0; 46 counter_ = 0;
48 47
49 #ifdef TCMALLOC_SMALL_BUT_SLOW 48 #ifdef TCMALLOC_SMALL_BUT_SLOW
50 // Disable the transfer cache for the small footprint case. 49 // Disable the transfer cache for the small footprint case.
51 cache_size_ = 0; 50 cache_size_ = 0;
52 #else 51 #else
53 cache_size_ = 16; 52 cache_size_ = 16;
54 #endif 53 #endif
55 used_slots_ = 0; 54 used_slots_ = 0;
56 ASSERT(cache_size_ <= kNumTransferEntries); 55 ASSERT(cache_size_ <= kNumTransferEntries);
57 } 56 }
58 57
59 void CentralFreeList::ReleaseListToSpans(void* start) { 58 void CentralFreeList::ReleaseListToSpans(void* start) {
60 while (start) { 59 while (start) {
61 void *next = SLL_Next(start); 60 void *next = FL_Next(start);
62 ReleaseToSpans(start); 61 ReleaseToSpans(start);
63 start = next; 62 start = next;
64 } 63 }
65 } 64 }
66 65
67 // MapObjectToSpan should logically be part of ReleaseToSpans. But 66 // MapObjectToSpan should logically be part of ReleaseToSpans. But
68 // this triggers an optimization bug in gcc 4.5.0. Moving to a 67 // this triggers an optimization bug in gcc 4.5.0. Moving to a
69 // separate function, and making sure that function isn't inlined, 68 // separate function, and making sure that function isn't inlined,
70 // seems to fix the problem. It also should be fixed for gcc 4.5.1. 69 // seems to fix the problem. It also should be fixed for gcc 4.5.1.
71 static 70 static
(...skipping 14 matching lines...) Expand all
86 // If span is empty, move it to non-empty list 85 // If span is empty, move it to non-empty list
87 if (span->objects == NULL) { 86 if (span->objects == NULL) {
88 tcmalloc::DLL_Remove(span); 87 tcmalloc::DLL_Remove(span);
89 tcmalloc::DLL_Prepend(&nonempty_, span); 88 tcmalloc::DLL_Prepend(&nonempty_, span);
90 Event(span, 'N', 0); 89 Event(span, 'N', 0);
91 } 90 }
92 91
93 // The following check is expensive, so it is disabled by default 92 // The following check is expensive, so it is disabled by default
94 if (false) { 93 if (false) {
95 // Check that object does not occur in list 94 // Check that object does not occur in list
95 void *next = span->objects;
96 int got = 0; 96 int got = 0;
97 for (void* p = span->objects; p != NULL; p = *((void**) p)) { 97 while (next = FL_Next(next)) {
jar (doing other things) 2011/08/20 02:40:30 Minimalist changes are better. Merging etc. is eas
bxx 2011/08/24 00:19:24 Done.
98 ASSERT(p != object); 98 ASSERT(next != object);
99 got++; 99 got++;
100 } 100 }
101 ASSERT(got + span->refcount == 101 ASSERT(got + span->refcount ==
102 (span->length<<kPageShift) / 102 (span->length<<kPageShift) /
103 Static::sizemap()->ByteSizeForClass(span->sizeclass)); 103 Static::sizemap()->ByteSizeForClass(span->sizeclass));
104 } 104 }
105 105
106 counter_++; 106 counter_++;
107 span->refcount--; 107 span->refcount--;
108 if (span->refcount == 0) { 108 if (span->refcount == 0) {
109 Event(span, '#', 0); 109 Event(span, '#', 0);
110 counter_ -= ((span->length<<kPageShift) / 110 counter_ -= ((span->length<<kPageShift) /
111 Static::sizemap()->ByteSizeForClass(span->sizeclass)); 111 Static::sizemap()->ByteSizeForClass(span->sizeclass));
112 tcmalloc::DLL_Remove(span); 112 tcmalloc::DLL_Remove(span);
113 113
114 // Release central list lock while operating on pageheap 114 // Release central list lock while operating on pageheap
115 lock_.Unlock(); 115 lock_.Unlock();
116 { 116 {
117 SpinLockHolder h(Static::pageheap_lock()); 117 SpinLockHolder h(Static::pageheap_lock());
118 Static::pageheap()->Delete(span); 118 Static::pageheap()->Delete(span);
119 } 119 }
120 lock_.Lock(); 120 lock_.Lock();
121 } else { 121 } else {
122 *(reinterpret_cast<void**>(object)) = span->objects; 122 FL_Push(&(span->objects), object);
123 span->objects = object;
124 } 123 }
125 } 124 }
126 125
127 bool CentralFreeList::EvictRandomSizeClass( 126 bool CentralFreeList::EvictRandomSizeClass(
128 int locked_size_class, bool force) { 127 int locked_size_class, bool force) {
129 static int race_counter = 0; 128 static int race_counter = 0;
130 int t = race_counter++; // Updated without a lock, but who cares. 129 int t = race_counter++; // Updated without a lock, but who cares.
131 if (t >= kNumClasses) { 130 if (t >= kNumClasses) {
132 while (t >= kNumClasses) { 131 while (t >= kNumClasses) {
133 t -= kNumClasses; 132 t -= kNumClasses;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 *start = entry->head; 229 *start = entry->head;
231 *end = entry->tail; 230 *end = entry->tail;
232 lock_.Unlock(); 231 lock_.Unlock();
233 return N; 232 return N;
234 } 233 }
235 234
236 int result = 0; 235 int result = 0;
237 void* head = NULL; 236 void* head = NULL;
238 void* tail = NULL; 237 void* tail = NULL;
239 // TODO: Prefetch multiple TCEntries? 238 // TODO: Prefetch multiple TCEntries?
240 tail = FetchFromSpansSafe(); 239 tail = FetchFromSpansSafe(); // makes freelist and returns pointer to start
jar (doing other things) 2011/08/20 02:40:30 Minimalst: Comment here is not critical, and adds
bxx 2011/08/24 00:19:24 Done.
241 if (tail != NULL) { 240 if (tail != NULL) {
242 SLL_SetNext(tail, NULL); 241 FL_Push(&head, tail);
243 head = tail;
244 result = 1; 242 result = 1;
245 while (result < N) { 243 while (result < N) {
246 void *t = FetchFromSpans(); 244 void *t = FetchFromSpans();
247 if (!t) break; 245 if (!t) break;
248 SLL_Push(&head, t); 246 FL_Push(&head, t);
249 result++; 247 result++;
250 } 248 }
251 } 249 }
252 lock_.Unlock(); 250 lock_.Unlock();
253 *start = head; 251 *start = head;
254 *end = tail; 252 *end = tail;
253
jar (doing other things) 2011/08/20 02:40:30 nit: Remove extra line.
bxx 2011/08/24 00:19:24 Done.
255 return result; 254 return result;
256 } 255 }
257 256
258 257
259 void* CentralFreeList::FetchFromSpansSafe() { 258 void* CentralFreeList::FetchFromSpansSafe() {
260 void *t = FetchFromSpans(); 259 void *t = FetchFromSpans();
261 if (!t) { 260 if (!t) {
262 Populate(); 261 Populate();
263 t = FetchFromSpans(); 262 t = FetchFromSpans();
264 } 263 }
265 return t; 264 return t;
266 } 265 }
267 266
268 void* CentralFreeList::FetchFromSpans() { 267 void* CentralFreeList::FetchFromSpans() {
269 if (tcmalloc::DLL_IsEmpty(&nonempty_)) return NULL; 268 if (tcmalloc::DLL_IsEmpty(&nonempty_)) return NULL;
270 Span* span = nonempty_.next; 269 Span* span = nonempty_.next;
271 270
272 ASSERT(span->objects != NULL); 271 ASSERT(span->objects != NULL);
273 span->refcount++; 272 span->refcount++;
274 void* result = span->objects; 273 void *result = FL_Pop(&(span->objects));
275 span->objects = *(reinterpret_cast<void**>(result));
276 if (span->objects == NULL) { 274 if (span->objects == NULL) {
277 // Move to empty list 275 // Move to empty list
278 tcmalloc::DLL_Remove(span); 276 tcmalloc::DLL_Remove(span);
279 tcmalloc::DLL_Prepend(&empty_, span); 277 tcmalloc::DLL_Prepend(&empty_, span);
280 Event(span, 'E', 0); 278 Event(span, 'E', 0);
281 } 279 }
282 counter_--; 280 counter_--;
283 return result; 281 return result;
284 } 282 }
285 283
(...skipping 22 matching lines...) Expand all
308 Static::pageheap()->CacheSizeClass(span->start + i, size_class_); 306 Static::pageheap()->CacheSizeClass(span->start + i, size_class_);
309 } 307 }
310 308
311 // Split the block into pieces and add to the free-list 309 // Split the block into pieces and add to the free-list
312 // TODO: coloring of objects to avoid cache conflicts? 310 // TODO: coloring of objects to avoid cache conflicts?
313 void** tail = &span->objects; 311 void** tail = &span->objects;
314 char* ptr = reinterpret_cast<char*>(span->start << kPageShift); 312 char* ptr = reinterpret_cast<char*>(span->start << kPageShift);
315 char* limit = ptr + (npages << kPageShift); 313 char* limit = ptr + (npages << kPageShift);
316 const size_t size = Static::sizemap()->ByteSizeForClass(size_class_); 314 const size_t size = Static::sizemap()->ByteSizeForClass(size_class_);
317 int num = 0; 315 int num = 0;
316 span->objects = NULL;
jar (doing other things) 2011/08/20 02:40:30 This might be a tad more readable (and connect wit
bxx 2011/08/24 00:19:24 Done.
318 while (ptr + size <= limit) { 317 while (ptr + size <= limit) {
319 *tail = ptr; 318 tcmalloc::FL_Push(tail, static_cast<void*>(ptr));
jar (doing other things) 2011/08/20 02:40:30 I think the change is ok, but it is good to note t
bxx 2011/08/24 00:19:24 I think I fixed it properly. Just to make sure I
320 tail = reinterpret_cast<void**>(ptr);
321 ptr += size; 319 ptr += size;
322 num++; 320 num++;
323 } 321 }
324 ASSERT(ptr <= limit); 322 ASSERT(ptr <= limit);
325 *tail = NULL; 323 span->refcount = 0; // No sub-object in use yet
jar (doing other things) 2011/08/20 02:40:30 Minimalist: Don't correct with today's style. Lea
bxx 2011/08/24 00:19:24 Done.
326 span->refcount = 0; // No sub-object in use yet
327 324
328 // Add span to list of non-empty spans 325 // Add span to list of non-empty spans
329 lock_.Lock(); 326 lock_.Lock();
330 tcmalloc::DLL_Prepend(&nonempty_, span); 327 tcmalloc::DLL_Prepend(&nonempty_, span);
331 counter_ += num; 328 counter_ += num;
332 } 329 }
333 330
334 int CentralFreeList::tc_length() { 331 int CentralFreeList::tc_length() {
335 SpinLockHolder h(&lock_); 332 SpinLockHolder h(&lock_);
336 return used_slots_ * Static::sizemap()->num_objects_to_move(size_class_); 333 return used_slots_ * Static::sizemap()->num_objects_to_move(size_class_);
337 } 334 }
338 335
339 } // namespace tcmalloc 336 } // namespace tcmalloc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698