Source file 
src/runtime/mpagealloc_test.go
     1  
     2  
     3  
     4  
     5  package runtime_test
     6  
     7  import (
     8  	"fmt"
     9  	"internal/goos"
    10  	. "runtime"
    11  	"testing"
    12  )
    13  
    14  func checkPageAlloc(t *testing.T, want, got *PageAlloc) {
    15  	
    16  	wantStart, wantEnd := want.Bounds()
    17  	gotStart, gotEnd := got.Bounds()
    18  	if gotStart != wantStart {
    19  		t.Fatalf("start values not equal: got %d, want %d", gotStart, wantStart)
    20  	}
    21  	if gotEnd != wantEnd {
    22  		t.Fatalf("end values not equal: got %d, want %d", gotEnd, wantEnd)
    23  	}
    24  
    25  	for i := gotStart; i < gotEnd; i++ {
    26  		
    27  		gb, wb := got.PallocData(i), want.PallocData(i)
    28  		if gb == nil && wb == nil {
    29  			continue
    30  		}
    31  		if (gb == nil && wb != nil) || (gb != nil && wb == nil) {
    32  			t.Errorf("chunk %d nilness mismatch", i)
    33  		}
    34  		if !checkPallocBits(t, gb.PallocBits(), wb.PallocBits()) {
    35  			t.Logf("in chunk %d (mallocBits)", i)
    36  		}
    37  		if !checkPallocBits(t, gb.Scavenged(), wb.Scavenged()) {
    38  			t.Logf("in chunk %d (scavenged)", i)
    39  		}
    40  	}
    41  	
    42  }
    43  
    44  func TestPageAllocGrow(t *testing.T) {
    45  	if GOOS == "openbsd" && testing.Short() {
    46  		t.Skip("skipping because virtual memory is limited; see #36210")
    47  	}
    48  	type test struct {
    49  		chunks []ChunkIdx
    50  		inUse  []AddrRange
    51  	}
    52  	tests := map[string]test{
    53  		"One": {
    54  			chunks: []ChunkIdx{
    55  				BaseChunkIdx,
    56  			},
    57  			inUse: []AddrRange{
    58  				MakeAddrRange(PageBase(BaseChunkIdx, 0), PageBase(BaseChunkIdx+1, 0)),
    59  			},
    60  		},
    61  		"Contiguous2": {
    62  			chunks: []ChunkIdx{
    63  				BaseChunkIdx,
    64  				BaseChunkIdx + 1,
    65  			},
    66  			inUse: []AddrRange{
    67  				MakeAddrRange(PageBase(BaseChunkIdx, 0), PageBase(BaseChunkIdx+2, 0)),
    68  			},
    69  		},
    70  		"Contiguous5": {
    71  			chunks: []ChunkIdx{
    72  				BaseChunkIdx,
    73  				BaseChunkIdx + 1,
    74  				BaseChunkIdx + 2,
    75  				BaseChunkIdx + 3,
    76  				BaseChunkIdx + 4,
    77  			},
    78  			inUse: []AddrRange{
    79  				MakeAddrRange(PageBase(BaseChunkIdx, 0), PageBase(BaseChunkIdx+5, 0)),
    80  			},
    81  		},
    82  		"Discontiguous": {
    83  			chunks: []ChunkIdx{
    84  				BaseChunkIdx,
    85  				BaseChunkIdx + 2,
    86  				BaseChunkIdx + 4,
    87  			},
    88  			inUse: []AddrRange{
    89  				MakeAddrRange(PageBase(BaseChunkIdx, 0), PageBase(BaseChunkIdx+1, 0)),
    90  				MakeAddrRange(PageBase(BaseChunkIdx+2, 0), PageBase(BaseChunkIdx+3, 0)),
    91  				MakeAddrRange(PageBase(BaseChunkIdx+4, 0), PageBase(BaseChunkIdx+5, 0)),
    92  			},
    93  		},
    94  		"Mixed": {
    95  			chunks: []ChunkIdx{
    96  				BaseChunkIdx,
    97  				BaseChunkIdx + 1,
    98  				BaseChunkIdx + 2,
    99  				BaseChunkIdx + 4,
   100  			},
   101  			inUse: []AddrRange{
   102  				MakeAddrRange(PageBase(BaseChunkIdx, 0), PageBase(BaseChunkIdx+3, 0)),
   103  				MakeAddrRange(PageBase(BaseChunkIdx+4, 0), PageBase(BaseChunkIdx+5, 0)),
   104  			},
   105  		},
   106  		"WildlyDiscontiguous": {
   107  			chunks: []ChunkIdx{
   108  				BaseChunkIdx,
   109  				BaseChunkIdx + 1,
   110  				BaseChunkIdx + 0x10,
   111  				BaseChunkIdx + 0x21,
   112  			},
   113  			inUse: []AddrRange{
   114  				MakeAddrRange(PageBase(BaseChunkIdx, 0), PageBase(BaseChunkIdx+2, 0)),
   115  				MakeAddrRange(PageBase(BaseChunkIdx+0x10, 0), PageBase(BaseChunkIdx+0x11, 0)),
   116  				MakeAddrRange(PageBase(BaseChunkIdx+0x21, 0), PageBase(BaseChunkIdx+0x22, 0)),
   117  			},
   118  		},
   119  		"ManyDiscontiguous": {
   120  			
   121  			chunks: []ChunkIdx{
   122  				BaseChunkIdx, BaseChunkIdx + 2, BaseChunkIdx + 4, BaseChunkIdx + 6,
   123  				BaseChunkIdx + 8, BaseChunkIdx + 10, BaseChunkIdx + 12, BaseChunkIdx + 14,
   124  				BaseChunkIdx + 16, BaseChunkIdx + 18, BaseChunkIdx + 20, BaseChunkIdx + 22,
   125  				BaseChunkIdx + 24, BaseChunkIdx + 26, BaseChunkIdx + 28, BaseChunkIdx + 30,
   126  				BaseChunkIdx + 32, BaseChunkIdx + 34, BaseChunkIdx + 36, BaseChunkIdx + 38,
   127  				BaseChunkIdx + 40, BaseChunkIdx + 42, BaseChunkIdx + 44, BaseChunkIdx + 46,
   128  				BaseChunkIdx + 48, BaseChunkIdx + 50, BaseChunkIdx + 52, BaseChunkIdx + 54,
   129  				BaseChunkIdx + 56, BaseChunkIdx + 58, BaseChunkIdx + 60, BaseChunkIdx + 62,
   130  				BaseChunkIdx + 64,
   131  			},
   132  			inUse: []AddrRange{
   133  				MakeAddrRange(PageBase(BaseChunkIdx, 0), PageBase(BaseChunkIdx+1, 0)),
   134  				MakeAddrRange(PageBase(BaseChunkIdx+2, 0), PageBase(BaseChunkIdx+3, 0)),
   135  				MakeAddrRange(PageBase(BaseChunkIdx+4, 0), PageBase(BaseChunkIdx+5, 0)),
   136  				MakeAddrRange(PageBase(BaseChunkIdx+6, 0), PageBase(BaseChunkIdx+7, 0)),
   137  				MakeAddrRange(PageBase(BaseChunkIdx+8, 0), PageBase(BaseChunkIdx+9, 0)),
   138  				MakeAddrRange(PageBase(BaseChunkIdx+10, 0), PageBase(BaseChunkIdx+11, 0)),
   139  				MakeAddrRange(PageBase(BaseChunkIdx+12, 0), PageBase(BaseChunkIdx+13, 0)),
   140  				MakeAddrRange(PageBase(BaseChunkIdx+14, 0), PageBase(BaseChunkIdx+15, 0)),
   141  				MakeAddrRange(PageBase(BaseChunkIdx+16, 0), PageBase(BaseChunkIdx+17, 0)),
   142  				MakeAddrRange(PageBase(BaseChunkIdx+18, 0), PageBase(BaseChunkIdx+19, 0)),
   143  				MakeAddrRange(PageBase(BaseChunkIdx+20, 0), PageBase(BaseChunkIdx+21, 0)),
   144  				MakeAddrRange(PageBase(BaseChunkIdx+22, 0), PageBase(BaseChunkIdx+23, 0)),
   145  				MakeAddrRange(PageBase(BaseChunkIdx+24, 0), PageBase(BaseChunkIdx+25, 0)),
   146  				MakeAddrRange(PageBase(BaseChunkIdx+26, 0), PageBase(BaseChunkIdx+27, 0)),
   147  				MakeAddrRange(PageBase(BaseChunkIdx+28, 0), PageBase(BaseChunkIdx+29, 0)),
   148  				MakeAddrRange(PageBase(BaseChunkIdx+30, 0), PageBase(BaseChunkIdx+31, 0)),
   149  				MakeAddrRange(PageBase(BaseChunkIdx+32, 0), PageBase(BaseChunkIdx+33, 0)),
   150  				MakeAddrRange(PageBase(BaseChunkIdx+34, 0), PageBase(BaseChunkIdx+35, 0)),
   151  				MakeAddrRange(PageBase(BaseChunkIdx+36, 0), PageBase(BaseChunkIdx+37, 0)),
   152  				MakeAddrRange(PageBase(BaseChunkIdx+38, 0), PageBase(BaseChunkIdx+39, 0)),
   153  				MakeAddrRange(PageBase(BaseChunkIdx+40, 0), PageBase(BaseChunkIdx+41, 0)),
   154  				MakeAddrRange(PageBase(BaseChunkIdx+42, 0), PageBase(BaseChunkIdx+43, 0)),
   155  				MakeAddrRange(PageBase(BaseChunkIdx+44, 0), PageBase(BaseChunkIdx+45, 0)),
   156  				MakeAddrRange(PageBase(BaseChunkIdx+46, 0), PageBase(BaseChunkIdx+47, 0)),
   157  				MakeAddrRange(PageBase(BaseChunkIdx+48, 0), PageBase(BaseChunkIdx+49, 0)),
   158  				MakeAddrRange(PageBase(BaseChunkIdx+50, 0), PageBase(BaseChunkIdx+51, 0)),
   159  				MakeAddrRange(PageBase(BaseChunkIdx+52, 0), PageBase(BaseChunkIdx+53, 0)),
   160  				MakeAddrRange(PageBase(BaseChunkIdx+54, 0), PageBase(BaseChunkIdx+55, 0)),
   161  				MakeAddrRange(PageBase(BaseChunkIdx+56, 0), PageBase(BaseChunkIdx+57, 0)),
   162  				MakeAddrRange(PageBase(BaseChunkIdx+58, 0), PageBase(BaseChunkIdx+59, 0)),
   163  				MakeAddrRange(PageBase(BaseChunkIdx+60, 0), PageBase(BaseChunkIdx+61, 0)),
   164  				MakeAddrRange(PageBase(BaseChunkIdx+62, 0), PageBase(BaseChunkIdx+63, 0)),
   165  				MakeAddrRange(PageBase(BaseChunkIdx+64, 0), PageBase(BaseChunkIdx+65, 0)),
   166  			},
   167  		},
   168  	}
   169  	
   170  	
   171  	if PageAlloc64Bit != 0 && goos.IsIos == 0 {
   172  		tests["ExtremelyDiscontiguous"] = test{
   173  			chunks: []ChunkIdx{
   174  				BaseChunkIdx,
   175  				BaseChunkIdx + 0x100000, 
   176  			},
   177  			inUse: []AddrRange{
   178  				MakeAddrRange(PageBase(BaseChunkIdx, 0), PageBase(BaseChunkIdx+1, 0)),
   179  				MakeAddrRange(PageBase(BaseChunkIdx+0x100000, 0), PageBase(BaseChunkIdx+0x100001, 0)),
   180  			},
   181  		}
   182  	}
   183  	for name, v := range tests {
   184  		t.Run(name, func(t *testing.T) {
   185  			
   186  			
   187  			x := make(map[ChunkIdx][]BitRange)
   188  			for _, c := range v.chunks {
   189  				x[c] = []BitRange{}
   190  			}
   191  			b := NewPageAlloc(x, nil)
   192  			defer FreePageAlloc(b)
   193  
   194  			got := b.InUse()
   195  			want := v.inUse
   196  
   197  			
   198  			if len(got) != len(want) {
   199  				t.Fail()
   200  			} else {
   201  				for i := range want {
   202  					if !want[i].Equals(got[i]) {
   203  						t.Fail()
   204  						break
   205  					}
   206  				}
   207  			}
   208  			if t.Failed() {
   209  				t.Logf("found inUse mismatch")
   210  				t.Logf("got:")
   211  				for i, r := range got {
   212  					t.Logf("\t#%d [0x%x, 0x%x)", i, r.Base(), r.Limit())
   213  				}
   214  				t.Logf("want:")
   215  				for i, r := range want {
   216  					t.Logf("\t#%d [0x%x, 0x%x)", i, r.Base(), r.Limit())
   217  				}
   218  			}
   219  		})
   220  	}
   221  }
   222  
   223  func TestPageAllocAlloc(t *testing.T) {
   224  	if GOOS == "openbsd" && testing.Short() {
   225  		t.Skip("skipping because virtual memory is limited; see #36210")
   226  	}
   227  	type hit struct {
   228  		npages, base, scav uintptr
   229  	}
   230  	type test struct {
   231  		scav   map[ChunkIdx][]BitRange
   232  		before map[ChunkIdx][]BitRange
   233  		after  map[ChunkIdx][]BitRange
   234  		hits   []hit
   235  	}
   236  	tests := map[string]test{
   237  		"AllFree1": {
   238  			before: map[ChunkIdx][]BitRange{
   239  				BaseChunkIdx: {},
   240  			},
   241  			scav: map[ChunkIdx][]BitRange{
   242  				BaseChunkIdx: {{0, 1}, {2, 2}},
   243  			},
   244  			hits: []hit{
   245  				{1, PageBase(BaseChunkIdx, 0), PageSize},
   246  				{1, PageBase(BaseChunkIdx, 1), 0},
   247  				{1, PageBase(BaseChunkIdx, 2), PageSize},
   248  				{1, PageBase(BaseChunkIdx, 3), PageSize},
   249  				{1, PageBase(BaseChunkIdx, 4), 0},
   250  			},
   251  			after: map[ChunkIdx][]BitRange{
   252  				BaseChunkIdx: {{0, 5}},
   253  			},
   254  		},
   255  		"ManyArena1": {
   256  			before: map[ChunkIdx][]BitRange{
   257  				BaseChunkIdx:     {{0, PallocChunkPages}},
   258  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   259  				BaseChunkIdx + 2: {{0, PallocChunkPages - 1}},
   260  			},
   261  			scav: map[ChunkIdx][]BitRange{
   262  				BaseChunkIdx:     {{0, PallocChunkPages}},
   263  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   264  				BaseChunkIdx + 2: {{0, PallocChunkPages}},
   265  			},
   266  			hits: []hit{
   267  				{1, PageBase(BaseChunkIdx+2, PallocChunkPages-1), PageSize},
   268  			},
   269  			after: map[ChunkIdx][]BitRange{
   270  				BaseChunkIdx:     {{0, PallocChunkPages}},
   271  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   272  				BaseChunkIdx + 2: {{0, PallocChunkPages}},
   273  			},
   274  		},
   275  		"NotContiguous1": {
   276  			before: map[ChunkIdx][]BitRange{
   277  				BaseChunkIdx:        {{0, PallocChunkPages}},
   278  				BaseChunkIdx + 0xff: {{0, 0}},
   279  			},
   280  			scav: map[ChunkIdx][]BitRange{
   281  				BaseChunkIdx:        {{0, PallocChunkPages}},
   282  				BaseChunkIdx + 0xff: {{0, PallocChunkPages}},
   283  			},
   284  			hits: []hit{
   285  				{1, PageBase(BaseChunkIdx+0xff, 0), PageSize},
   286  			},
   287  			after: map[ChunkIdx][]BitRange{
   288  				BaseChunkIdx:        {{0, PallocChunkPages}},
   289  				BaseChunkIdx + 0xff: {{0, 1}},
   290  			},
   291  		},
   292  		"AllFree2": {
   293  			before: map[ChunkIdx][]BitRange{
   294  				BaseChunkIdx: {},
   295  			},
   296  			scav: map[ChunkIdx][]BitRange{
   297  				BaseChunkIdx: {{0, 3}, {7, 1}},
   298  			},
   299  			hits: []hit{
   300  				{2, PageBase(BaseChunkIdx, 0), 2 * PageSize},
   301  				{2, PageBase(BaseChunkIdx, 2), PageSize},
   302  				{2, PageBase(BaseChunkIdx, 4), 0},
   303  				{2, PageBase(BaseChunkIdx, 6), PageSize},
   304  				{2, PageBase(BaseChunkIdx, 8), 0},
   305  			},
   306  			after: map[ChunkIdx][]BitRange{
   307  				BaseChunkIdx: {{0, 10}},
   308  			},
   309  		},
   310  		"Straddle2": {
   311  			before: map[ChunkIdx][]BitRange{
   312  				BaseChunkIdx:     {{0, PallocChunkPages - 1}},
   313  				BaseChunkIdx + 1: {{1, PallocChunkPages - 1}},
   314  			},
   315  			scav: map[ChunkIdx][]BitRange{
   316  				BaseChunkIdx:     {{PallocChunkPages - 1, 1}},
   317  				BaseChunkIdx + 1: {},
   318  			},
   319  			hits: []hit{
   320  				{2, PageBase(BaseChunkIdx, PallocChunkPages-1), PageSize},
   321  			},
   322  			after: map[ChunkIdx][]BitRange{
   323  				BaseChunkIdx:     {{0, PallocChunkPages}},
   324  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   325  			},
   326  		},
   327  		"AllFree5": {
   328  			before: map[ChunkIdx][]BitRange{
   329  				BaseChunkIdx: {},
   330  			},
   331  			scav: map[ChunkIdx][]BitRange{
   332  				BaseChunkIdx: {{0, 8}, {9, 1}, {17, 5}},
   333  			},
   334  			hits: []hit{
   335  				{5, PageBase(BaseChunkIdx, 0), 5 * PageSize},
   336  				{5, PageBase(BaseChunkIdx, 5), 4 * PageSize},
   337  				{5, PageBase(BaseChunkIdx, 10), 0},
   338  				{5, PageBase(BaseChunkIdx, 15), 3 * PageSize},
   339  				{5, PageBase(BaseChunkIdx, 20), 2 * PageSize},
   340  			},
   341  			after: map[ChunkIdx][]BitRange{
   342  				BaseChunkIdx: {{0, 25}},
   343  			},
   344  		},
   345  		"ExhaustPallocChunkPages-3": {
   346  			before: map[ChunkIdx][]BitRange{
   347  				BaseChunkIdx: {},
   348  			},
   349  			scav: map[ChunkIdx][]BitRange{
   350  				BaseChunkIdx: {{10, 1}},
   351  			},
   352  			hits: []hit{
   353  				{PallocChunkPages - 3, PageBase(BaseChunkIdx, 0), PageSize},
   354  				{PallocChunkPages - 3, 0, 0},
   355  				{1, PageBase(BaseChunkIdx, PallocChunkPages-3), 0},
   356  				{2, PageBase(BaseChunkIdx, PallocChunkPages-2), 0},
   357  				{1, 0, 0},
   358  				{PallocChunkPages - 3, 0, 0},
   359  			},
   360  			after: map[ChunkIdx][]BitRange{
   361  				BaseChunkIdx: {{0, PallocChunkPages}},
   362  			},
   363  		},
   364  		"AllFreePallocChunkPages": {
   365  			before: map[ChunkIdx][]BitRange{
   366  				BaseChunkIdx: {},
   367  			},
   368  			scav: map[ChunkIdx][]BitRange{
   369  				BaseChunkIdx: {{0, 1}, {PallocChunkPages - 1, 1}},
   370  			},
   371  			hits: []hit{
   372  				{PallocChunkPages, PageBase(BaseChunkIdx, 0), 2 * PageSize},
   373  				{PallocChunkPages, 0, 0},
   374  				{1, 0, 0},
   375  			},
   376  			after: map[ChunkIdx][]BitRange{
   377  				BaseChunkIdx: {{0, PallocChunkPages}},
   378  			},
   379  		},
   380  		"StraddlePallocChunkPages+1": {
   381  			before: map[ChunkIdx][]BitRange{
   382  				BaseChunkIdx:     {{0, PallocChunkPages / 2}},
   383  				BaseChunkIdx + 1: {},
   384  			},
   385  			scav: map[ChunkIdx][]BitRange{
   386  				BaseChunkIdx:     {{0, PallocChunkPages}},
   387  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   388  			},
   389  			hits: []hit{
   390  				{PallocChunkPages + 1, PageBase(BaseChunkIdx, PallocChunkPages/2), (PallocChunkPages + 1) * PageSize},
   391  				{PallocChunkPages, 0, 0},
   392  				{1, PageBase(BaseChunkIdx+1, PallocChunkPages/2+1), PageSize},
   393  			},
   394  			after: map[ChunkIdx][]BitRange{
   395  				BaseChunkIdx:     {{0, PallocChunkPages}},
   396  				BaseChunkIdx + 1: {{0, PallocChunkPages/2 + 2}},
   397  			},
   398  		},
   399  		"AllFreePallocChunkPages*2": {
   400  			before: map[ChunkIdx][]BitRange{
   401  				BaseChunkIdx:     {},
   402  				BaseChunkIdx + 1: {},
   403  			},
   404  			scav: map[ChunkIdx][]BitRange{
   405  				BaseChunkIdx:     {},
   406  				BaseChunkIdx + 1: {},
   407  			},
   408  			hits: []hit{
   409  				{PallocChunkPages * 2, PageBase(BaseChunkIdx, 0), 0},
   410  				{PallocChunkPages * 2, 0, 0},
   411  				{1, 0, 0},
   412  			},
   413  			after: map[ChunkIdx][]BitRange{
   414  				BaseChunkIdx:     {{0, PallocChunkPages}},
   415  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   416  			},
   417  		},
   418  		"NotContiguousPallocChunkPages*2": {
   419  			before: map[ChunkIdx][]BitRange{
   420  				BaseChunkIdx:        {},
   421  				BaseChunkIdx + 0x40: {},
   422  				BaseChunkIdx + 0x41: {},
   423  			},
   424  			scav: map[ChunkIdx][]BitRange{
   425  				BaseChunkIdx:        {{0, PallocChunkPages}},
   426  				BaseChunkIdx + 0x40: {},
   427  				BaseChunkIdx + 0x41: {},
   428  			},
   429  			hits: []hit{
   430  				{PallocChunkPages * 2, PageBase(BaseChunkIdx+0x40, 0), 0},
   431  				{21, PageBase(BaseChunkIdx, 0), 21 * PageSize},
   432  				{1, PageBase(BaseChunkIdx, 21), PageSize},
   433  			},
   434  			after: map[ChunkIdx][]BitRange{
   435  				BaseChunkIdx:        {{0, 22}},
   436  				BaseChunkIdx + 0x40: {{0, PallocChunkPages}},
   437  				BaseChunkIdx + 0x41: {{0, PallocChunkPages}},
   438  			},
   439  		},
   440  		"StraddlePallocChunkPages*5/4": {
   441  			before: map[ChunkIdx][]BitRange{
   442  				BaseChunkIdx:     {{0, PallocChunkPages}},
   443  				BaseChunkIdx + 1: {{0, PallocChunkPages * 3 / 4}},
   444  				BaseChunkIdx + 2: {{0, PallocChunkPages * 3 / 4}},
   445  				BaseChunkIdx + 3: {{0, 0}},
   446  			},
   447  			scav: map[ChunkIdx][]BitRange{
   448  				BaseChunkIdx:     {{0, PallocChunkPages}},
   449  				BaseChunkIdx + 1: {{PallocChunkPages / 2, PallocChunkPages/4 + 1}},
   450  				BaseChunkIdx + 2: {{PallocChunkPages / 3, 1}},
   451  				BaseChunkIdx + 3: {{PallocChunkPages * 2 / 3, 1}},
   452  			},
   453  			hits: []hit{
   454  				{PallocChunkPages * 5 / 4, PageBase(BaseChunkIdx+2, PallocChunkPages*3/4), PageSize},
   455  				{PallocChunkPages * 5 / 4, 0, 0},
   456  				{1, PageBase(BaseChunkIdx+1, PallocChunkPages*3/4), PageSize},
   457  			},
   458  			after: map[ChunkIdx][]BitRange{
   459  				BaseChunkIdx:     {{0, PallocChunkPages}},
   460  				BaseChunkIdx + 1: {{0, PallocChunkPages*3/4 + 1}},
   461  				BaseChunkIdx + 2: {{0, PallocChunkPages}},
   462  				BaseChunkIdx + 3: {{0, PallocChunkPages}},
   463  			},
   464  		},
   465  	}
   466  	if PallocChunkPages >= 512 {
   467  		tests["AllFree64"] = test{
   468  			before: map[ChunkIdx][]BitRange{
   469  				BaseChunkIdx: {},
   470  			},
   471  			scav: map[ChunkIdx][]BitRange{
   472  				BaseChunkIdx: {{21, 1}, {63, 65}},
   473  			},
   474  			hits: []hit{
   475  				{64, PageBase(BaseChunkIdx, 0), 2 * PageSize},
   476  				{64, PageBase(BaseChunkIdx, 64), 64 * PageSize},
   477  				{64, PageBase(BaseChunkIdx, 128), 0},
   478  			},
   479  			after: map[ChunkIdx][]BitRange{
   480  				BaseChunkIdx: {{0, 192}},
   481  			},
   482  		}
   483  		tests["AllFree65"] = test{
   484  			before: map[ChunkIdx][]BitRange{
   485  				BaseChunkIdx: {},
   486  			},
   487  			scav: map[ChunkIdx][]BitRange{
   488  				BaseChunkIdx: {{129, 1}},
   489  			},
   490  			hits: []hit{
   491  				{65, PageBase(BaseChunkIdx, 0), 0},
   492  				{65, PageBase(BaseChunkIdx, 65), PageSize},
   493  				{65, PageBase(BaseChunkIdx, 130), 0},
   494  			},
   495  			after: map[ChunkIdx][]BitRange{
   496  				BaseChunkIdx: {{0, 195}},
   497  			},
   498  		}
   499  		tests["StraddlePallocChunkPages"] = test{
   500  			before: map[ChunkIdx][]BitRange{
   501  				BaseChunkIdx:     {{0, PallocChunkPages / 2}},
   502  				BaseChunkIdx + 1: {{PallocChunkPages / 2, PallocChunkPages / 2}},
   503  			},
   504  			scav: map[ChunkIdx][]BitRange{
   505  				BaseChunkIdx:     {},
   506  				BaseChunkIdx + 1: {{3, 100}},
   507  			},
   508  			hits: []hit{
   509  				{PallocChunkPages, PageBase(BaseChunkIdx, PallocChunkPages/2), 100 * PageSize},
   510  				{PallocChunkPages, 0, 0},
   511  				{1, 0, 0},
   512  			},
   513  			after: map[ChunkIdx][]BitRange{
   514  				BaseChunkIdx:     {{0, PallocChunkPages}},
   515  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   516  			},
   517  		}
   518  		tests["AllFreePallocChunkPages*7+5"] = test{
   519  			before: map[ChunkIdx][]BitRange{
   520  				BaseChunkIdx:     {},
   521  				BaseChunkIdx + 1: {},
   522  				BaseChunkIdx + 2: {},
   523  				BaseChunkIdx + 3: {},
   524  				BaseChunkIdx + 4: {},
   525  				BaseChunkIdx + 5: {},
   526  				BaseChunkIdx + 6: {},
   527  				BaseChunkIdx + 7: {},
   528  			},
   529  			scav: map[ChunkIdx][]BitRange{
   530  				BaseChunkIdx:     {{50, 1}},
   531  				BaseChunkIdx + 1: {{31, 1}},
   532  				BaseChunkIdx + 2: {{7, 1}},
   533  				BaseChunkIdx + 3: {{200, 1}},
   534  				BaseChunkIdx + 4: {{3, 1}},
   535  				BaseChunkIdx + 5: {{51, 1}},
   536  				BaseChunkIdx + 6: {{20, 1}},
   537  				BaseChunkIdx + 7: {{1, 1}},
   538  			},
   539  			hits: []hit{
   540  				{PallocChunkPages*7 + 5, PageBase(BaseChunkIdx, 0), 8 * PageSize},
   541  				{PallocChunkPages*7 + 5, 0, 0},
   542  				{1, PageBase(BaseChunkIdx+7, 5), 0},
   543  			},
   544  			after: map[ChunkIdx][]BitRange{
   545  				BaseChunkIdx:     {{0, PallocChunkPages}},
   546  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   547  				BaseChunkIdx + 2: {{0, PallocChunkPages}},
   548  				BaseChunkIdx + 3: {{0, PallocChunkPages}},
   549  				BaseChunkIdx + 4: {{0, PallocChunkPages}},
   550  				BaseChunkIdx + 5: {{0, PallocChunkPages}},
   551  				BaseChunkIdx + 6: {{0, PallocChunkPages}},
   552  				BaseChunkIdx + 7: {{0, 6}},
   553  			},
   554  		}
   555  		tests["StraddlePallocChunkPages*2"] = test{
   556  			before: map[ChunkIdx][]BitRange{
   557  				BaseChunkIdx:     {{0, PallocChunkPages / 2}},
   558  				BaseChunkIdx + 1: {},
   559  				BaseChunkIdx + 2: {{PallocChunkPages / 2, PallocChunkPages / 2}},
   560  			},
   561  			scav: map[ChunkIdx][]BitRange{
   562  				BaseChunkIdx:     {{0, 7}},
   563  				BaseChunkIdx + 1: {{3, 5}, {121, 10}},
   564  				BaseChunkIdx + 2: {{PallocChunkPages/2 + 12, 2}},
   565  			},
   566  			hits: []hit{
   567  				{PallocChunkPages * 2, PageBase(BaseChunkIdx, PallocChunkPages/2), 15 * PageSize},
   568  				{PallocChunkPages * 2, 0, 0},
   569  				{1, 0, 0},
   570  			},
   571  			after: map[ChunkIdx][]BitRange{
   572  				BaseChunkIdx:     {{0, PallocChunkPages}},
   573  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   574  				BaseChunkIdx + 2: {{0, PallocChunkPages}},
   575  			},
   576  		}
   577  	}
   578  	
   579  	
   580  	if PageAlloc64Bit != 0 && goos.IsIos == 0 {
   581  		const chunkIdxBigJump = 0x100000 
   582  
   583  		
   584  		
   585  		
   586  		
   587  		
   588  		
   589  		
   590  		
   591  		
   592  		
   593  		
   594  
   595  		
   596  		
   597  		
   598  		sumsPerPhysPage := ChunkIdx(PhysPageSize / PallocSumBytes)
   599  		baseChunkIdx := BaseChunkIdx &^ (sumsPerPhysPage - 1)
   600  		tests["DiscontiguousMappedSumBoundary"] = test{
   601  			before: map[ChunkIdx][]BitRange{
   602  				baseChunkIdx + sumsPerPhysPage - 1: {},
   603  				baseChunkIdx + chunkIdxBigJump:     {},
   604  			},
   605  			scav: map[ChunkIdx][]BitRange{
   606  				baseChunkIdx + sumsPerPhysPage - 1: {},
   607  				baseChunkIdx + chunkIdxBigJump:     {},
   608  			},
   609  			hits: []hit{
   610  				{PallocChunkPages - 1, PageBase(baseChunkIdx+sumsPerPhysPage-1, 0), 0},
   611  				{1, PageBase(baseChunkIdx+sumsPerPhysPage-1, PallocChunkPages-1), 0},
   612  				{1, PageBase(baseChunkIdx+chunkIdxBigJump, 0), 0},
   613  				{PallocChunkPages - 1, PageBase(baseChunkIdx+chunkIdxBigJump, 1), 0},
   614  				{1, 0, 0},
   615  			},
   616  			after: map[ChunkIdx][]BitRange{
   617  				baseChunkIdx + sumsPerPhysPage - 1: {{0, PallocChunkPages}},
   618  				baseChunkIdx + chunkIdxBigJump:     {{0, PallocChunkPages}},
   619  			},
   620  		}
   621  
   622  		
   623  		
   624  		
   625  		
   626  		
   627  		
   628  		
   629  		const chunkIdxSmallOffset = 0x503
   630  		tests["DiscontiguousBadSearchAddr"] = test{
   631  			before: map[ChunkIdx][]BitRange{
   632  				
   633  				
   634  				
   635  				
   636  				
   637  				
   638  				
   639  				
   640  				
   641  				BaseChunkIdx + chunkIdxBigJump*0: {{0, PallocChunkPages - 1}},
   642  				BaseChunkIdx + chunkIdxBigJump*1 + chunkIdxSmallOffset: {
   643  					{0, PallocChunkPages - 10},
   644  					{PallocChunkPages - 1, 1},
   645  				},
   646  				BaseChunkIdx + chunkIdxBigJump*2: {},
   647  			},
   648  			scav: map[ChunkIdx][]BitRange{
   649  				BaseChunkIdx + chunkIdxBigJump*0:                       {},
   650  				BaseChunkIdx + chunkIdxBigJump*1 + chunkIdxSmallOffset: {},
   651  				BaseChunkIdx + chunkIdxBigJump*2:                       {},
   652  			},
   653  			hits: []hit{
   654  				
   655  				
   656  				{1, PageBase(BaseChunkIdx, PallocChunkPages-1), 0},
   657  				
   658  				
   659  				
   660  				
   661  				
   662  				
   663  				
   664  				{100, PageBase(baseChunkIdx+chunkIdxBigJump*2, 0), 0},
   665  				
   666  				
   667  				
   668  				
   669  				
   670  				{9, PageBase(baseChunkIdx+chunkIdxBigJump*1+chunkIdxSmallOffset, PallocChunkPages-10), 0},
   671  			},
   672  			after: map[ChunkIdx][]BitRange{
   673  				BaseChunkIdx + chunkIdxBigJump*0:                       {{0, PallocChunkPages}},
   674  				BaseChunkIdx + chunkIdxBigJump*1 + chunkIdxSmallOffset: {{0, PallocChunkPages}},
   675  				BaseChunkIdx + chunkIdxBigJump*2:                       {{0, 100}},
   676  			},
   677  		}
   678  	}
   679  	for name, v := range tests {
   680  		t.Run(name, func(t *testing.T) {
   681  			b := NewPageAlloc(v.before, v.scav)
   682  			defer FreePageAlloc(b)
   683  
   684  			for iter, i := range v.hits {
   685  				a, s := b.Alloc(i.npages)
   686  				if a != i.base {
   687  					t.Fatalf("bad alloc #%d: want base 0x%x, got 0x%x", iter+1, i.base, a)
   688  				}
   689  				if s != i.scav {
   690  					t.Fatalf("bad alloc #%d: want scav %d, got %d", iter+1, i.scav, s)
   691  				}
   692  			}
   693  			want := NewPageAlloc(v.after, v.scav)
   694  			defer FreePageAlloc(want)
   695  
   696  			checkPageAlloc(t, want, b)
   697  		})
   698  	}
   699  }
   700  
   701  func TestPageAllocExhaust(t *testing.T) {
   702  	if GOOS == "openbsd" && testing.Short() {
   703  		t.Skip("skipping because virtual memory is limited; see #36210")
   704  	}
   705  	for _, npages := range []uintptr{1, 2, 3, 4, 5, 8, 16, 64, 1024, 1025, 2048, 2049} {
   706  		t.Run(fmt.Sprintf("%d", npages), func(t *testing.T) {
   707  			
   708  			bDesc := make(map[ChunkIdx][]BitRange)
   709  			for i := ChunkIdx(0); i < 4; i++ {
   710  				bDesc[BaseChunkIdx+i] = []BitRange{}
   711  			}
   712  			b := NewPageAlloc(bDesc, nil)
   713  			defer FreePageAlloc(b)
   714  
   715  			
   716  			nAlloc := (PallocChunkPages * 4) / int(npages)
   717  			for i := 0; i < nAlloc; i++ {
   718  				addr := PageBase(BaseChunkIdx, uint(i)*uint(npages))
   719  				if a, _ := b.Alloc(npages); a != addr {
   720  					t.Fatalf("bad alloc #%d: want 0x%x, got 0x%x", i+1, addr, a)
   721  				}
   722  			}
   723  
   724  			
   725  			if a, _ := b.Alloc(npages); a != 0 {
   726  				t.Fatalf("bad alloc #%d: want 0, got 0x%x", nAlloc, a)
   727  			}
   728  
   729  			
   730  			allocPages := nAlloc * int(npages)
   731  			wantDesc := make(map[ChunkIdx][]BitRange)
   732  			for i := ChunkIdx(0); i < 4; i++ {
   733  				if allocPages >= PallocChunkPages {
   734  					wantDesc[BaseChunkIdx+i] = []BitRange{{0, PallocChunkPages}}
   735  					allocPages -= PallocChunkPages
   736  				} else if allocPages > 0 {
   737  					wantDesc[BaseChunkIdx+i] = []BitRange{{0, uint(allocPages)}}
   738  					allocPages = 0
   739  				} else {
   740  					wantDesc[BaseChunkIdx+i] = []BitRange{}
   741  				}
   742  			}
   743  			want := NewPageAlloc(wantDesc, nil)
   744  			defer FreePageAlloc(want)
   745  
   746  			
   747  			checkPageAlloc(t, want, b)
   748  		})
   749  	}
   750  }
   751  
   752  func TestPageAllocFree(t *testing.T) {
   753  	if GOOS == "openbsd" && testing.Short() {
   754  		t.Skip("skipping because virtual memory is limited; see #36210")
   755  	}
   756  	type test struct {
   757  		before map[ChunkIdx][]BitRange
   758  		after  map[ChunkIdx][]BitRange
   759  		npages uintptr
   760  		frees  []uintptr
   761  	}
   762  	tests := map[string]test{
   763  		"Free1": {
   764  			npages: 1,
   765  			before: map[ChunkIdx][]BitRange{
   766  				BaseChunkIdx: {{0, PallocChunkPages}},
   767  			},
   768  			frees: []uintptr{
   769  				PageBase(BaseChunkIdx, 0),
   770  				PageBase(BaseChunkIdx, 1),
   771  				PageBase(BaseChunkIdx, 2),
   772  				PageBase(BaseChunkIdx, 3),
   773  				PageBase(BaseChunkIdx, 4),
   774  			},
   775  			after: map[ChunkIdx][]BitRange{
   776  				BaseChunkIdx: {{5, PallocChunkPages - 5}},
   777  			},
   778  		},
   779  		"ManyArena1": {
   780  			npages: 1,
   781  			before: map[ChunkIdx][]BitRange{
   782  				BaseChunkIdx:     {{0, PallocChunkPages}},
   783  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   784  				BaseChunkIdx + 2: {{0, PallocChunkPages}},
   785  			},
   786  			frees: []uintptr{
   787  				PageBase(BaseChunkIdx, PallocChunkPages/2),
   788  				PageBase(BaseChunkIdx+1, 0),
   789  				PageBase(BaseChunkIdx+2, PallocChunkPages-1),
   790  			},
   791  			after: map[ChunkIdx][]BitRange{
   792  				BaseChunkIdx:     {{0, PallocChunkPages / 2}, {PallocChunkPages/2 + 1, PallocChunkPages/2 - 1}},
   793  				BaseChunkIdx + 1: {{1, PallocChunkPages - 1}},
   794  				BaseChunkIdx + 2: {{0, PallocChunkPages - 1}},
   795  			},
   796  		},
   797  		"Free2": {
   798  			npages: 2,
   799  			before: map[ChunkIdx][]BitRange{
   800  				BaseChunkIdx: {{0, PallocChunkPages}},
   801  			},
   802  			frees: []uintptr{
   803  				PageBase(BaseChunkIdx, 0),
   804  				PageBase(BaseChunkIdx, 2),
   805  				PageBase(BaseChunkIdx, 4),
   806  				PageBase(BaseChunkIdx, 6),
   807  				PageBase(BaseChunkIdx, 8),
   808  			},
   809  			after: map[ChunkIdx][]BitRange{
   810  				BaseChunkIdx: {{10, PallocChunkPages - 10}},
   811  			},
   812  		},
   813  		"Straddle2": {
   814  			npages: 2,
   815  			before: map[ChunkIdx][]BitRange{
   816  				BaseChunkIdx:     {{PallocChunkPages - 1, 1}},
   817  				BaseChunkIdx + 1: {{0, 1}},
   818  			},
   819  			frees: []uintptr{
   820  				PageBase(BaseChunkIdx, PallocChunkPages-1),
   821  			},
   822  			after: map[ChunkIdx][]BitRange{
   823  				BaseChunkIdx:     {},
   824  				BaseChunkIdx + 1: {},
   825  			},
   826  		},
   827  		"Free5": {
   828  			npages: 5,
   829  			before: map[ChunkIdx][]BitRange{
   830  				BaseChunkIdx: {{0, PallocChunkPages}},
   831  			},
   832  			frees: []uintptr{
   833  				PageBase(BaseChunkIdx, 0),
   834  				PageBase(BaseChunkIdx, 5),
   835  				PageBase(BaseChunkIdx, 10),
   836  				PageBase(BaseChunkIdx, 15),
   837  				PageBase(BaseChunkIdx, 20),
   838  			},
   839  			after: map[ChunkIdx][]BitRange{
   840  				BaseChunkIdx: {{25, PallocChunkPages - 25}},
   841  			},
   842  		},
   843  		"FreePallocChunkPages": {
   844  			npages: PallocChunkPages,
   845  			before: map[ChunkIdx][]BitRange{
   846  				BaseChunkIdx: {{0, PallocChunkPages}},
   847  			},
   848  			frees: []uintptr{
   849  				PageBase(BaseChunkIdx, 0),
   850  			},
   851  			after: map[ChunkIdx][]BitRange{
   852  				BaseChunkIdx: {},
   853  			},
   854  		},
   855  		"StraddlePallocChunkPages": {
   856  			npages: PallocChunkPages,
   857  			before: map[ChunkIdx][]BitRange{
   858  				BaseChunkIdx:     {{PallocChunkPages / 2, PallocChunkPages / 2}},
   859  				BaseChunkIdx + 1: {{0, PallocChunkPages / 2}},
   860  			},
   861  			frees: []uintptr{
   862  				PageBase(BaseChunkIdx, PallocChunkPages/2),
   863  			},
   864  			after: map[ChunkIdx][]BitRange{
   865  				BaseChunkIdx:     {},
   866  				BaseChunkIdx + 1: {},
   867  			},
   868  		},
   869  		"StraddlePallocChunkPages+1": {
   870  			npages: PallocChunkPages + 1,
   871  			before: map[ChunkIdx][]BitRange{
   872  				BaseChunkIdx:     {{0, PallocChunkPages}},
   873  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   874  			},
   875  			frees: []uintptr{
   876  				PageBase(BaseChunkIdx, PallocChunkPages/2),
   877  			},
   878  			after: map[ChunkIdx][]BitRange{
   879  				BaseChunkIdx:     {{0, PallocChunkPages / 2}},
   880  				BaseChunkIdx + 1: {{PallocChunkPages/2 + 1, PallocChunkPages/2 - 1}},
   881  			},
   882  		},
   883  		"FreePallocChunkPages*2": {
   884  			npages: PallocChunkPages * 2,
   885  			before: map[ChunkIdx][]BitRange{
   886  				BaseChunkIdx:     {{0, PallocChunkPages}},
   887  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   888  			},
   889  			frees: []uintptr{
   890  				PageBase(BaseChunkIdx, 0),
   891  			},
   892  			after: map[ChunkIdx][]BitRange{
   893  				BaseChunkIdx:     {},
   894  				BaseChunkIdx + 1: {},
   895  			},
   896  		},
   897  		"StraddlePallocChunkPages*2": {
   898  			npages: PallocChunkPages * 2,
   899  			before: map[ChunkIdx][]BitRange{
   900  				BaseChunkIdx:     {{0, PallocChunkPages}},
   901  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   902  				BaseChunkIdx + 2: {{0, PallocChunkPages}},
   903  			},
   904  			frees: []uintptr{
   905  				PageBase(BaseChunkIdx, PallocChunkPages/2),
   906  			},
   907  			after: map[ChunkIdx][]BitRange{
   908  				BaseChunkIdx:     {{0, PallocChunkPages / 2}},
   909  				BaseChunkIdx + 1: {},
   910  				BaseChunkIdx + 2: {{PallocChunkPages / 2, PallocChunkPages / 2}},
   911  			},
   912  		},
   913  		"AllFreePallocChunkPages*7+5": {
   914  			npages: PallocChunkPages*7 + 5,
   915  			before: map[ChunkIdx][]BitRange{
   916  				BaseChunkIdx:     {{0, PallocChunkPages}},
   917  				BaseChunkIdx + 1: {{0, PallocChunkPages}},
   918  				BaseChunkIdx + 2: {{0, PallocChunkPages}},
   919  				BaseChunkIdx + 3: {{0, PallocChunkPages}},
   920  				BaseChunkIdx + 4: {{0, PallocChunkPages}},
   921  				BaseChunkIdx + 5: {{0, PallocChunkPages}},
   922  				BaseChunkIdx + 6: {{0, PallocChunkPages}},
   923  				BaseChunkIdx + 7: {{0, PallocChunkPages}},
   924  			},
   925  			frees: []uintptr{
   926  				PageBase(BaseChunkIdx, 0),
   927  			},
   928  			after: map[ChunkIdx][]BitRange{
   929  				BaseChunkIdx:     {},
   930  				BaseChunkIdx + 1: {},
   931  				BaseChunkIdx + 2: {},
   932  				BaseChunkIdx + 3: {},
   933  				BaseChunkIdx + 4: {},
   934  				BaseChunkIdx + 5: {},
   935  				BaseChunkIdx + 6: {},
   936  				BaseChunkIdx + 7: {{5, PallocChunkPages - 5}},
   937  			},
   938  		},
   939  	}
   940  	if PallocChunkPages >= 512 {
   941  		
   942  		var PallocChunkPages uint = PallocChunkPages
   943  		tests["Free64"] = test{
   944  			npages: 64,
   945  			before: map[ChunkIdx][]BitRange{
   946  				BaseChunkIdx: {{0, PallocChunkPages}},
   947  			},
   948  			frees: []uintptr{
   949  				PageBase(BaseChunkIdx, 0),
   950  				PageBase(BaseChunkIdx, 64),
   951  				PageBase(BaseChunkIdx, 128),
   952  			},
   953  			after: map[ChunkIdx][]BitRange{
   954  				BaseChunkIdx: {{192, PallocChunkPages - 192}},
   955  			},
   956  		}
   957  		tests["Free65"] = test{
   958  			npages: 65,
   959  			before: map[ChunkIdx][]BitRange{
   960  				BaseChunkIdx: {{0, PallocChunkPages}},
   961  			},
   962  			frees: []uintptr{
   963  				PageBase(BaseChunkIdx, 0),
   964  				PageBase(BaseChunkIdx, 65),
   965  				PageBase(BaseChunkIdx, 130),
   966  			},
   967  			after: map[ChunkIdx][]BitRange{
   968  				BaseChunkIdx: {{195, PallocChunkPages - 195}},
   969  			},
   970  		}
   971  	}
   972  	for name, v := range tests {
   973  		t.Run(name, func(t *testing.T) {
   974  			b := NewPageAlloc(v.before, nil)
   975  			defer FreePageAlloc(b)
   976  
   977  			for _, addr := range v.frees {
   978  				b.Free(addr, v.npages)
   979  			}
   980  			want := NewPageAlloc(v.after, nil)
   981  			defer FreePageAlloc(want)
   982  
   983  			checkPageAlloc(t, want, b)
   984  		})
   985  	}
   986  }
   987  
   988  func TestPageAllocAllocAndFree(t *testing.T) {
   989  	if GOOS == "openbsd" && testing.Short() {
   990  		t.Skip("skipping because virtual memory is limited; see #36210")
   991  	}
   992  	type hit struct {
   993  		alloc  bool
   994  		npages uintptr
   995  		base   uintptr
   996  	}
   997  	tests := map[string]struct {
   998  		init map[ChunkIdx][]BitRange
   999  		hits []hit
  1000  	}{
  1001  		
  1002  		"Chunks8": {
  1003  			init: map[ChunkIdx][]BitRange{
  1004  				BaseChunkIdx:     {},
  1005  				BaseChunkIdx + 1: {},
  1006  				BaseChunkIdx + 2: {},
  1007  				BaseChunkIdx + 3: {},
  1008  				BaseChunkIdx + 4: {},
  1009  				BaseChunkIdx + 5: {},
  1010  				BaseChunkIdx + 6: {},
  1011  				BaseChunkIdx + 7: {},
  1012  			},
  1013  			hits: []hit{
  1014  				{true, PallocChunkPages * 8, PageBase(BaseChunkIdx, 0)},
  1015  				{false, PallocChunkPages * 8, PageBase(BaseChunkIdx, 0)},
  1016  				{true, PallocChunkPages * 8, PageBase(BaseChunkIdx, 0)},
  1017  				{false, PallocChunkPages * 8, PageBase(BaseChunkIdx, 0)},
  1018  				{true, PallocChunkPages * 8, PageBase(BaseChunkIdx, 0)},
  1019  				{false, PallocChunkPages * 8, PageBase(BaseChunkIdx, 0)},
  1020  				{true, 1, PageBase(BaseChunkIdx, 0)},
  1021  				{false, 1, PageBase(BaseChunkIdx, 0)},
  1022  				{true, PallocChunkPages * 8, PageBase(BaseChunkIdx, 0)},
  1023  			},
  1024  		},
  1025  	}
  1026  	for name, v := range tests {
  1027  		t.Run(name, func(t *testing.T) {
  1028  			b := NewPageAlloc(v.init, nil)
  1029  			defer FreePageAlloc(b)
  1030  
  1031  			for iter, i := range v.hits {
  1032  				if i.alloc {
  1033  					if a, _ := b.Alloc(i.npages); a != i.base {
  1034  						t.Fatalf("bad alloc #%d: want 0x%x, got 0x%x", iter+1, i.base, a)
  1035  					}
  1036  				} else {
  1037  					b.Free(i.base, i.npages)
  1038  				}
  1039  			}
  1040  		})
  1041  	}
  1042  }
  1043  
View as plain text