Source file 
src/runtime/mpagecache.go
     1  
     2  
     3  
     4  
     5  package runtime
     6  
     7  import (
     8  	"internal/runtime/sys"
     9  	"unsafe"
    10  )
    11  
    12  const pageCachePages = 8 * unsafe.Sizeof(pageCache{}.cache)
    13  
    14  
    15  
    16  
    17  
    18  type pageCache struct {
    19  	base  uintptr 
    20  	cache uint64  
    21  	scav  uint64  
    22  }
    23  
    24  
    25  func (c *pageCache) empty() bool {
    26  	return c.cache == 0
    27  }
    28  
    29  
    30  
    31  
    32  
    33  
    34  
    35  
    36  
    37  func (c *pageCache) alloc(npages uintptr) (uintptr, uintptr) {
    38  	if c.cache == 0 {
    39  		return 0, 0
    40  	}
    41  	if npages == 1 {
    42  		i := uintptr(sys.TrailingZeros64(c.cache))
    43  		scav := (c.scav >> i) & 1
    44  		c.cache &^= 1 << i 
    45  		c.scav &^= 1 << i  
    46  		return c.base + i*pageSize, uintptr(scav) * pageSize
    47  	}
    48  	return c.allocN(npages)
    49  }
    50  
    51  
    52  
    53  
    54  
    55  
    56  
    57  func (c *pageCache) allocN(npages uintptr) (uintptr, uintptr) {
    58  	i := findBitRange64(c.cache, uint(npages))
    59  	if i >= 64 {
    60  		return 0, 0
    61  	}
    62  	mask := ((uint64(1) << npages) - 1) << i
    63  	scav := sys.OnesCount64(c.scav & mask)
    64  	c.cache &^= mask 
    65  	c.scav &^= mask  
    66  	return c.base + uintptr(i*pageSize), uintptr(scav) * pageSize
    67  }
    68  
    69  
    70  
    71  
    72  
    73  
    74  
    75  
    76  
    77  
    78  func (c *pageCache) flush(p *pageAlloc) {
    79  	assertLockHeld(p.mheapLock)
    80  
    81  	if c.empty() {
    82  		return
    83  	}
    84  	ci := chunkIndex(c.base)
    85  	pi := chunkPageIndex(c.base)
    86  
    87  	
    88  	
    89  	for i := uint(0); i < 64; i++ {
    90  		if c.cache&(1<<i) != 0 {
    91  			p.chunkOf(ci).free1(pi + i)
    92  
    93  			
    94  			p.scav.index.free(ci, pi+i, 1)
    95  		}
    96  		if c.scav&(1<<i) != 0 {
    97  			p.chunkOf(ci).scavenged.setRange(pi+i, 1)
    98  		}
    99  	}
   100  
   101  	
   102  	
   103  	if b := (offAddr{c.base}); b.lessThan(p.searchAddr) {
   104  		p.searchAddr = b
   105  	}
   106  	p.update(c.base, pageCachePages, false, false)
   107  	*c = pageCache{}
   108  }
   109  
   110  
   111  
   112  
   113  
   114  
   115  
   116  
   117  
   118  
   119  func (p *pageAlloc) allocToCache() pageCache {
   120  	assertLockHeld(p.mheapLock)
   121  
   122  	
   123  	
   124  	if chunkIndex(p.searchAddr.addr()) >= p.end {
   125  		return pageCache{}
   126  	}
   127  	c := pageCache{}
   128  	ci := chunkIndex(p.searchAddr.addr()) 
   129  	var chunk *pallocData
   130  	if p.summary[len(p.summary)-1][ci] != 0 {
   131  		
   132  		chunk = p.chunkOf(ci)
   133  		j, _ := chunk.find(1, chunkPageIndex(p.searchAddr.addr()))
   134  		if j == ^uint(0) {
   135  			throw("bad summary data")
   136  		}
   137  		c = pageCache{
   138  			base:  chunkBase(ci) + alignDown(uintptr(j), 64)*pageSize,
   139  			cache: ^chunk.pages64(j),
   140  			scav:  chunk.scavenged.block64(j),
   141  		}
   142  	} else {
   143  		
   144  		
   145  		addr, _ := p.find(1)
   146  		if addr == 0 {
   147  			
   148  			
   149  			p.searchAddr = maxSearchAddr()
   150  			return pageCache{}
   151  		}
   152  		ci = chunkIndex(addr)
   153  		chunk = p.chunkOf(ci)
   154  		c = pageCache{
   155  			base:  alignDown(addr, 64*pageSize),
   156  			cache: ^chunk.pages64(chunkPageIndex(addr)),
   157  			scav:  chunk.scavenged.block64(chunkPageIndex(addr)),
   158  		}
   159  	}
   160  
   161  	
   162  	
   163  	cpi := chunkPageIndex(c.base)
   164  	chunk.allocPages64(cpi, c.cache)
   165  	chunk.scavenged.clearBlock64(cpi, c.cache&c.scav )
   166  
   167  	
   168  	p.update(c.base, pageCachePages, false, true)
   169  
   170  	
   171  	p.scav.index.alloc(ci, uint(sys.OnesCount64(c.cache)))
   172  
   173  	
   174  	
   175  	
   176  	
   177  	
   178  	
   179  	
   180  	
   181  	p.searchAddr = offAddr{c.base + pageSize*(pageCachePages-1)}
   182  	return c
   183  }
   184  
View as plain text