Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1509)

Delta Between Two Patch Sets: src/pkg/runtime/mgc0.c

Issue 782041: code review 782041: runtime: run all finalizers in a single goroutine. (Closed)
Left Patch Set: Created 14 years, 11 months ago
Right Patch Set: code review 782041: runtime: run all finalizers in a single goroutine. Created 14 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/runtime/mfinal.c ('k') | src/pkg/runtime/proc.c » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 // Garbage collector -- step 0. 5 // Garbage collector -- step 0.
6 // 6 //
7 // Stop the world, mark and sweep garbage collector. 7 // Stop the world, mark and sweep garbage collector.
8 // NOT INTENDED FOR PRODUCTION USE. 8 // NOT INTENDED FOR PRODUCTION USE.
9 // 9 //
10 // A mark and sweep collector provides a way to exercise 10 // A mark and sweep collector provides a way to exercise
11 // and test the memory allocator and the stack walking machinery 11 // and test the memory allocator and the stack walking machinery
12 // without also needing to get reference counting 12 // without also needing to get reference counting
13 // exactly right. 13 // exactly right.
14 14
15 #include "runtime.h" 15 #include "runtime.h"
16 #include "malloc.h" 16 #include "malloc.h"
17 17
18 enum { 18 enum {
19 Debug = 0 19 Debug = 0
20 }; 20 };
21 21
22 extern byte data[]; 22 extern byte data[];
23 extern byte etext[]; 23 extern byte etext[];
24 extern byte end[]; 24 extern byte end[];
25 25
26 static G *fing;
26 static Finalizer *finq; 27 static Finalizer *finq;
27 static void sweepblock(byte*, int64, uint32*, int32); 28 static void sweepblock(byte*, int64, uint32*, int32);
28 static void runfinq(void*); 29 static void runfinq(void);
29 30
30 enum { 31 enum {
31 PtrSize = sizeof(void*) 32 PtrSize = sizeof(void*)
32 }; 33 };
33 34
34 static void 35 static void
35 scanblock(int32 depth, byte *b, int64 n) 36 scanblock(int32 depth, byte *b, int64 n)
36 { 37 {
37 int32 off; 38 int32 off;
38 void *obj; 39 void *obj;
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 if(mheap.Lock.key != 0) 293 if(mheap.Lock.key != 0)
293 throw("mheap locked during gc"); 294 throw("mheap locked during gc");
294 if(force || mstats.heap_alloc >= mstats.next_gc) { 295 if(force || mstats.heap_alloc >= mstats.next_gc) {
295 mark(); 296 mark();
296 sweep(); 297 sweep();
297 stealcache(); 298 stealcache();
298 mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/1 00; 299 mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/1 00;
299 } 300 }
300 m->gcing = 0; 301 m->gcing = 0;
301 302
302 // kick off goroutines to run queued finalizers
303 m->locks++; // disable gc during the mallocs in newproc 303 m->locks++; // disable gc during the mallocs in newproc
304 fp = finq; 304 fp = finq;
305 » if(fp != nil) 305 » if(fp != nil) {
306 » » newproc1((byte*)runfinq, (byte*)&fp, sizeof(fp), 0); 306 » » // kick off or wake up goroutine to run queued finalizers
307 » finq = nil; 307 » » if(fing == nil)
308 » » » fing = newproc1((byte*)runfinq, nil, 0, 0);
309 » » else if(fing->status == Gwaiting)
310 » » » ready(fing);
311 » }
308 m->locks--; 312 m->locks--;
309 313
310 t1 = nanotime(); 314 t1 = nanotime();
311 mstats.numgc++; 315 mstats.numgc++;
312 mstats.pause_ns += t1 - t0; 316 mstats.pause_ns += t1 - t0;
313 if(mstats.debuggc) 317 if(mstats.debuggc)
314 printf("pause %D\n", t1-t0); 318 printf("pause %D\n", t1-t0);
315 semrelease(&gcsema); 319 semrelease(&gcsema);
316 starttheworld(); 320 starttheworld();
317 ········ 321 ········
318 // give the queued finalizers, if any, a chance to run 322 // give the queued finalizers, if any, a chance to run
319 if(fp != nil) 323 if(fp != nil)
320 gosched(); 324 gosched();
321 } 325 }
322 326
323 static void 327 static void
324 runfinq(void *v) 328 runfinq(void)
325 { 329 {
326 Finalizer *f, *next; 330 Finalizer *f, *next;
327 byte *frame; 331 byte *frame;
328 »······· 332
329 » f = v; 333 » for(;;) {
330 » for(; f; f=next) { 334 » » // There's no need for a lock in this section
331 » » next = f->next; 335 » » // because it only conflicts with the garbage
332 » » frame = mal(sizeof(uintptr) + f->nret); 336 » » // collector, and the garbage collector only
333 » » *(void**)frame = f->arg; 337 » » // runs when everyone else is stopped, and
334 » » reflect·call((byte*)f->fn, frame, sizeof(uintptr) + f->nret); 338 » » // runfinq only stops at the gosched() or
335 » » free(frame); 339 » » // during the calls in the for loop.
336 » » f->fn = nil; 340 » » f = finq;
337 » » f->arg = nil; 341 » » finq = nil;
338 » » f->next = nil; 342 » » if(f == nil) {
339 » } 343 » » » g->status = Gwaiting;
340 » gc(1);» // force another gc to clean up the finalizer entries 344 » » » gosched();
341 } 345 » » » continue;
346 » » }
347 » » for(; f; f=next) {
348 » » » next = f->next;
349 » » » frame = mal(sizeof(uintptr) + f->nret);
350 » » » *(void**)frame = f->arg;
351 » » » reflect·call((byte*)f->fn, frame, sizeof(uintptr) + f->n ret);
352 » » » free(frame);
353 » » » f->fn = nil;
354 » » » f->arg = nil;
355 » » » f->next = nil;
356 » » }
357 » » gc(1);» // trigger another gc to clean up the finalized objects, if possible
358 » }
359 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b