X-Git-Url: https://git.llucax.com/software/dgc/cdgc.git/blobdiff_plain/b8af9d3c77843fc75c260f6c95028f769015532c..9037ef3e51af8c40168a08911ac30650f882ee81:/gc/gc.d diff --git a/gc/gc.d b/gc/gc.d index 7915a11..3e22a0a 100644 --- a/gc/gc.d +++ b/gc/gc.d @@ -43,18 +43,14 @@ module gc.gc; version = STACKGROWSDOWN; // growing the stack means subtracting from the stack pointer // (use for Intel X86 CPUs) // else growing the stack means adding to the stack pointer -version = MULTI_THREADED; // produce multithreaded version /***************************************************/ import gc.bits; import gc.stats; import gc.alloc; +import gc.libc; -import cstdlib = tango.stdc.stdlib : calloc, free, malloc, realloc; -import cstring = tango.stdc.string : memcpy, memmove, memset; - -debug import tango.stdc.stdio : printf; version (GNU) { @@ -92,14 +88,11 @@ private extern (C) void rt_scanStaticData( scanFn scan ); - version (MULTI_THREADED) - { - extern (C) bool thread_needLock(); - extern (C) void thread_suspendAll(); - extern (C) void thread_resumeAll(); + extern (C) bool thread_needLock(); + extern (C) void thread_suspendAll(); + extern (C) void thread_resumeAll(); - extern (C) void thread_scanAll( scanFn fn, void* curStackTop = null ); - } + extern (C) void thread_scanAll( scanFn fn, void* curStackTop = null ); extern (C) void onOutOfMemoryError(); @@ -147,7 +140,7 @@ debug (LOGGING) void Dtor() { if (data) - cstdlib.free(data); + .free(data); data = null; } @@ -160,18 +153,18 @@ debug (LOGGING) assert(dim + nentries <= allocdim); if (!data) { - data = cast(Log*)cstdlib.malloc(allocdim * Log.sizeof); + data = cast(Log*) .malloc(allocdim * Log.sizeof); if (!data && allocdim) onOutOfMemoryError(); } else { Log *newdata; - newdata = cast(Log*)cstdlib.malloc(allocdim * Log.sizeof); + newdata = cast(Log*) .malloc(allocdim * Log.sizeof); if (!newdata && allocdim) onOutOfMemoryError(); - cstring.memcpy(newdata, data, dim * Log.sizeof); - cstdlib.free(data); + .memcpy(newdata, data, dim * Log.sizeof); + .free(data); data = newdata; } } @@ -186,7 +179,7 @@ debug (LOGGING) void remove(size_t i) { - cstring.memmove(data + i, data + i + 1, (dim - i) * Log.sizeof); + .memmove(data + i, data + i + 1, (dim - i) * Log.sizeof); dim--; } @@ -206,7 +199,7 @@ debug (LOGGING) { reserve(from.dim - dim); assert(from.dim <= allocdim); - cstring.memcpy(data, from.data, from.dim * Log.sizeof); + .memcpy(data, from.data, from.dim * Log.sizeof); dim = from.dim; } } @@ -237,7 +230,7 @@ class GC void initialize() { gcLock = GCLock.classinfo; - gcx = cast(Gcx*)cstdlib.calloc(1, Gcx.sizeof); + gcx = cast(Gcx*) .calloc(1, Gcx.sizeof); if (!gcx) onOutOfMemoryError(); gcx.initialize(); @@ -250,7 +243,7 @@ class GC if (gcx) { gcx.Dtor(); - cstdlib.free(gcx); + .free(gcx); gcx = null; } } @@ -483,9 +476,9 @@ class GC // Return next item from free list gcx.bucket[bin] = (cast(List*)p).next; if( !(bits & BlkAttr.NO_SCAN) ) - cstring.memset(p + size, 0, binsize[bin] - size); + .memset(p + size, 0, binsize[bin] - size); //debug(PRINTF) printf("\tmalloc => %x\n", p); - debug (MEMSTOMP) cstring.memset(p, 0xF0, size); + debug (MEMSTOMP) .memset(p, 0xF0, size); } else { @@ -539,7 +532,7 @@ class GC //debug(PRINTF) printf("calloc: %x len %d\n", p, len); void *p = mallocNoSync(size, bits); - cstring.memset(p, 0, size); + .memset(p, 0, size); return p; } @@ -609,7 +602,7 @@ class GC if (psize < size) size = psize; //debug(PRINTF) printf("\tcopying %d bytes\n",size); - cstring.memcpy(p2, p, size); + .memcpy(p2, p, size); p = p2; } } @@ -630,7 +623,7 @@ class GC { // Shrink in place synchronized (gcLock) { - debug (MEMSTOMP) cstring.memset(p + size, 0xF2, psize - size); + debug (MEMSTOMP) .memset(p + size, 0xF2, psize - size); pool.freePages(pagenum + newsz, psz - newsz); } return p; @@ -644,17 +637,13 @@ class GC { if (i == pagenum + newsz) { - debug (MEMSTOMP) cstring.memset(p + psize, 0xF0, size - psize); - cstring.memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz); + debug (MEMSTOMP) .memset(p + psize, 0xF0, size - psize); + .memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz); return p; } - if (i == pool.ncommitted) + if (i == pool.npages) { - auto u = pool.extendPages(pagenum + newsz - pool.ncommitted); - if (u == OPFAIL) - break; - i = pagenum + newsz; - continue; + break; } if (pool.pagetable[i] != B_FREE) break; @@ -689,7 +678,7 @@ class GC if (psize < size) size = psize; //debug(PRINTF) printf("\tcopying %d bytes\n",size); - cstring.memcpy(p2, p, size); + .memcpy(p2, p, size); p = p2; } } @@ -750,7 +739,7 @@ class GC for (sz = 0; sz < maxsz; sz++) { auto i = pagenum + psz + sz; - if (i == pool.ncommitted) + if (i == pool.npages) break; if (pool.pagetable[i] != B_FREE) { if (sz < minsz) @@ -758,20 +747,10 @@ class GC break; } } - if (sz >= minsz) - { - } - else if (pagenum + psz + sz == pool.ncommitted) - { - auto u = pool.extendPages(minsz - sz); - if (u == OPFAIL) - return 0; - sz = minsz; - } - else + if (sz < minsz) return 0; - debug (MEMSTOMP) cstring.memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize); - cstring.memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz); + debug (MEMSTOMP) .memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize); + .memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz); gcx.p_cache = null; gcx.size_cache = 0; return (psz + sz) * PAGESIZE; @@ -862,16 +841,16 @@ class GC // Free pages npages = 1; n = pagenum; - while (++n < pool.ncommitted && pool.pagetable[n] == B_PAGEPLUS) + while (++n < pool.npages && pool.pagetable[n] == B_PAGEPLUS) npages++; - debug (MEMSTOMP) cstring.memset(p, 0xF2, npages * PAGESIZE); + debug (MEMSTOMP) .memset(p, 0xF2, npages * PAGESIZE); pool.freePages(pagenum, npages); } else { // Add to free list List *list = cast(List*)p; - debug (MEMSTOMP) cstring.memset(p, 0xF2, binsize[bin]); + debug (MEMSTOMP) .memset(p, 0xF2, binsize[bin]); list.next = gcx.bucket[bin]; gcx.bucket[bin] = list; @@ -1288,13 +1267,13 @@ class GC size_t bsize = 0; //debug(PRINTF) printf("getStats()\n"); - cstring.memset(&stats, 0, GCStats.sizeof); + .memset(&stats, 0, GCStats.sizeof); for (n = 0; n < gcx.npools; n++) { Pool *pool = gcx.pooltable[n]; - psize += pool.ncommitted * PAGESIZE; - for (size_t j = 0; j < pool.ncommitted; j++) + psize += pool.npages * PAGESIZE; + for (size_t j = 0; j < pool.npages; j++) { Bins bin = cast(Bins)pool.pagetable[j]; if (bin == B_FREE) @@ -1329,7 +1308,6 @@ class GC enum { PAGESIZE = 4096, - COMMITSIZE = (4096*16), POOLSIZE = (4096*256), } @@ -1347,7 +1325,6 @@ enum B_PAGE, // start of large alloc B_PAGEPLUS, // continuation of large alloc B_FREE, // free page - B_UNCOMMITTED, // memory not committed for this page B_MAX } @@ -1424,16 +1401,16 @@ struct Gcx { Pool *pool = pooltable[i]; pool.Dtor(); - cstdlib.free(pool); + .free(pool); } if (pooltable) - cstdlib.free(pooltable); + .free(pooltable); if (roots) - cstdlib.free(roots); + .free(roots); if (ranges) - cstdlib.free(ranges); + .free(ranges); } @@ -1504,12 +1481,12 @@ struct Gcx size_t newdim = rootdim * 2 + 16; void** newroots; - newroots = cast(void**)cstdlib.malloc(newdim * newroots[0].sizeof); + newroots = cast(void**) .malloc(newdim * newroots[0].sizeof); if (!newroots) onOutOfMemoryError(); if (roots) - { cstring.memcpy(newroots, roots, nroots * newroots[0].sizeof); - cstdlib.free(roots); + { .memcpy(newroots, roots, nroots * newroots[0].sizeof); + .free(roots); } roots = newroots; rootdim = newdim; @@ -1529,7 +1506,7 @@ struct Gcx if (roots[i] == p) { nroots--; - cstring.memmove(roots + i, roots + i + 1, (nroots - i) * roots[0].sizeof); + .memmove(roots + i, roots + i + 1, (nroots - i) * roots[0].sizeof); return; } } @@ -1549,12 +1526,12 @@ struct Gcx size_t newdim = rangedim * 2 + 16; Range *newranges; - newranges = cast(Range*)cstdlib.malloc(newdim * newranges[0].sizeof); + newranges = cast(Range*) .malloc(newdim * newranges[0].sizeof); if (!newranges) onOutOfMemoryError(); if (ranges) - { cstring.memcpy(newranges, ranges, nranges * newranges[0].sizeof); - cstdlib.free(ranges); + { .memcpy(newranges, ranges, nranges * newranges[0].sizeof); + .free(ranges); } ranges = newranges; rangedim = newdim; @@ -1577,7 +1554,7 @@ struct Gcx if (ranges[i].pbot == pbot) { nranges--; - cstring.memmove(ranges + i, ranges + i + 1, (nranges - i) * ranges[0].sizeof); + .memmove(ranges + i, ranges + i + 1, (nranges - i) * ranges[0].sizeof); return; } } @@ -1649,7 +1626,7 @@ struct Gcx } else { - // we are in a B_FREE or B_UNCOMMITTED page + // we are in a B_FREE page return null; } } @@ -1676,12 +1653,12 @@ struct Gcx bin = cast(Bins)pool.pagetable[pagenum]; size = binsize[bin]; if (bin == B_PAGE) - { size_t npages = pool.ncommitted; + { ubyte* pt; size_t i; pt = &pool.pagetable[0]; - for (i = pagenum + 1; i < npages; i++) + for (i = pagenum + 1; i < pool.npages; i++) { if (pt[i] != B_PAGEPLUS) break; @@ -1734,12 +1711,12 @@ struct Gcx info.size = binsize[bin]; if (bin == B_PAGE) - { size_t npages = pool.ncommitted; + { ubyte* pt; size_t i; pt = &pool.pagetable[0]; - for (i = pn + 1; i < npages; i++) + for (i = pn + 1; i < pool.npages; i++) { if (pt[i] != B_PAGEPLUS) break; @@ -1814,9 +1791,9 @@ struct Gcx size_t npages = (size + PAGESIZE - 1) / PAGESIZE; Pool* pool = newPool(npages); - if (!pool || pool.extendPages(npages) == OPFAIL) + if (!pool) return 0; - return pool.ncommitted * PAGESIZE; + return pool.npages * PAGESIZE; } @@ -1828,25 +1805,23 @@ struct Gcx size_t n; size_t pn; Pool* pool; - size_t ncommitted; for (n = 0; n < npools; n++) { pool = pooltable[n]; - ncommitted = pool.ncommitted; - for (pn = 0; pn < ncommitted; pn++) + for (pn = 0; pn < pool.npages; pn++) { if (cast(Bins)pool.pagetable[pn] != B_FREE) break; } - if (pn < ncommitted) + if (pn < pool.npages) { n++; continue; } pool.Dtor(); - cstdlib.free(pool); - cstring.memmove(pooltable + n, + .free(pool); + .memmove(pooltable + n, pooltable + n + 1, (--npools - n) * (Pool*).sizeof); minAddr = pooltable[0].baseAddr; @@ -1929,10 +1904,10 @@ struct Gcx L1: pool.pagetable[pn] = B_PAGE; if (npages > 1) - cstring.memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1); + .memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1); p = pool.baseAddr + pn * PAGESIZE; - cstring.memset(cast(char *)p + size, 0, npages * PAGESIZE - size); - debug (MEMSTOMP) cstring.memset(p, 0xF1, size); + .memset(cast(char *)p + size, 0, npages * PAGESIZE - size); + debug (MEMSTOMP) .memset(p, 0xF1, size); //debug(PRINTF) printf("\tp = %x\n", p); return p; @@ -1955,9 +1930,6 @@ struct Gcx //debug(PRINTF) printf("************Gcx::newPool(npages = %d)****************\n", npages); - // Round up to COMMITSIZE pages - npages = (npages + (COMMITSIZE/PAGESIZE) - 1) & ~(COMMITSIZE/PAGESIZE - 1); - // Minimum of POOLSIZE if (npages < POOLSIZE/PAGESIZE) npages = POOLSIZE/PAGESIZE; @@ -1980,7 +1952,7 @@ struct Gcx npages = n; } - pool = cast(Pool *)cstdlib.calloc(1, Pool.sizeof); + pool = cast(Pool *) .calloc(1, Pool.sizeof); if (pool) { pool.initialize(npages); @@ -1988,7 +1960,7 @@ struct Gcx goto Lerr; newnpools = npools + 1; - newpooltable = cast(Pool **)cstdlib.realloc(pooltable, newnpools * (Pool *).sizeof); + newpooltable = cast(Pool **) .realloc(pooltable, newnpools * (Pool *).sizeof); if (!newpooltable) goto Lerr; @@ -1998,7 +1970,7 @@ struct Gcx if (pool.opCmp(newpooltable[i]) < 0) break; } - cstring.memmove(newpooltable + i + 1, newpooltable + i, (npools - i) * (Pool *).sizeof); + .memmove(newpooltable + i + 1, newpooltable + i, (npools - i) * (Pool *).sizeof); newpooltable[i] = pool; pooltable = newpooltable; @@ -2011,7 +1983,7 @@ struct Gcx Lerr: pool.Dtor(); - cstdlib.free(pool); + .free(pool); return null; } @@ -2104,7 +2076,7 @@ struct Gcx } else { - // Don't mark bits in B_FREE or B_UNCOMMITTED pages + // Don't mark bits in B_FREE pages continue; } @@ -2260,25 +2232,10 @@ struct Gcx rt_scanStaticData( &mark ); - version (MULTI_THREADED) + if (!noStack) { - if (!noStack) - { - // Scan stacks and registers for each paused thread - thread_scanAll( &mark, stackTop ); - } - } - else - { - if (!noStack) - { - // Scan stack for main thread - debug(PRINTF) printf(" scan stack bot = %x, top = %x\n", stackTop, stackBottom); - version (STACKGROWSDOWN) - mark(stackTop, stackBottom); - else - mark(stackBottom, stackTop); - } + // Scan stacks and registers for each paused thread + thread_scanAll( &mark, stackTop ); } // Scan roots[] @@ -2348,7 +2305,7 @@ struct Gcx pn--; } u = 1; - while (pn + u < pool.ncommitted && pool.pagetable[pn + u] == B_PAGEPLUS) + while (pn + u < pool.npages && pool.pagetable[pn + u] == B_PAGEPLUS) u++; mark(o, o + u * PAGESIZE); } @@ -2365,13 +2322,11 @@ struct Gcx size_t freed = 0; for (n = 0; n < npools; n++) { size_t pn; - size_t ncommitted; uint* bbase; pool = pooltable[n]; bbase = pool.mark.base(); - ncommitted = pool.ncommitted; - for (pn = 0; pn < ncommitted; pn++, bbase += PAGESIZE / (32 * 16)) + for (pn = 0; pn < pool.npages; pn++, bbase += PAGESIZE / (32 * 16)) { Bins bin = cast(Bins)pool.pagetable[pn]; @@ -2403,7 +2358,7 @@ struct Gcx //debug(PRINTF) printf("\tcollecting %x\n", list); log_free(sentinel_add(list)); - debug (MEMSTOMP) cstring.memset(p, 0xF3, size); + debug (MEMSTOMP) .memset(p, 0xF3, size); } pool.pagetable[pn] = B_FREE; freed += PAGESIZE; @@ -2426,7 +2381,7 @@ struct Gcx debug(PRINTF) printf("\tcollecting %x\n", list); log_free(sentinel_add(list)); - debug (MEMSTOMP) cstring.memset(p, 0xF3, size); + debug (MEMSTOMP) .memset(p, 0xF3, size); freed += size; } @@ -2447,8 +2402,8 @@ struct Gcx log_free(sentinel_add(p)); pool.pagetable[pn] = B_FREE; freedpages++; - debug (MEMSTOMP) cstring.memset(p, 0xF3, PAGESIZE); - while (pn + 1 < ncommitted && pool.pagetable[pn + 1] == B_PAGEPLUS) + debug (MEMSTOMP) .memset(p, 0xF3, PAGESIZE); + while (pn + 1 < pool.npages && pool.pagetable[pn + 1] == B_PAGEPLUS) { pn++; pool.pagetable[pn] = B_FREE; @@ -2456,7 +2411,7 @@ struct Gcx debug (MEMSTOMP) { p += PAGESIZE; - cstring.memset(p, 0xF3, PAGESIZE); + .memset(p, 0xF3, PAGESIZE); } } } @@ -2472,11 +2427,9 @@ struct Gcx size_t recoveredpages = 0; for (n = 0; n < npools; n++) { size_t pn; - size_t ncommitted; pool = pooltable[n]; - ncommitted = pool.ncommitted; - for (pn = 0; pn < ncommitted; pn++) + for (pn = 0; pn < pool.npages; pn++) { Bins bin = cast(Bins)pool.pagetable[pn]; size_t biti; @@ -2743,7 +2696,6 @@ struct Pool GCBits noscan; // entries that should not be scanned size_t npages; - size_t ncommitted; // ncommitted <= npages ubyte* pagetable; @@ -2775,13 +2727,12 @@ struct Pool freebits.alloc(cast(size_t)poolsize / 16); noscan.alloc(cast(size_t)poolsize / 16); - pagetable = cast(ubyte*)cstdlib.malloc(npages); + pagetable = cast(ubyte*) .malloc(npages); if (!pagetable) onOutOfMemoryError(); - cstring.memset(pagetable, B_UNCOMMITTED, npages); + .memset(pagetable, B_FREE, npages); this.npages = npages; - ncommitted = 0; } @@ -2791,17 +2742,10 @@ struct Pool { int result; - if (ncommitted) - { - result = os_mem_decommit(baseAddr, 0, ncommitted * PAGESIZE); - assert(result == 0); - ncommitted = 0; - } - if (npages) { result = os_mem_unmap(baseAddr, npages * PAGESIZE); - assert(result == 0); + assert(result); npages = 0; } @@ -2809,7 +2753,7 @@ struct Pool topAddr = null; } if (pagetable) - cstdlib.free(pagetable); + .free(pagetable); mark.Dtor(); scan.Dtor(); @@ -2835,7 +2779,6 @@ struct Pool //if (baseAddr + npages * PAGESIZE != topAddr) //printf("baseAddr = %p, npages = %d, topAddr = %p\n", baseAddr, npages, topAddr); assert(baseAddr + npages * PAGESIZE == topAddr); - assert(ncommitted <= npages); } for (size_t i = 0; i < npages; i++) @@ -2857,7 +2800,7 @@ struct Pool //debug(PRINTF) printf("Pool::allocPages(n = %d)\n", n); n2 = n; - for (i = 0; i < ncommitted; i++) + for (i = 0; i < npages; i++) { if (pagetable[i] == B_FREE) { @@ -2869,39 +2812,6 @@ struct Pool else n2 = n; } - return extendPages(n); - } - - /** - * Extend Pool by n pages. - * Returns OPFAIL on failure. - */ - size_t extendPages(size_t n) - { - //debug(PRINTF) printf("Pool::extendPages(n = %d)\n", n); - if (ncommitted + n <= npages) - { - size_t tocommit; - - tocommit = (n + (COMMITSIZE/PAGESIZE) - 1) & ~(COMMITSIZE/PAGESIZE - 1); - if (ncommitted + tocommit > npages) - tocommit = npages - ncommitted; - //debug(PRINTF) printf("\tlooking to commit %d more pages\n", tocommit); - //fflush(stdout); - if (os_mem_commit(baseAddr, ncommitted * PAGESIZE, tocommit * PAGESIZE) == 0) - { - cstring.memset(pagetable + ncommitted, B_FREE, tocommit); - auto i = ncommitted; - ncommitted += tocommit; - - while (i && pagetable[i - 1] == B_FREE) - i--; - - return i; - } - //debug(PRINTF) printf("\tfailed to commit %d pages\n", tocommit); - } - return OPFAIL; } @@ -2911,7 +2821,7 @@ struct Pool */ void freePages(size_t pagenum, size_t npages) { - cstring.memset(&pagetable[pagenum], B_FREE, npages); + .memset(&pagetable[pagenum], B_FREE, npages); }