OSDN Git Service

Update Go compiler, library, and testsuite on gcc 4.7 branch.
[pf3gnuchains/gcc-fork.git] / libgo / runtime / mgc0.c
index 73c399d..4aa7c45 100644 (file)
@@ -61,6 +61,21 @@ enum {
 
 #define bitMask (bitBlockBoundary | bitAllocated | bitMarked | bitSpecial)
 
+// Holding worldsema grants an M the right to try to stop the world.
+// The procedure is:
+//
+//     runtime_semacquire(&runtime_worldsema);
+//     m->gcing = 1;
+//     runtime_stoptheworld();
+//
+//     ... do stuff ...
+//
+//     m->gcing = 0;
+//     runtime_semrelease(&runtime_worldsema);
+//     runtime_starttheworld();
+//
+uint32 runtime_worldsema = 1;
+
 // TODO: Make these per-M.
 static uint64 nhandoff;
 
@@ -92,7 +107,6 @@ struct FinBlock
        Finalizer fin[1];
 };
 
-
 static G *fing;
 static FinBlock *finq; // list of finalizers that are to be executed
 static FinBlock *finc; // cache of free blocks
@@ -640,14 +654,6 @@ markfin(void *v)
        scanblock(v, size);
 }
 
-struct root_list {
-       struct root_list *next;
-       struct root {
-               void *decl;
-               size_t size;
-       } roots[];
-};
-
 static struct root_list* roots;
 
 void
@@ -778,9 +784,11 @@ sweep(void)
        byte *p;
        MCache *c;
        byte *arena_start;
+       int64 now;
 
        m = runtime_m();
        arena_start = runtime_mheap.arena_start;
+       now = runtime_nanotime();
 
        for(;;) {
                s = work.spans;
@@ -789,6 +797,11 @@ sweep(void)
                if(!runtime_casp(&work.spans, s, s->allnext))
                        continue;
 
+               // Stamp newly unused spans. The scavenger will use that
+               // info to potentially give back some pages to the OS.
+               if(s->state == MSpanFree && s->unusedsince == 0)
+                       s->unusedsince = now;
+
                if(s->state != MSpanInUse)
                        continue;
 
@@ -875,11 +888,6 @@ runtime_gchelper(void)
                runtime_notewakeup(&work.alldone);
 }
 
-// Semaphore, not Lock, so that the goroutine
-// reschedules when there is contention rather
-// than spinning.
-static uint32 gcsema = 1;
-
 // Initialized from $GOGC.  GOGC=off means no gc.
 //
 // Next gc is after we've allocated an extra amount of
@@ -968,9 +976,9 @@ runtime_gc(int32 force)
        if(gcpercent < 0)
                return;
 
-       runtime_semacquire(&gcsema);
+       runtime_semacquire(&runtime_worldsema);
        if(!force && mstats.heap_alloc < mstats.next_gc) {
-               runtime_semrelease(&gcsema);
+               runtime_semrelease(&runtime_worldsema);
                return;
        }
 
@@ -1032,6 +1040,7 @@ runtime_gc(int32 force)
        obj1 = mstats.nmalloc - mstats.nfree;
 
        t3 = runtime_nanotime();
+       mstats.last_gc = t3;
        mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = t3 - t0;
        mstats.pause_total_ns += t3 - t0;
        mstats.numgc++;
@@ -1045,8 +1054,9 @@ runtime_gc(int32 force)
                        (unsigned long long) mstats.nmalloc, (unsigned long long)mstats.nfree,
                        (unsigned long long) nhandoff);
        }
-
-       runtime_semrelease(&gcsema);
+       
+       runtime_MProf_GC();
+       runtime_semrelease(&runtime_worldsema);
 
        // If we could have used another helper proc, start one now,
        // in the hope that it will be available next time.
@@ -1073,18 +1083,18 @@ runtime_ReadMemStats(MStats *stats)
 {
        M *m;
 
-       // Have to acquire gcsema to stop the world,
+       // Have to acquire worldsema to stop the world,
        // because stoptheworld can only be used by
        // one goroutine at a time, and there might be
        // a pending garbage collection already calling it.
-       runtime_semacquire(&gcsema);
+       runtime_semacquire(&runtime_worldsema);
        m = runtime_m();
        m->gcing = 1;
        runtime_stoptheworld();
        cachestats();
        *stats = mstats;
        m->gcing = 0;
-       runtime_semrelease(&gcsema);
+       runtime_semrelease(&runtime_worldsema);
        runtime_starttheworld(false);
 }