Source file 
src/runtime/mpallocbits.go
     1  
     2  
     3  
     4  
     5  package runtime
     6  
     7  import (
     8  	"internal/runtime/sys"
     9  )
    10  
    11  
    12  type pageBits [pallocChunkPages / 64]uint64
    13  
    14  
    15  func (b *pageBits) get(i uint) uint {
    16  	return uint((b[i/64] >> (i % 64)) & 1)
    17  }
    18  
    19  
    20  func (b *pageBits) block64(i uint) uint64 {
    21  	return b[i/64]
    22  }
    23  
    24  
    25  func (b *pageBits) set(i uint) {
    26  	b[i/64] |= 1 << (i % 64)
    27  }
    28  
    29  
    30  func (b *pageBits) setRange(i, n uint) {
    31  	_ = b[i/64]
    32  	if n == 1 {
    33  		
    34  		b.set(i)
    35  		return
    36  	}
    37  	
    38  	j := i + n - 1
    39  	if i/64 == j/64 {
    40  		b[i/64] |= ((uint64(1) << n) - 1) << (i % 64)
    41  		return
    42  	}
    43  	_ = b[j/64]
    44  	
    45  	b[i/64] |= ^uint64(0) << (i % 64)
    46  	for k := i/64 + 1; k < j/64; k++ {
    47  		b[k] = ^uint64(0)
    48  	}
    49  	
    50  	b[j/64] |= (uint64(1) << (j%64 + 1)) - 1
    51  }
    52  
    53  
    54  func (b *pageBits) setAll() {
    55  	for i := range b {
    56  		b[i] = ^uint64(0)
    57  	}
    58  }
    59  
    60  
    61  
    62  func (b *pageBits) setBlock64(i uint, v uint64) {
    63  	b[i/64] |= v
    64  }
    65  
    66  
    67  func (b *pageBits) clear(i uint) {
    68  	b[i/64] &^= 1 << (i % 64)
    69  }
    70  
    71  
    72  func (b *pageBits) clearRange(i, n uint) {
    73  	_ = b[i/64]
    74  	if n == 1 {
    75  		
    76  		b.clear(i)
    77  		return
    78  	}
    79  	
    80  	j := i + n - 1
    81  	if i/64 == j/64 {
    82  		b[i/64] &^= ((uint64(1) << n) - 1) << (i % 64)
    83  		return
    84  	}
    85  	_ = b[j/64]
    86  	
    87  	b[i/64] &^= ^uint64(0) << (i % 64)
    88  	clear(b[i/64+1 : j/64])
    89  	
    90  	b[j/64] &^= (uint64(1) << (j%64 + 1)) - 1
    91  }
    92  
    93  
    94  func (b *pageBits) clearAll() {
    95  	clear(b[:])
    96  }
    97  
    98  
    99  
   100  func (b *pageBits) clearBlock64(i uint, v uint64) {
   101  	b[i/64] &^= v
   102  }
   103  
   104  
   105  
   106  func (b *pageBits) popcntRange(i, n uint) (s uint) {
   107  	if n == 1 {
   108  		return uint((b[i/64] >> (i % 64)) & 1)
   109  	}
   110  	_ = b[i/64]
   111  	j := i + n - 1
   112  	if i/64 == j/64 {
   113  		return uint(sys.OnesCount64((b[i/64] >> (i % 64)) & ((1 << n) - 1)))
   114  	}
   115  	_ = b[j/64]
   116  	s += uint(sys.OnesCount64(b[i/64] >> (i % 64)))
   117  	for k := i/64 + 1; k < j/64; k++ {
   118  		s += uint(sys.OnesCount64(b[k]))
   119  	}
   120  	s += uint(sys.OnesCount64(b[j/64] & ((1 << (j%64 + 1)) - 1)))
   121  	return
   122  }
   123  
   124  
   125  
   126  
   127  
   128  
   129  type pallocBits pageBits
   130  
   131  
   132  func (b *pallocBits) summarize() pallocSum {
   133  	var start, most, cur uint
   134  	const notSetYet = ^uint(0) 
   135  	start = notSetYet
   136  	for i := 0; i < len(b); i++ {
   137  		x := b[i]
   138  		if x == 0 {
   139  			cur += 64
   140  			continue
   141  		}
   142  		t := uint(sys.TrailingZeros64(x))
   143  		l := uint(sys.LeadingZeros64(x))
   144  
   145  		
   146  		cur += t
   147  		if start == notSetYet {
   148  			start = cur
   149  		}
   150  		most = max(most, cur)
   151  		
   152  		cur = l
   153  	}
   154  	if start == notSetYet {
   155  		
   156  		const n = uint(64 * len(b))
   157  		return packPallocSum(n, n, n)
   158  	}
   159  	most = max(most, cur)
   160  
   161  	if most >= 64-2 {
   162  		
   163  		return packPallocSum(start, most, cur)
   164  	}
   165  	
   166  	
   167  outer:
   168  	for i := 0; i < len(b); i++ {
   169  		x := b[i]
   170  
   171  		
   172  		
   173  		
   174  		
   175  
   176  		
   177  		x >>= sys.TrailingZeros64(x) & 63
   178  		if x&(x+1) == 0 { 
   179  			continue
   180  		}
   181  
   182  		
   183  		
   184  		p := most    
   185  		k := uint(1) 
   186  		for {
   187  			
   188  			for p > 0 {
   189  				if p <= k {
   190  					
   191  					x |= x >> (p & 63)
   192  					if x&(x+1) == 0 { 
   193  						continue outer
   194  					}
   195  					break
   196  				}
   197  				
   198  				x |= x >> (k & 63)
   199  				if x&(x+1) == 0 { 
   200  					continue outer
   201  				}
   202  				p -= k
   203  				
   204  				
   205  				k *= 2
   206  			}
   207  
   208  			
   209  			j := uint(sys.TrailingZeros64(^x)) 
   210  			x >>= j & 63                       
   211  			j = uint(sys.TrailingZeros64(x))   
   212  			x >>= j & 63                       
   213  			most += j                          
   214  			if x&(x+1) == 0 {                  
   215  				continue outer
   216  			}
   217  			p = j 
   218  		}
   219  	}
   220  	return packPallocSum(start, most, cur)
   221  }
   222  
   223  
   224  
   225  
   226  
   227  
   228  
   229  
   230  
   231  
   232  func (b *pallocBits) find(npages uintptr, searchIdx uint) (uint, uint) {
   233  	if npages == 1 {
   234  		addr := b.find1(searchIdx)
   235  		return addr, addr
   236  	} else if npages <= 64 {
   237  		return b.findSmallN(npages, searchIdx)
   238  	}
   239  	return b.findLargeN(npages, searchIdx)
   240  }
   241  
   242  
   243  
   244  
   245  
   246  func (b *pallocBits) find1(searchIdx uint) uint {
   247  	_ = b[0] 
   248  	for i := searchIdx / 64; i < uint(len(b)); i++ {
   249  		x := b[i]
   250  		if ^x == 0 {
   251  			continue
   252  		}
   253  		return i*64 + uint(sys.TrailingZeros64(^x))
   254  	}
   255  	return ^uint(0)
   256  }
   257  
   258  
   259  
   260  
   261  
   262  
   263  
   264  
   265  
   266  
   267  
   268  func (b *pallocBits) findSmallN(npages uintptr, searchIdx uint) (uint, uint) {
   269  	end, newSearchIdx := uint(0), ^uint(0)
   270  	for i := searchIdx / 64; i < uint(len(b)); i++ {
   271  		bi := b[i]
   272  		if ^bi == 0 {
   273  			end = 0
   274  			continue
   275  		}
   276  		
   277  		
   278  		if newSearchIdx == ^uint(0) {
   279  			
   280  			
   281  			newSearchIdx = i*64 + uint(sys.TrailingZeros64(^bi))
   282  		}
   283  		start := uint(sys.TrailingZeros64(bi))
   284  		if end+start >= uint(npages) {
   285  			return i*64 - end, newSearchIdx
   286  		}
   287  		
   288  		j := findBitRange64(^bi, uint(npages))
   289  		if j < 64 {
   290  			return i*64 + j, newSearchIdx
   291  		}
   292  		end = uint(sys.LeadingZeros64(bi))
   293  	}
   294  	return ^uint(0), newSearchIdx
   295  }
   296  
   297  
   298  
   299  
   300  
   301  
   302  
   303  
   304  
   305  
   306  
   307  func (b *pallocBits) findLargeN(npages uintptr, searchIdx uint) (uint, uint) {
   308  	start, size, newSearchIdx := ^uint(0), uint(0), ^uint(0)
   309  	for i := searchIdx / 64; i < uint(len(b)); i++ {
   310  		x := b[i]
   311  		if x == ^uint64(0) {
   312  			size = 0
   313  			continue
   314  		}
   315  		if newSearchIdx == ^uint(0) {
   316  			
   317  			
   318  			newSearchIdx = i*64 + uint(sys.TrailingZeros64(^x))
   319  		}
   320  		if size == 0 {
   321  			size = uint(sys.LeadingZeros64(x))
   322  			start = i*64 + 64 - size
   323  			continue
   324  		}
   325  		s := uint(sys.TrailingZeros64(x))
   326  		if s+size >= uint(npages) {
   327  			return start, newSearchIdx
   328  		}
   329  		if s < 64 {
   330  			size = uint(sys.LeadingZeros64(x))
   331  			start = i*64 + 64 - size
   332  			continue
   333  		}
   334  		size += 64
   335  	}
   336  	if size < uint(npages) {
   337  		return ^uint(0), newSearchIdx
   338  	}
   339  	return start, newSearchIdx
   340  }
   341  
   342  
   343  func (b *pallocBits) allocRange(i, n uint) {
   344  	(*pageBits)(b).setRange(i, n)
   345  }
   346  
   347  
   348  func (b *pallocBits) allocAll() {
   349  	(*pageBits)(b).setAll()
   350  }
   351  
   352  
   353  func (b *pallocBits) free1(i uint) {
   354  	(*pageBits)(b).clear(i)
   355  }
   356  
   357  
   358  func (b *pallocBits) free(i, n uint) {
   359  	(*pageBits)(b).clearRange(i, n)
   360  }
   361  
   362  
   363  func (b *pallocBits) freeAll() {
   364  	(*pageBits)(b).clearAll()
   365  }
   366  
   367  
   368  
   369  
   370  func (b *pallocBits) pages64(i uint) uint64 {
   371  	return (*pageBits)(b).block64(i)
   372  }
   373  
   374  
   375  
   376  func (b *pallocBits) allocPages64(i uint, alloc uint64) {
   377  	(*pageBits)(b).setBlock64(i, alloc)
   378  }
   379  
   380  
   381  
   382  
   383  
   384  func findBitRange64(c uint64, n uint) uint {
   385  	
   386  	
   387  	
   388  	p := n - 1   
   389  	k := uint(1) 
   390  	for p > 0 {
   391  		if p <= k {
   392  			
   393  			c &= c >> (p & 63)
   394  			break
   395  		}
   396  		
   397  		c &= c >> (k & 63)
   398  		if c == 0 {
   399  			return 64
   400  		}
   401  		p -= k
   402  		
   403  		
   404  		k *= 2
   405  	}
   406  	
   407  	
   408  	
   409  	return uint(sys.TrailingZeros64(c))
   410  }
   411  
   412  
   413  
   414  
   415  
   416  
   417  
   418  
   419  type pallocData struct {
   420  	pallocBits
   421  	scavenged pageBits
   422  }
   423  
   424  
   425  
   426  func (m *pallocData) allocRange(i, n uint) {
   427  	
   428  	m.pallocBits.allocRange(i, n)
   429  	m.scavenged.clearRange(i, n)
   430  }
   431  
   432  
   433  
   434  func (m *pallocData) allocAll() {
   435  	
   436  	m.pallocBits.allocAll()
   437  	m.scavenged.clearAll()
   438  }
   439  
View as plain text