Source file src/sync/atomic/atomic_test.go

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package atomic_test
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"runtime"
    11  	"runtime/debug"
    12  	"strings"
    13  	. "sync/atomic"
    14  	"testing"
    15  	"unsafe"
    16  )
    17  
    18  // Tests of correct behavior, without contention.
    19  // (Does the function work as advertised?)
    20  //
    21  // Test that the Add functions add correctly.
    22  // Test that the CompareAndSwap functions actually
    23  // do the comparison and the swap correctly.
    24  //
    25  // The loop over power-of-two values is meant to
    26  // ensure that the operations apply to the full word size.
    27  // The struct fields x.before and x.after check that the
    28  // operations do not extend past the full word size.
    29  
    30  const (
    31  	magic32 = 0xdedbeef
    32  	magic64 = 0xdeddeadbeefbeef
    33  )
    34  
    35  func TestSwapInt32(t *testing.T) {
    36  	var x struct {
    37  		before int32
    38  		i      int32
    39  		after  int32
    40  	}
    41  	x.before = magic32
    42  	x.after = magic32
    43  	var j int32
    44  	for delta := int32(1); delta+delta > delta; delta += delta {
    45  		k := SwapInt32(&x.i, delta)
    46  		if x.i != delta || k != j {
    47  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    48  		}
    49  		j = delta
    50  	}
    51  	if x.before != magic32 || x.after != magic32 {
    52  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    53  	}
    54  }
    55  
    56  func TestSwapInt32Method(t *testing.T) {
    57  	var x struct {
    58  		before int32
    59  		i      Int32
    60  		after  int32
    61  	}
    62  	x.before = magic32
    63  	x.after = magic32
    64  	var j int32
    65  	for delta := int32(1); delta+delta > delta; delta += delta {
    66  		k := x.i.Swap(delta)
    67  		if x.i.Load() != delta || k != j {
    68  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
    69  		}
    70  		j = delta
    71  	}
    72  	if x.before != magic32 || x.after != magic32 {
    73  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    74  	}
    75  }
    76  
    77  func TestSwapUint32(t *testing.T) {
    78  	var x struct {
    79  		before uint32
    80  		i      uint32
    81  		after  uint32
    82  	}
    83  	x.before = magic32
    84  	x.after = magic32
    85  	var j uint32
    86  	for delta := uint32(1); delta+delta > delta; delta += delta {
    87  		k := SwapUint32(&x.i, delta)
    88  		if x.i != delta || k != j {
    89  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    90  		}
    91  		j = delta
    92  	}
    93  	if x.before != magic32 || x.after != magic32 {
    94  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    95  	}
    96  }
    97  
    98  func TestSwapUint32Method(t *testing.T) {
    99  	var x struct {
   100  		before uint32
   101  		i      Uint32
   102  		after  uint32
   103  	}
   104  	x.before = magic32
   105  	x.after = magic32
   106  	var j uint32
   107  	for delta := uint32(1); delta+delta > delta; delta += delta {
   108  		k := x.i.Swap(delta)
   109  		if x.i.Load() != delta || k != j {
   110  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
   111  		}
   112  		j = delta
   113  	}
   114  	if x.before != magic32 || x.after != magic32 {
   115  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   116  	}
   117  }
   118  
   119  func TestSwapInt64(t *testing.T) {
   120  	var x struct {
   121  		before int64
   122  		i      int64
   123  		after  int64
   124  	}
   125  	magic64 := int64(magic64)
   126  	x.before = magic64
   127  	x.after = magic64
   128  	var j int64
   129  	for delta := int64(1); delta+delta > delta; delta += delta {
   130  		k := SwapInt64(&x.i, delta)
   131  		if x.i != delta || k != j {
   132  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   133  		}
   134  		j = delta
   135  	}
   136  	if x.before != magic64 || x.after != magic64 {
   137  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   138  	}
   139  }
   140  
   141  func TestSwapInt64Method(t *testing.T) {
   142  	var x struct {
   143  		before int64
   144  		i      Int64
   145  		after  int64
   146  	}
   147  	magic64 := int64(magic64)
   148  	x.before = magic64
   149  	x.after = magic64
   150  	var j int64
   151  	for delta := int64(1); delta+delta > delta; delta += delta {
   152  		k := x.i.Swap(delta)
   153  		if x.i.Load() != delta || k != j {
   154  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
   155  		}
   156  		j = delta
   157  	}
   158  	if x.before != magic64 || x.after != magic64 {
   159  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   160  	}
   161  }
   162  
   163  func TestSwapUint64(t *testing.T) {
   164  	var x struct {
   165  		before uint64
   166  		i      uint64
   167  		after  uint64
   168  	}
   169  	magic64 := uint64(magic64)
   170  	x.before = magic64
   171  	x.after = magic64
   172  	var j uint64
   173  	for delta := uint64(1); delta+delta > delta; delta += delta {
   174  		k := SwapUint64(&x.i, delta)
   175  		if x.i != delta || k != j {
   176  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   177  		}
   178  		j = delta
   179  	}
   180  	if x.before != magic64 || x.after != magic64 {
   181  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   182  	}
   183  }
   184  
   185  func TestSwapUint64Method(t *testing.T) {
   186  	var x struct {
   187  		before uint64
   188  		i      Uint64
   189  		after  uint64
   190  	}
   191  	magic64 := uint64(magic64)
   192  	x.before = magic64
   193  	x.after = magic64
   194  	var j uint64
   195  	for delta := uint64(1); delta+delta > delta; delta += delta {
   196  		k := x.i.Swap(delta)
   197  		if x.i.Load() != delta || k != j {
   198  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
   199  		}
   200  		j = delta
   201  	}
   202  	if x.before != magic64 || x.after != magic64 {
   203  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   204  	}
   205  }
   206  
   207  func TestSwapUintptr(t *testing.T) {
   208  	var x struct {
   209  		before uintptr
   210  		i      uintptr
   211  		after  uintptr
   212  	}
   213  	var m uint64 = magic64
   214  	magicptr := uintptr(m)
   215  	x.before = magicptr
   216  	x.after = magicptr
   217  	var j uintptr
   218  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   219  		k := SwapUintptr(&x.i, delta)
   220  		if x.i != delta || k != j {
   221  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   222  		}
   223  		j = delta
   224  	}
   225  	if x.before != magicptr || x.after != magicptr {
   226  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   227  	}
   228  }
   229  
   230  func TestSwapUintptrMethod(t *testing.T) {
   231  	var x struct {
   232  		before uintptr
   233  		i      Uintptr
   234  		after  uintptr
   235  	}
   236  	var m uint64 = magic64
   237  	magicptr := uintptr(m)
   238  	x.before = magicptr
   239  	x.after = magicptr
   240  	var j uintptr
   241  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   242  		k := x.i.Swap(delta)
   243  		if x.i.Load() != delta || k != j {
   244  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
   245  		}
   246  		j = delta
   247  	}
   248  	if x.before != magicptr || x.after != magicptr {
   249  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   250  	}
   251  }
   252  
   253  var global [1024]byte
   254  
   255  func testPointers() []unsafe.Pointer {
   256  	var pointers []unsafe.Pointer
   257  	// globals
   258  	for i := 0; i < 10; i++ {
   259  		pointers = append(pointers, unsafe.Pointer(&global[1<<i-1]))
   260  	}
   261  	// heap
   262  	pointers = append(pointers, unsafe.Pointer(new(byte)))
   263  	// nil
   264  	pointers = append(pointers, nil)
   265  	return pointers
   266  }
   267  
   268  func TestSwapPointer(t *testing.T) {
   269  	var x struct {
   270  		before uintptr
   271  		i      unsafe.Pointer
   272  		after  uintptr
   273  	}
   274  	var m uint64 = magic64
   275  	magicptr := uintptr(m)
   276  	x.before = magicptr
   277  	x.after = magicptr
   278  	var j unsafe.Pointer
   279  
   280  	for _, p := range testPointers() {
   281  		k := SwapPointer(&x.i, p)
   282  		if x.i != p || k != j {
   283  			t.Fatalf("p=%p i=%p j=%p k=%p", p, x.i, j, k)
   284  		}
   285  		j = p
   286  	}
   287  	if x.before != magicptr || x.after != magicptr {
   288  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   289  	}
   290  }
   291  
   292  func TestSwapPointerMethod(t *testing.T) {
   293  	var x struct {
   294  		before uintptr
   295  		i      Pointer[byte]
   296  		after  uintptr
   297  	}
   298  	var m uint64 = magic64
   299  	magicptr := uintptr(m)
   300  	x.before = magicptr
   301  	x.after = magicptr
   302  	var j *byte
   303  	for _, p := range testPointers() {
   304  		p := (*byte)(p)
   305  		k := x.i.Swap(p)
   306  		if x.i.Load() != p || k != j {
   307  			t.Fatalf("p=%p i=%p j=%p k=%p", p, x.i.Load(), j, k)
   308  		}
   309  		j = p
   310  	}
   311  	if x.before != magicptr || x.after != magicptr {
   312  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   313  	}
   314  }
   315  
   316  func TestAddInt32(t *testing.T) {
   317  	var x struct {
   318  		before int32
   319  		i      int32
   320  		after  int32
   321  	}
   322  	x.before = magic32
   323  	x.after = magic32
   324  	var j int32
   325  	for delta := int32(1); delta+delta > delta; delta += delta {
   326  		k := AddInt32(&x.i, delta)
   327  		j += delta
   328  		if x.i != j || k != j {
   329  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   330  		}
   331  	}
   332  	if x.before != magic32 || x.after != magic32 {
   333  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   334  	}
   335  }
   336  
   337  func TestAddInt32Method(t *testing.T) {
   338  	var x struct {
   339  		before int32
   340  		i      Int32
   341  		after  int32
   342  	}
   343  	x.before = magic32
   344  	x.after = magic32
   345  	var j int32
   346  	for delta := int32(1); delta+delta > delta; delta += delta {
   347  		k := x.i.Add(delta)
   348  		j += delta
   349  		if x.i.Load() != j || k != j {
   350  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
   351  		}
   352  	}
   353  	if x.before != magic32 || x.after != magic32 {
   354  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   355  	}
   356  }
   357  
   358  func TestAddUint32(t *testing.T) {
   359  	var x struct {
   360  		before uint32
   361  		i      uint32
   362  		after  uint32
   363  	}
   364  	x.before = magic32
   365  	x.after = magic32
   366  	var j uint32
   367  	for delta := uint32(1); delta+delta > delta; delta += delta {
   368  		k := AddUint32(&x.i, delta)
   369  		j += delta
   370  		if x.i != j || k != j {
   371  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   372  		}
   373  	}
   374  	if x.before != magic32 || x.after != magic32 {
   375  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   376  	}
   377  }
   378  
   379  func TestAddUint32Method(t *testing.T) {
   380  	var x struct {
   381  		before uint32
   382  		i      Uint32
   383  		after  uint32
   384  	}
   385  	x.before = magic32
   386  	x.after = magic32
   387  	var j uint32
   388  	for delta := uint32(1); delta+delta > delta; delta += delta {
   389  		k := x.i.Add(delta)
   390  		j += delta
   391  		if x.i.Load() != j || k != j {
   392  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
   393  		}
   394  	}
   395  	if x.before != magic32 || x.after != magic32 {
   396  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   397  	}
   398  }
   399  
   400  func TestAddInt64(t *testing.T) {
   401  	var x struct {
   402  		before int64
   403  		i      int64
   404  		after  int64
   405  	}
   406  	magic64 := int64(magic64)
   407  	x.before = magic64
   408  	x.after = magic64
   409  	var j int64
   410  	for delta := int64(1); delta+delta > delta; delta += delta {
   411  		k := AddInt64(&x.i, delta)
   412  		j += delta
   413  		if x.i != j || k != j {
   414  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   415  		}
   416  	}
   417  	if x.before != magic64 || x.after != magic64 {
   418  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   419  	}
   420  }
   421  
   422  func TestAddInt64Method(t *testing.T) {
   423  	var x struct {
   424  		before int64
   425  		i      Int64
   426  		after  int64
   427  	}
   428  	magic64 := int64(magic64)
   429  	x.before = magic64
   430  	x.after = magic64
   431  	var j int64
   432  	for delta := int64(1); delta+delta > delta; delta += delta {
   433  		k := x.i.Add(delta)
   434  		j += delta
   435  		if x.i.Load() != j || k != j {
   436  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
   437  		}
   438  	}
   439  	if x.before != magic64 || x.after != magic64 {
   440  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   441  	}
   442  }
   443  
   444  func TestAddUint64(t *testing.T) {
   445  	var x struct {
   446  		before uint64
   447  		i      uint64
   448  		after  uint64
   449  	}
   450  	magic64 := uint64(magic64)
   451  	x.before = magic64
   452  	x.after = magic64
   453  	var j uint64
   454  	for delta := uint64(1); delta+delta > delta; delta += delta {
   455  		k := AddUint64(&x.i, delta)
   456  		j += delta
   457  		if x.i != j || k != j {
   458  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   459  		}
   460  	}
   461  	if x.before != magic64 || x.after != magic64 {
   462  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   463  	}
   464  }
   465  
   466  func TestAddUint64Method(t *testing.T) {
   467  	var x struct {
   468  		before uint64
   469  		i      Uint64
   470  		after  uint64
   471  	}
   472  	magic64 := uint64(magic64)
   473  	x.before = magic64
   474  	x.after = magic64
   475  	var j uint64
   476  	for delta := uint64(1); delta+delta > delta; delta += delta {
   477  		k := x.i.Add(delta)
   478  		j += delta
   479  		if x.i.Load() != j || k != j {
   480  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
   481  		}
   482  	}
   483  	if x.before != magic64 || x.after != magic64 {
   484  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   485  	}
   486  }
   487  
   488  func TestAddUintptr(t *testing.T) {
   489  	var x struct {
   490  		before uintptr
   491  		i      uintptr
   492  		after  uintptr
   493  	}
   494  	var m uint64 = magic64
   495  	magicptr := uintptr(m)
   496  	x.before = magicptr
   497  	x.after = magicptr
   498  	var j uintptr
   499  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   500  		k := AddUintptr(&x.i, delta)
   501  		j += delta
   502  		if x.i != j || k != j {
   503  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   504  		}
   505  	}
   506  	if x.before != magicptr || x.after != magicptr {
   507  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   508  	}
   509  }
   510  
   511  func TestAddUintptrMethod(t *testing.T) {
   512  	var x struct {
   513  		before uintptr
   514  		i      Uintptr
   515  		after  uintptr
   516  	}
   517  	var m uint64 = magic64
   518  	magicptr := uintptr(m)
   519  	x.before = magicptr
   520  	x.after = magicptr
   521  	var j uintptr
   522  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   523  		k := x.i.Add(delta)
   524  		j += delta
   525  		if x.i.Load() != j || k != j {
   526  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
   527  		}
   528  	}
   529  	if x.before != magicptr || x.after != magicptr {
   530  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   531  	}
   532  }
   533  
   534  func TestCompareAndSwapInt32(t *testing.T) {
   535  	var x struct {
   536  		before int32
   537  		i      int32
   538  		after  int32
   539  	}
   540  	x.before = magic32
   541  	x.after = magic32
   542  	for val := int32(1); val+val > val; val += val {
   543  		x.i = val
   544  		if !CompareAndSwapInt32(&x.i, val, val+1) {
   545  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   546  		}
   547  		if x.i != val+1 {
   548  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   549  		}
   550  		x.i = val + 1
   551  		if CompareAndSwapInt32(&x.i, val, val+2) {
   552  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   553  		}
   554  		if x.i != val+1 {
   555  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   556  		}
   557  	}
   558  	if x.before != magic32 || x.after != magic32 {
   559  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   560  	}
   561  }
   562  
   563  func TestCompareAndSwapInt32Method(t *testing.T) {
   564  	var x struct {
   565  		before int32
   566  		i      Int32
   567  		after  int32
   568  	}
   569  	x.before = magic32
   570  	x.after = magic32
   571  	for val := int32(1); val+val > val; val += val {
   572  		x.i.Store(val)
   573  		if !x.i.CompareAndSwap(val, val+1) {
   574  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   575  		}
   576  		if x.i.Load() != val+1 {
   577  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
   578  		}
   579  		x.i.Store(val + 1)
   580  		if x.i.CompareAndSwap(val, val+2) {
   581  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   582  		}
   583  		if x.i.Load() != val+1 {
   584  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
   585  		}
   586  	}
   587  	if x.before != magic32 || x.after != magic32 {
   588  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   589  	}
   590  }
   591  
   592  func TestCompareAndSwapUint32(t *testing.T) {
   593  	var x struct {
   594  		before uint32
   595  		i      uint32
   596  		after  uint32
   597  	}
   598  	x.before = magic32
   599  	x.after = magic32
   600  	for val := uint32(1); val+val > val; val += val {
   601  		x.i = val
   602  		if !CompareAndSwapUint32(&x.i, val, val+1) {
   603  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   604  		}
   605  		if x.i != val+1 {
   606  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   607  		}
   608  		x.i = val + 1
   609  		if CompareAndSwapUint32(&x.i, val, val+2) {
   610  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   611  		}
   612  		if x.i != val+1 {
   613  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   614  		}
   615  	}
   616  	if x.before != magic32 || x.after != magic32 {
   617  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   618  	}
   619  }
   620  
   621  func TestCompareAndSwapUint32Method(t *testing.T) {
   622  	var x struct {
   623  		before uint32
   624  		i      Uint32
   625  		after  uint32
   626  	}
   627  	x.before = magic32
   628  	x.after = magic32
   629  	for val := uint32(1); val+val > val; val += val {
   630  		x.i.Store(val)
   631  		if !x.i.CompareAndSwap(val, val+1) {
   632  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   633  		}
   634  		if x.i.Load() != val+1 {
   635  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
   636  		}
   637  		x.i.Store(val + 1)
   638  		if x.i.CompareAndSwap(val, val+2) {
   639  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   640  		}
   641  		if x.i.Load() != val+1 {
   642  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
   643  		}
   644  	}
   645  	if x.before != magic32 || x.after != magic32 {
   646  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   647  	}
   648  }
   649  
   650  func TestCompareAndSwapInt64(t *testing.T) {
   651  	var x struct {
   652  		before int64
   653  		i      int64
   654  		after  int64
   655  	}
   656  	magic64 := int64(magic64)
   657  	x.before = magic64
   658  	x.after = magic64
   659  	for val := int64(1); val+val > val; val += val {
   660  		x.i = val
   661  		if !CompareAndSwapInt64(&x.i, val, val+1) {
   662  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   663  		}
   664  		if x.i != val+1 {
   665  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   666  		}
   667  		x.i = val + 1
   668  		if CompareAndSwapInt64(&x.i, val, val+2) {
   669  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   670  		}
   671  		if x.i != val+1 {
   672  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   673  		}
   674  	}
   675  	if x.before != magic64 || x.after != magic64 {
   676  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   677  	}
   678  }
   679  
   680  func TestCompareAndSwapInt64Method(t *testing.T) {
   681  	var x struct {
   682  		before int64
   683  		i      Int64
   684  		after  int64
   685  	}
   686  	magic64 := int64(magic64)
   687  	x.before = magic64
   688  	x.after = magic64
   689  	for val := int64(1); val+val > val; val += val {
   690  		x.i.Store(val)
   691  		if !x.i.CompareAndSwap(val, val+1) {
   692  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   693  		}
   694  		if x.i.Load() != val+1 {
   695  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
   696  		}
   697  		x.i.Store(val + 1)
   698  		if x.i.CompareAndSwap(val, val+2) {
   699  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   700  		}
   701  		if x.i.Load() != val+1 {
   702  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
   703  		}
   704  	}
   705  	if x.before != magic64 || x.after != magic64 {
   706  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   707  	}
   708  }
   709  
   710  func testCompareAndSwapUint64(t *testing.T, cas func(*uint64, uint64, uint64) bool) {
   711  	var x struct {
   712  		before uint64
   713  		i      uint64
   714  		after  uint64
   715  	}
   716  	magic64 := uint64(magic64)
   717  	x.before = magic64
   718  	x.after = magic64
   719  	for val := uint64(1); val+val > val; val += val {
   720  		x.i = val
   721  		if !cas(&x.i, val, val+1) {
   722  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   723  		}
   724  		if x.i != val+1 {
   725  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   726  		}
   727  		x.i = val + 1
   728  		if cas(&x.i, val, val+2) {
   729  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   730  		}
   731  		if x.i != val+1 {
   732  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   733  		}
   734  	}
   735  	if x.before != magic64 || x.after != magic64 {
   736  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   737  	}
   738  }
   739  
   740  func TestCompareAndSwapUint64(t *testing.T) {
   741  	testCompareAndSwapUint64(t, CompareAndSwapUint64)
   742  }
   743  
   744  func TestCompareAndSwapUint64Method(t *testing.T) {
   745  	var x struct {
   746  		before uint64
   747  		i      Uint64
   748  		after  uint64
   749  	}
   750  	magic64 := uint64(magic64)
   751  	x.before = magic64
   752  	x.after = magic64
   753  	for val := uint64(1); val+val > val; val += val {
   754  		x.i.Store(val)
   755  		if !x.i.CompareAndSwap(val, val+1) {
   756  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   757  		}
   758  		if x.i.Load() != val+1 {
   759  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
   760  		}
   761  		x.i.Store(val + 1)
   762  		if x.i.CompareAndSwap(val, val+2) {
   763  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   764  		}
   765  		if x.i.Load() != val+1 {
   766  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
   767  		}
   768  	}
   769  	if x.before != magic64 || x.after != magic64 {
   770  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
   771  	}
   772  }
   773  
   774  func TestCompareAndSwapUintptr(t *testing.T) {
   775  	var x struct {
   776  		before uintptr
   777  		i      uintptr
   778  		after  uintptr
   779  	}
   780  	var m uint64 = magic64
   781  	magicptr := uintptr(m)
   782  	x.before = magicptr
   783  	x.after = magicptr
   784  	for val := uintptr(1); val+val > val; val += val {
   785  		x.i = val
   786  		if !CompareAndSwapUintptr(&x.i, val, val+1) {
   787  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   788  		}
   789  		if x.i != val+1 {
   790  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   791  		}
   792  		x.i = val + 1
   793  		if CompareAndSwapUintptr(&x.i, val, val+2) {
   794  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   795  		}
   796  		if x.i != val+1 {
   797  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   798  		}
   799  	}
   800  	if x.before != magicptr || x.after != magicptr {
   801  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   802  	}
   803  }
   804  
   805  func TestCompareAndSwapUintptrMethod(t *testing.T) {
   806  	var x struct {
   807  		before uintptr
   808  		i      Uintptr
   809  		after  uintptr
   810  	}
   811  	var m uint64 = magic64
   812  	magicptr := uintptr(m)
   813  	x.before = magicptr
   814  	x.after = magicptr
   815  	for val := uintptr(1); val+val > val; val += val {
   816  		x.i.Store(val)
   817  		if !x.i.CompareAndSwap(val, val+1) {
   818  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   819  		}
   820  		if x.i.Load() != val+1 {
   821  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
   822  		}
   823  		x.i.Store(val + 1)
   824  		if x.i.CompareAndSwap(val, val+2) {
   825  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   826  		}
   827  		if x.i.Load() != val+1 {
   828  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
   829  		}
   830  	}
   831  	if x.before != magicptr || x.after != magicptr {
   832  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uintptr(magicptr), uintptr(magicptr))
   833  	}
   834  }
   835  
   836  func TestCompareAndSwapPointer(t *testing.T) {
   837  	var x struct {
   838  		before uintptr
   839  		i      unsafe.Pointer
   840  		after  uintptr
   841  	}
   842  	var m uint64 = magic64
   843  	magicptr := uintptr(m)
   844  	x.before = magicptr
   845  	x.after = magicptr
   846  	q := unsafe.Pointer(new(byte))
   847  	for _, p := range testPointers() {
   848  		x.i = p
   849  		if !CompareAndSwapPointer(&x.i, p, q) {
   850  			t.Fatalf("should have swapped %p %p", p, q)
   851  		}
   852  		if x.i != q {
   853  			t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q)
   854  		}
   855  		if CompareAndSwapPointer(&x.i, p, nil) {
   856  			t.Fatalf("should not have swapped %p nil", p)
   857  		}
   858  		if x.i != q {
   859  			t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q)
   860  		}
   861  	}
   862  	if x.before != magicptr || x.after != magicptr {
   863  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   864  	}
   865  }
   866  
   867  func TestCompareAndSwapPointerMethod(t *testing.T) {
   868  	var x struct {
   869  		before uintptr
   870  		i      Pointer[byte]
   871  		after  uintptr
   872  	}
   873  	var m uint64 = magic64
   874  	magicptr := uintptr(m)
   875  	x.before = magicptr
   876  	x.after = magicptr
   877  	q := new(byte)
   878  	for _, p := range testPointers() {
   879  		p := (*byte)(p)
   880  		x.i.Store(p)
   881  		if !x.i.CompareAndSwap(p, q) {
   882  			t.Fatalf("should have swapped %p %p", p, q)
   883  		}
   884  		if x.i.Load() != q {
   885  			t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q)
   886  		}
   887  		if x.i.CompareAndSwap(p, nil) {
   888  			t.Fatalf("should not have swapped %p nil", p)
   889  		}
   890  		if x.i.Load() != q {
   891  			t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q)
   892  		}
   893  	}
   894  	if x.before != magicptr || x.after != magicptr {
   895  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   896  	}
   897  }
   898  
   899  func TestLoadInt32(t *testing.T) {
   900  	var x struct {
   901  		before int32
   902  		i      int32
   903  		after  int32
   904  	}
   905  	x.before = magic32
   906  	x.after = magic32
   907  	for delta := int32(1); delta+delta > delta; delta += delta {
   908  		k := LoadInt32(&x.i)
   909  		if k != x.i {
   910  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   911  		}
   912  		x.i += delta
   913  	}
   914  	if x.before != magic32 || x.after != magic32 {
   915  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   916  	}
   917  }
   918  
   919  func TestLoadInt32Method(t *testing.T) {
   920  	var x struct {
   921  		before int32
   922  		i      Int32
   923  		after  int32
   924  	}
   925  	x.before = magic32
   926  	x.after = magic32
   927  	want := int32(0)
   928  	for delta := int32(1); delta+delta > delta; delta += delta {
   929  		k := x.i.Load()
   930  		if k != want {
   931  			t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
   932  		}
   933  		x.i.Store(k + delta)
   934  		want = k + delta
   935  	}
   936  	if x.before != magic32 || x.after != magic32 {
   937  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   938  	}
   939  }
   940  
   941  func TestLoadUint32(t *testing.T) {
   942  	var x struct {
   943  		before uint32
   944  		i      uint32
   945  		after  uint32
   946  	}
   947  	x.before = magic32
   948  	x.after = magic32
   949  	for delta := uint32(1); delta+delta > delta; delta += delta {
   950  		k := LoadUint32(&x.i)
   951  		if k != x.i {
   952  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   953  		}
   954  		x.i += delta
   955  	}
   956  	if x.before != magic32 || x.after != magic32 {
   957  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   958  	}
   959  }
   960  
   961  func TestLoadUint32Method(t *testing.T) {
   962  	var x struct {
   963  		before uint32
   964  		i      Uint32
   965  		after  uint32
   966  	}
   967  	x.before = magic32
   968  	x.after = magic32
   969  	want := uint32(0)
   970  	for delta := uint32(1); delta+delta > delta; delta += delta {
   971  		k := x.i.Load()
   972  		if k != want {
   973  			t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
   974  		}
   975  		x.i.Store(k + delta)
   976  		want = k + delta
   977  	}
   978  	if x.before != magic32 || x.after != magic32 {
   979  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   980  	}
   981  }
   982  
   983  func TestLoadInt64(t *testing.T) {
   984  	var x struct {
   985  		before int64
   986  		i      int64
   987  		after  int64
   988  	}
   989  	magic64 := int64(magic64)
   990  	x.before = magic64
   991  	x.after = magic64
   992  	for delta := int64(1); delta+delta > delta; delta += delta {
   993  		k := LoadInt64(&x.i)
   994  		if k != x.i {
   995  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   996  		}
   997  		x.i += delta
   998  	}
   999  	if x.before != magic64 || x.after != magic64 {
  1000  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
  1001  	}
  1002  }
  1003  
  1004  func TestLoadInt64Method(t *testing.T) {
  1005  	var x struct {
  1006  		before int64
  1007  		i      Int64
  1008  		after  int64
  1009  	}
  1010  	magic64 := int64(magic64)
  1011  	x.before = magic64
  1012  	x.after = magic64
  1013  	want := int64(0)
  1014  	for delta := int64(1); delta+delta > delta; delta += delta {
  1015  		k := x.i.Load()
  1016  		if k != want {
  1017  			t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
  1018  		}
  1019  		x.i.Store(k + delta)
  1020  		want = k + delta
  1021  	}
  1022  	if x.before != magic64 || x.after != magic64 {
  1023  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
  1024  	}
  1025  }
  1026  
  1027  func TestLoadUint64(t *testing.T) {
  1028  	var x struct {
  1029  		before uint64
  1030  		i      uint64
  1031  		after  uint64
  1032  	}
  1033  	magic64 := uint64(magic64)
  1034  	x.before = magic64
  1035  	x.after = magic64
  1036  	for delta := uint64(1); delta+delta > delta; delta += delta {
  1037  		k := LoadUint64(&x.i)
  1038  		if k != x.i {
  1039  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
  1040  		}
  1041  		x.i += delta
  1042  	}
  1043  	if x.before != magic64 || x.after != magic64 {
  1044  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
  1045  	}
  1046  }
  1047  
  1048  func TestLoadUint64Method(t *testing.T) {
  1049  	var x struct {
  1050  		before uint64
  1051  		i      Uint64
  1052  		after  uint64
  1053  	}
  1054  	magic64 := uint64(magic64)
  1055  	x.before = magic64
  1056  	x.after = magic64
  1057  	want := uint64(0)
  1058  	for delta := uint64(1); delta+delta > delta; delta += delta {
  1059  		k := x.i.Load()
  1060  		if k != want {
  1061  			t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
  1062  		}
  1063  		x.i.Store(k + delta)
  1064  		want = k + delta
  1065  	}
  1066  	if x.before != magic64 || x.after != magic64 {
  1067  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
  1068  	}
  1069  }
  1070  
  1071  func TestLoadUintptr(t *testing.T) {
  1072  	var x struct {
  1073  		before uintptr
  1074  		i      uintptr
  1075  		after  uintptr
  1076  	}
  1077  	var m uint64 = magic64
  1078  	magicptr := uintptr(m)
  1079  	x.before = magicptr
  1080  	x.after = magicptr
  1081  	for delta := uintptr(1); delta+delta > delta; delta += delta {
  1082  		k := LoadUintptr(&x.i)
  1083  		if k != x.i {
  1084  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
  1085  		}
  1086  		x.i += delta
  1087  	}
  1088  	if x.before != magicptr || x.after != magicptr {
  1089  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
  1090  	}
  1091  }
  1092  
  1093  func TestLoadUintptrMethod(t *testing.T) {
  1094  	var x struct {
  1095  		before uintptr
  1096  		i      Uintptr
  1097  		after  uintptr
  1098  	}
  1099  	var m uint64 = magic64
  1100  	magicptr := uintptr(m)
  1101  	x.before = magicptr
  1102  	x.after = magicptr
  1103  	want := uintptr(0)
  1104  	for delta := uintptr(1); delta+delta > delta; delta += delta {
  1105  		k := x.i.Load()
  1106  		if k != want {
  1107  			t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
  1108  		}
  1109  		x.i.Store(k + delta)
  1110  		want = k + delta
  1111  	}
  1112  	if x.before != magicptr || x.after != magicptr {
  1113  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
  1114  	}
  1115  }
  1116  
  1117  func TestLoadPointer(t *testing.T) {
  1118  	var x struct {
  1119  		before uintptr
  1120  		i      unsafe.Pointer
  1121  		after  uintptr
  1122  	}
  1123  	var m uint64 = magic64
  1124  	magicptr := uintptr(m)
  1125  	x.before = magicptr
  1126  	x.after = magicptr
  1127  	for _, p := range testPointers() {
  1128  		x.i = p
  1129  		k := LoadPointer(&x.i)
  1130  		if k != p {
  1131  			t.Fatalf("p=%x k=%x", p, k)
  1132  		}
  1133  	}
  1134  	if x.before != magicptr || x.after != magicptr {
  1135  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
  1136  	}
  1137  }
  1138  
  1139  func TestLoadPointerMethod(t *testing.T) {
  1140  	var x struct {
  1141  		before uintptr
  1142  		i      Pointer[byte]
  1143  		after  uintptr
  1144  	}
  1145  	var m uint64 = magic64
  1146  	magicptr := uintptr(m)
  1147  	x.before = magicptr
  1148  	x.after = magicptr
  1149  	for _, p := range testPointers() {
  1150  		p := (*byte)(p)
  1151  		x.i.Store(p)
  1152  		k := x.i.Load()
  1153  		if k != p {
  1154  			t.Fatalf("p=%x k=%x", p, k)
  1155  		}
  1156  	}
  1157  	if x.before != magicptr || x.after != magicptr {
  1158  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
  1159  	}
  1160  }
  1161  
  1162  func TestStoreInt32(t *testing.T) {
  1163  	var x struct {
  1164  		before int32
  1165  		i      int32
  1166  		after  int32
  1167  	}
  1168  	x.before = magic32
  1169  	x.after = magic32
  1170  	v := int32(0)
  1171  	for delta := int32(1); delta+delta > delta; delta += delta {
  1172  		StoreInt32(&x.i, v)
  1173  		if x.i != v {
  1174  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
  1175  		}
  1176  		v += delta
  1177  	}
  1178  	if x.before != magic32 || x.after != magic32 {
  1179  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
  1180  	}
  1181  }
  1182  
  1183  func TestStoreInt32Method(t *testing.T) {
  1184  	var x struct {
  1185  		before int32
  1186  		i      Int32
  1187  		after  int32
  1188  	}
  1189  	x.before = magic32
  1190  	x.after = magic32
  1191  	v := int32(0)
  1192  	for delta := int32(1); delta+delta > delta; delta += delta {
  1193  		x.i.Store(v)
  1194  		if x.i.Load() != v {
  1195  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
  1196  		}
  1197  		v += delta
  1198  	}
  1199  	if x.before != magic32 || x.after != magic32 {
  1200  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
  1201  	}
  1202  }
  1203  
  1204  func TestStoreUint32(t *testing.T) {
  1205  	var x struct {
  1206  		before uint32
  1207  		i      uint32
  1208  		after  uint32
  1209  	}
  1210  	x.before = magic32
  1211  	x.after = magic32
  1212  	v := uint32(0)
  1213  	for delta := uint32(1); delta+delta > delta; delta += delta {
  1214  		StoreUint32(&x.i, v)
  1215  		if x.i != v {
  1216  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
  1217  		}
  1218  		v += delta
  1219  	}
  1220  	if x.before != magic32 || x.after != magic32 {
  1221  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
  1222  	}
  1223  }
  1224  
  1225  func TestStoreUint32Method(t *testing.T) {
  1226  	var x struct {
  1227  		before uint32
  1228  		i      Uint32
  1229  		after  uint32
  1230  	}
  1231  	x.before = magic32
  1232  	x.after = magic32
  1233  	v := uint32(0)
  1234  	for delta := uint32(1); delta+delta > delta; delta += delta {
  1235  		x.i.Store(v)
  1236  		if x.i.Load() != v {
  1237  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
  1238  		}
  1239  		v += delta
  1240  	}
  1241  	if x.before != magic32 || x.after != magic32 {
  1242  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
  1243  	}
  1244  }
  1245  
  1246  func TestStoreInt64(t *testing.T) {
  1247  	var x struct {
  1248  		before int64
  1249  		i      int64
  1250  		after  int64
  1251  	}
  1252  	magic64 := int64(magic64)
  1253  	x.before = magic64
  1254  	x.after = magic64
  1255  	v := int64(0)
  1256  	for delta := int64(1); delta+delta > delta; delta += delta {
  1257  		StoreInt64(&x.i, v)
  1258  		if x.i != v {
  1259  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
  1260  		}
  1261  		v += delta
  1262  	}
  1263  	if x.before != magic64 || x.after != magic64 {
  1264  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
  1265  	}
  1266  }
  1267  
  1268  func TestStoreInt64Method(t *testing.T) {
  1269  	var x struct {
  1270  		before int64
  1271  		i      Int64
  1272  		after  int64
  1273  	}
  1274  	magic64 := int64(magic64)
  1275  	x.before = magic64
  1276  	x.after = magic64
  1277  	v := int64(0)
  1278  	for delta := int64(1); delta+delta > delta; delta += delta {
  1279  		x.i.Store(v)
  1280  		if x.i.Load() != v {
  1281  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
  1282  		}
  1283  		v += delta
  1284  	}
  1285  	if x.before != magic64 || x.after != magic64 {
  1286  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
  1287  	}
  1288  }
  1289  
  1290  func TestStoreUint64(t *testing.T) {
  1291  	var x struct {
  1292  		before uint64
  1293  		i      uint64
  1294  		after  uint64
  1295  	}
  1296  	magic64 := uint64(magic64)
  1297  	x.before = magic64
  1298  	x.after = magic64
  1299  	v := uint64(0)
  1300  	for delta := uint64(1); delta+delta > delta; delta += delta {
  1301  		StoreUint64(&x.i, v)
  1302  		if x.i != v {
  1303  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
  1304  		}
  1305  		v += delta
  1306  	}
  1307  	if x.before != magic64 || x.after != magic64 {
  1308  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
  1309  	}
  1310  }
  1311  
  1312  func TestStoreUint64Method(t *testing.T) {
  1313  	var x struct {
  1314  		before uint64
  1315  		i      Uint64
  1316  		after  uint64
  1317  	}
  1318  	magic64 := uint64(magic64)
  1319  	x.before = magic64
  1320  	x.after = magic64
  1321  	v := uint64(0)
  1322  	for delta := uint64(1); delta+delta > delta; delta += delta {
  1323  		x.i.Store(v)
  1324  		if x.i.Load() != v {
  1325  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
  1326  		}
  1327  		v += delta
  1328  	}
  1329  	if x.before != magic64 || x.after != magic64 {
  1330  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
  1331  	}
  1332  }
  1333  
  1334  func TestStoreUintptr(t *testing.T) {
  1335  	var x struct {
  1336  		before uintptr
  1337  		i      uintptr
  1338  		after  uintptr
  1339  	}
  1340  	var m uint64 = magic64
  1341  	magicptr := uintptr(m)
  1342  	x.before = magicptr
  1343  	x.after = magicptr
  1344  	v := uintptr(0)
  1345  	for delta := uintptr(1); delta+delta > delta; delta += delta {
  1346  		StoreUintptr(&x.i, v)
  1347  		if x.i != v {
  1348  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
  1349  		}
  1350  		v += delta
  1351  	}
  1352  	if x.before != magicptr || x.after != magicptr {
  1353  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
  1354  	}
  1355  }
  1356  
  1357  func TestStoreUintptrMethod(t *testing.T) {
  1358  	var x struct {
  1359  		before uintptr
  1360  		i      Uintptr
  1361  		after  uintptr
  1362  	}
  1363  	var m uint64 = magic64
  1364  	magicptr := uintptr(m)
  1365  	x.before = magicptr
  1366  	x.after = magicptr
  1367  	v := uintptr(0)
  1368  	for delta := uintptr(1); delta+delta > delta; delta += delta {
  1369  		x.i.Store(v)
  1370  		if x.i.Load() != v {
  1371  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
  1372  		}
  1373  		v += delta
  1374  	}
  1375  	if x.before != magicptr || x.after != magicptr {
  1376  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
  1377  	}
  1378  }
  1379  
  1380  func TestStorePointer(t *testing.T) {
  1381  	var x struct {
  1382  		before uintptr
  1383  		i      unsafe.Pointer
  1384  		after  uintptr
  1385  	}
  1386  	var m uint64 = magic64
  1387  	magicptr := uintptr(m)
  1388  	x.before = magicptr
  1389  	x.after = magicptr
  1390  	for _, p := range testPointers() {
  1391  		StorePointer(&x.i, p)
  1392  		if x.i != p {
  1393  			t.Fatalf("x.i=%p p=%p", x.i, p)
  1394  		}
  1395  	}
  1396  	if x.before != magicptr || x.after != magicptr {
  1397  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
  1398  	}
  1399  }
  1400  
  1401  func TestStorePointerMethod(t *testing.T) {
  1402  	var x struct {
  1403  		before uintptr
  1404  		i      Pointer[byte]
  1405  		after  uintptr
  1406  	}
  1407  	var m uint64 = magic64
  1408  	magicptr := uintptr(m)
  1409  	x.before = magicptr
  1410  	x.after = magicptr
  1411  	for _, p := range testPointers() {
  1412  		p := (*byte)(p)
  1413  		x.i.Store(p)
  1414  		if x.i.Load() != p {
  1415  			t.Fatalf("x.i=%p p=%p", x.i.Load(), p)
  1416  		}
  1417  	}
  1418  	if x.before != magicptr || x.after != magicptr {
  1419  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
  1420  	}
  1421  }
  1422  
  1423  // Tests of correct behavior, with contention.
  1424  // (Is the function atomic?)
  1425  //
  1426  // For each function, we write a "hammer" function that repeatedly
  1427  // uses the atomic operation to add 1 to a value. After running
  1428  // multiple hammers in parallel, check that we end with the correct
  1429  // total.
  1430  // Swap can't add 1, so it uses a different scheme.
  1431  // The functions repeatedly generate a pseudo-random number such that
  1432  // low bits are equal to high bits, swap, check that the old value
  1433  // has low and high bits equal.
  1434  
  1435  var hammer32 = map[string]func(*uint32, int){
  1436  	"SwapInt32":             hammerSwapInt32,
  1437  	"SwapUint32":            hammerSwapUint32,
  1438  	"SwapUintptr":           hammerSwapUintptr32,
  1439  	"AddInt32":              hammerAddInt32,
  1440  	"AddUint32":             hammerAddUint32,
  1441  	"AddUintptr":            hammerAddUintptr32,
  1442  	"CompareAndSwapInt32":   hammerCompareAndSwapInt32,
  1443  	"CompareAndSwapUint32":  hammerCompareAndSwapUint32,
  1444  	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr32,
  1445  
  1446  	"SwapInt32Method":             hammerSwapInt32Method,
  1447  	"SwapUint32Method":            hammerSwapUint32Method,
  1448  	"SwapUintptrMethod":           hammerSwapUintptr32Method,
  1449  	"AddInt32Method":              hammerAddInt32Method,
  1450  	"AddUint32Method":             hammerAddUint32Method,
  1451  	"AddUintptrMethod":            hammerAddUintptr32Method,
  1452  	"CompareAndSwapInt32Method":   hammerCompareAndSwapInt32Method,
  1453  	"CompareAndSwapUint32Method":  hammerCompareAndSwapUint32Method,
  1454  	"CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr32Method,
  1455  }
  1456  
  1457  func init() {
  1458  	var v uint64 = 1 << 50
  1459  	if uintptr(v) != 0 {
  1460  		// 64-bit system; clear uintptr tests
  1461  		delete(hammer32, "SwapUintptr")
  1462  		delete(hammer32, "AddUintptr")
  1463  		delete(hammer32, "CompareAndSwapUintptr")
  1464  		delete(hammer32, "SwapUintptrMethod")
  1465  		delete(hammer32, "AddUintptrMethod")
  1466  		delete(hammer32, "CompareAndSwapUintptrMethod")
  1467  	}
  1468  }
  1469  
  1470  func hammerSwapInt32(uaddr *uint32, count int) {
  1471  	addr := (*int32)(unsafe.Pointer(uaddr))
  1472  	seed := int(uintptr(unsafe.Pointer(&count)))
  1473  	for i := 0; i < count; i++ {
  1474  		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
  1475  		old := uint32(SwapInt32(addr, int32(new)))
  1476  		if old>>16 != old<<16>>16 {
  1477  			panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
  1478  		}
  1479  	}
  1480  }
  1481  
  1482  func hammerSwapInt32Method(uaddr *uint32, count int) {
  1483  	addr := (*Int32)(unsafe.Pointer(uaddr))
  1484  	seed := int(uintptr(unsafe.Pointer(&count)))
  1485  	for i := 0; i < count; i++ {
  1486  		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
  1487  		old := uint32(addr.Swap(int32(new)))
  1488  		if old>>16 != old<<16>>16 {
  1489  			panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
  1490  		}
  1491  	}
  1492  }
  1493  
  1494  func hammerSwapUint32(addr *uint32, count int) {
  1495  	seed := int(uintptr(unsafe.Pointer(&count)))
  1496  	for i := 0; i < count; i++ {
  1497  		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
  1498  		old := SwapUint32(addr, new)
  1499  		if old>>16 != old<<16>>16 {
  1500  			panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
  1501  		}
  1502  	}
  1503  }
  1504  
  1505  func hammerSwapUint32Method(uaddr *uint32, count int) {
  1506  	addr := (*Uint32)(unsafe.Pointer(uaddr))
  1507  	seed := int(uintptr(unsafe.Pointer(&count)))
  1508  	for i := 0; i < count; i++ {
  1509  		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
  1510  		old := addr.Swap(new)
  1511  		if old>>16 != old<<16>>16 {
  1512  			panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
  1513  		}
  1514  	}
  1515  }
  1516  
  1517  func hammerSwapUintptr32(uaddr *uint32, count int) {
  1518  	// only safe when uintptr is 32-bit.
  1519  	// not called on 64-bit systems.
  1520  	addr := (*uintptr)(unsafe.Pointer(uaddr))
  1521  	seed := int(uintptr(unsafe.Pointer(&count)))
  1522  	for i := 0; i < count; i++ {
  1523  		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
  1524  		old := SwapUintptr(addr, new)
  1525  		if old>>16 != old<<16>>16 {
  1526  			panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old))
  1527  		}
  1528  	}
  1529  }
  1530  
  1531  func hammerSwapUintptr32Method(uaddr *uint32, count int) {
  1532  	// only safe when uintptr is 32-bit.
  1533  	// not called on 64-bit systems.
  1534  	addr := (*Uintptr)(unsafe.Pointer(uaddr))
  1535  	seed := int(uintptr(unsafe.Pointer(&count)))
  1536  	for i := 0; i < count; i++ {
  1537  		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
  1538  		old := addr.Swap(new)
  1539  		if old>>16 != old<<16>>16 {
  1540  			panic(fmt.Sprintf("Uintptr.Swap is not atomic: %#08x", old))
  1541  		}
  1542  	}
  1543  }
  1544  
  1545  func hammerAddInt32(uaddr *uint32, count int) {
  1546  	addr := (*int32)(unsafe.Pointer(uaddr))
  1547  	for i := 0; i < count; i++ {
  1548  		AddInt32(addr, 1)
  1549  	}
  1550  }
  1551  
  1552  func hammerAddInt32Method(uaddr *uint32, count int) {
  1553  	addr := (*Int32)(unsafe.Pointer(uaddr))
  1554  	for i := 0; i < count; i++ {
  1555  		addr.Add(1)
  1556  	}
  1557  }
  1558  
  1559  func hammerAddUint32(addr *uint32, count int) {
  1560  	for i := 0; i < count; i++ {
  1561  		AddUint32(addr, 1)
  1562  	}
  1563  }
  1564  
  1565  func hammerAddUint32Method(uaddr *uint32, count int) {
  1566  	addr := (*Uint32)(unsafe.Pointer(uaddr))
  1567  	for i := 0; i < count; i++ {
  1568  		addr.Add(1)
  1569  	}
  1570  }
  1571  
  1572  func hammerAddUintptr32(uaddr *uint32, count int) {
  1573  	// only safe when uintptr is 32-bit.
  1574  	// not called on 64-bit systems.
  1575  	addr := (*uintptr)(unsafe.Pointer(uaddr))
  1576  	for i := 0; i < count; i++ {
  1577  		AddUintptr(addr, 1)
  1578  	}
  1579  }
  1580  
  1581  func hammerAddUintptr32Method(uaddr *uint32, count int) {
  1582  	// only safe when uintptr is 32-bit.
  1583  	// not called on 64-bit systems.
  1584  	addr := (*Uintptr)(unsafe.Pointer(uaddr))
  1585  	for i := 0; i < count; i++ {
  1586  		addr.Add(1)
  1587  	}
  1588  }
  1589  
  1590  func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
  1591  	addr := (*int32)(unsafe.Pointer(uaddr))
  1592  	for i := 0; i < count; i++ {
  1593  		for {
  1594  			v := LoadInt32(addr)
  1595  			if CompareAndSwapInt32(addr, v, v+1) {
  1596  				break
  1597  			}
  1598  		}
  1599  	}
  1600  }
  1601  
  1602  func hammerCompareAndSwapInt32Method(uaddr *uint32, count int) {
  1603  	addr := (*Int32)(unsafe.Pointer(uaddr))
  1604  	for i := 0; i < count; i++ {
  1605  		for {
  1606  			v := addr.Load()
  1607  			if addr.CompareAndSwap(v, v+1) {
  1608  				break
  1609  			}
  1610  		}
  1611  	}
  1612  }
  1613  
  1614  func hammerCompareAndSwapUint32(addr *uint32, count int) {
  1615  	for i := 0; i < count; i++ {
  1616  		for {
  1617  			v := LoadUint32(addr)
  1618  			if CompareAndSwapUint32(addr, v, v+1) {
  1619  				break
  1620  			}
  1621  		}
  1622  	}
  1623  }
  1624  
  1625  func hammerCompareAndSwapUint32Method(uaddr *uint32, count int) {
  1626  	addr := (*Uint32)(unsafe.Pointer(uaddr))
  1627  	for i := 0; i < count; i++ {
  1628  		for {
  1629  			v := addr.Load()
  1630  			if addr.CompareAndSwap(v, v+1) {
  1631  				break
  1632  			}
  1633  		}
  1634  	}
  1635  }
  1636  
  1637  func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
  1638  	// only safe when uintptr is 32-bit.
  1639  	// not called on 64-bit systems.
  1640  	addr := (*uintptr)(unsafe.Pointer(uaddr))
  1641  	for i := 0; i < count; i++ {
  1642  		for {
  1643  			v := LoadUintptr(addr)
  1644  			if CompareAndSwapUintptr(addr, v, v+1) {
  1645  				break
  1646  			}
  1647  		}
  1648  	}
  1649  }
  1650  
  1651  func hammerCompareAndSwapUintptr32Method(uaddr *uint32, count int) {
  1652  	// only safe when uintptr is 32-bit.
  1653  	// not called on 64-bit systems.
  1654  	addr := (*Uintptr)(unsafe.Pointer(uaddr))
  1655  	for i := 0; i < count; i++ {
  1656  		for {
  1657  			v := addr.Load()
  1658  			if addr.CompareAndSwap(v, v+1) {
  1659  				break
  1660  			}
  1661  		}
  1662  	}
  1663  }
  1664  
  1665  func TestHammer32(t *testing.T) {
  1666  	const p = 4
  1667  	n := 100000
  1668  	if testing.Short() {
  1669  		n = 1000
  1670  	}
  1671  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
  1672  
  1673  	for name, testf := range hammer32 {
  1674  		c := make(chan int)
  1675  		var val uint32
  1676  		for i := 0; i < p; i++ {
  1677  			go func() {
  1678  				defer func() {
  1679  					if err := recover(); err != nil {
  1680  						t.Error(err.(string))
  1681  					}
  1682  					c <- 1
  1683  				}()
  1684  				testf(&val, n)
  1685  			}()
  1686  		}
  1687  		for i := 0; i < p; i++ {
  1688  			<-c
  1689  		}
  1690  		if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p {
  1691  			t.Fatalf("%s: val=%d want %d", name, val, n*p)
  1692  		}
  1693  	}
  1694  }
  1695  
  1696  var hammer64 = map[string]func(*uint64, int){
  1697  	"SwapInt64":             hammerSwapInt64,
  1698  	"SwapUint64":            hammerSwapUint64,
  1699  	"SwapUintptr":           hammerSwapUintptr64,
  1700  	"AddInt64":              hammerAddInt64,
  1701  	"AddUint64":             hammerAddUint64,
  1702  	"AddUintptr":            hammerAddUintptr64,
  1703  	"CompareAndSwapInt64":   hammerCompareAndSwapInt64,
  1704  	"CompareAndSwapUint64":  hammerCompareAndSwapUint64,
  1705  	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr64,
  1706  
  1707  	"SwapInt64Method":             hammerSwapInt64Method,
  1708  	"SwapUint64Method":            hammerSwapUint64Method,
  1709  	"SwapUintptrMethod":           hammerSwapUintptr64Method,
  1710  	"AddInt64Method":              hammerAddInt64Method,
  1711  	"AddUint64Method":             hammerAddUint64Method,
  1712  	"AddUintptrMethod":            hammerAddUintptr64Method,
  1713  	"CompareAndSwapInt64Method":   hammerCompareAndSwapInt64Method,
  1714  	"CompareAndSwapUint64Method":  hammerCompareAndSwapUint64Method,
  1715  	"CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr64Method,
  1716  }
  1717  
  1718  func init() {
  1719  	var v uint64 = 1 << 50
  1720  	if uintptr(v) == 0 {
  1721  		// 32-bit system; clear uintptr tests
  1722  		delete(hammer64, "SwapUintptr")
  1723  		delete(hammer64, "SwapUintptrMethod")
  1724  		delete(hammer64, "AddUintptr")
  1725  		delete(hammer64, "AddUintptrMethod")
  1726  		delete(hammer64, "CompareAndSwapUintptr")
  1727  		delete(hammer64, "CompareAndSwapUintptrMethod")
  1728  	}
  1729  }
  1730  
  1731  func hammerSwapInt64(uaddr *uint64, count int) {
  1732  	addr := (*int64)(unsafe.Pointer(uaddr))
  1733  	seed := int(uintptr(unsafe.Pointer(&count)))
  1734  	for i := 0; i < count; i++ {
  1735  		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
  1736  		old := uint64(SwapInt64(addr, int64(new)))
  1737  		if old>>32 != old<<32>>32 {
  1738  			panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
  1739  		}
  1740  	}
  1741  }
  1742  
  1743  func hammerSwapInt64Method(uaddr *uint64, count int) {
  1744  	addr := (*Int64)(unsafe.Pointer(uaddr))
  1745  	seed := int(uintptr(unsafe.Pointer(&count)))
  1746  	for i := 0; i < count; i++ {
  1747  		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
  1748  		old := uint64(addr.Swap(int64(new)))
  1749  		if old>>32 != old<<32>>32 {
  1750  			panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
  1751  		}
  1752  	}
  1753  }
  1754  
  1755  func hammerSwapUint64(addr *uint64, count int) {
  1756  	seed := int(uintptr(unsafe.Pointer(&count)))
  1757  	for i := 0; i < count; i++ {
  1758  		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
  1759  		old := SwapUint64(addr, new)
  1760  		if old>>32 != old<<32>>32 {
  1761  			panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
  1762  		}
  1763  	}
  1764  }
  1765  
  1766  func hammerSwapUint64Method(uaddr *uint64, count int) {
  1767  	addr := (*Uint64)(unsafe.Pointer(uaddr))
  1768  	seed := int(uintptr(unsafe.Pointer(&count)))
  1769  	for i := 0; i < count; i++ {
  1770  		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
  1771  		old := addr.Swap(new)
  1772  		if old>>32 != old<<32>>32 {
  1773  			panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
  1774  		}
  1775  	}
  1776  }
  1777  
  1778  const arch32 = unsafe.Sizeof(uintptr(0)) == 4
  1779  
  1780  func hammerSwapUintptr64(uaddr *uint64, count int) {
  1781  	// only safe when uintptr is 64-bit.
  1782  	// not called on 32-bit systems.
  1783  	if !arch32 {
  1784  		addr := (*uintptr)(unsafe.Pointer(uaddr))
  1785  		seed := int(uintptr(unsafe.Pointer(&count)))
  1786  		for i := 0; i < count; i++ {
  1787  			new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
  1788  			old := SwapUintptr(addr, new)
  1789  			if old>>32 != old<<32>>32 {
  1790  				panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
  1791  			}
  1792  		}
  1793  	}
  1794  }
  1795  
  1796  func hammerSwapUintptr64Method(uaddr *uint64, count int) {
  1797  	// only safe when uintptr is 64-bit.
  1798  	// not called on 32-bit systems.
  1799  	if !arch32 {
  1800  		addr := (*Uintptr)(unsafe.Pointer(uaddr))
  1801  		seed := int(uintptr(unsafe.Pointer(&count)))
  1802  		for i := 0; i < count; i++ {
  1803  			new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
  1804  			old := addr.Swap(new)
  1805  			if old>>32 != old<<32>>32 {
  1806  				panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
  1807  			}
  1808  		}
  1809  	}
  1810  }
  1811  
  1812  func hammerAddInt64(uaddr *uint64, count int) {
  1813  	addr := (*int64)(unsafe.Pointer(uaddr))
  1814  	for i := 0; i < count; i++ {
  1815  		AddInt64(addr, 1)
  1816  	}
  1817  }
  1818  
  1819  func hammerAddInt64Method(uaddr *uint64, count int) {
  1820  	addr := (*Int64)(unsafe.Pointer(uaddr))
  1821  	for i := 0; i < count; i++ {
  1822  		addr.Add(1)
  1823  	}
  1824  }
  1825  
  1826  func hammerAddUint64(addr *uint64, count int) {
  1827  	for i := 0; i < count; i++ {
  1828  		AddUint64(addr, 1)
  1829  	}
  1830  }
  1831  
  1832  func hammerAddUint64Method(uaddr *uint64, count int) {
  1833  	addr := (*Uint64)(unsafe.Pointer(uaddr))
  1834  	for i := 0; i < count; i++ {
  1835  		addr.Add(1)
  1836  	}
  1837  }
  1838  
  1839  func hammerAddUintptr64(uaddr *uint64, count int) {
  1840  	// only safe when uintptr is 64-bit.
  1841  	// not called on 32-bit systems.
  1842  	addr := (*uintptr)(unsafe.Pointer(uaddr))
  1843  	for i := 0; i < count; i++ {
  1844  		AddUintptr(addr, 1)
  1845  	}
  1846  }
  1847  
  1848  func hammerAddUintptr64Method(uaddr *uint64, count int) {
  1849  	// only safe when uintptr is 64-bit.
  1850  	// not called on 32-bit systems.
  1851  	addr := (*Uintptr)(unsafe.Pointer(uaddr))
  1852  	for i := 0; i < count; i++ {
  1853  		addr.Add(1)
  1854  	}
  1855  }
  1856  
  1857  func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
  1858  	addr := (*int64)(unsafe.Pointer(uaddr))
  1859  	for i := 0; i < count; i++ {
  1860  		for {
  1861  			v := LoadInt64(addr)
  1862  			if CompareAndSwapInt64(addr, v, v+1) {
  1863  				break
  1864  			}
  1865  		}
  1866  	}
  1867  }
  1868  
  1869  func hammerCompareAndSwapInt64Method(uaddr *uint64, count int) {
  1870  	addr := (*Int64)(unsafe.Pointer(uaddr))
  1871  	for i := 0; i < count; i++ {
  1872  		for {
  1873  			v := addr.Load()
  1874  			if addr.CompareAndSwap(v, v+1) {
  1875  				break
  1876  			}
  1877  		}
  1878  	}
  1879  }
  1880  
  1881  func hammerCompareAndSwapUint64(addr *uint64, count int) {
  1882  	for i := 0; i < count; i++ {
  1883  		for {
  1884  			v := LoadUint64(addr)
  1885  			if CompareAndSwapUint64(addr, v, v+1) {
  1886  				break
  1887  			}
  1888  		}
  1889  	}
  1890  }
  1891  
  1892  func hammerCompareAndSwapUint64Method(uaddr *uint64, count int) {
  1893  	addr := (*Uint64)(unsafe.Pointer(uaddr))
  1894  	for i := 0; i < count; i++ {
  1895  		for {
  1896  			v := addr.Load()
  1897  			if addr.CompareAndSwap(v, v+1) {
  1898  				break
  1899  			}
  1900  		}
  1901  	}
  1902  }
  1903  
  1904  func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
  1905  	// only safe when uintptr is 64-bit.
  1906  	// not called on 32-bit systems.
  1907  	addr := (*uintptr)(unsafe.Pointer(uaddr))
  1908  	for i := 0; i < count; i++ {
  1909  		for {
  1910  			v := LoadUintptr(addr)
  1911  			if CompareAndSwapUintptr(addr, v, v+1) {
  1912  				break
  1913  			}
  1914  		}
  1915  	}
  1916  }
  1917  
  1918  func hammerCompareAndSwapUintptr64Method(uaddr *uint64, count int) {
  1919  	// only safe when uintptr is 64-bit.
  1920  	// not called on 32-bit systems.
  1921  	addr := (*Uintptr)(unsafe.Pointer(uaddr))
  1922  	for i := 0; i < count; i++ {
  1923  		for {
  1924  			v := addr.Load()
  1925  			if addr.CompareAndSwap(v, v+1) {
  1926  				break
  1927  			}
  1928  		}
  1929  	}
  1930  }
  1931  
  1932  func TestHammer64(t *testing.T) {
  1933  	const p = 4
  1934  	n := 100000
  1935  	if testing.Short() {
  1936  		n = 1000
  1937  	}
  1938  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
  1939  
  1940  	for name, testf := range hammer64 {
  1941  		c := make(chan int)
  1942  		var val uint64
  1943  		for i := 0; i < p; i++ {
  1944  			go func() {
  1945  				defer func() {
  1946  					if err := recover(); err != nil {
  1947  						t.Error(err.(string))
  1948  					}
  1949  					c <- 1
  1950  				}()
  1951  				testf(&val, n)
  1952  			}()
  1953  		}
  1954  		for i := 0; i < p; i++ {
  1955  			<-c
  1956  		}
  1957  		if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p {
  1958  			t.Fatalf("%s: val=%d want %d", name, val, n*p)
  1959  		}
  1960  	}
  1961  }
  1962  
  1963  func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
  1964  	addr := (*int32)(paddr)
  1965  	v := LoadInt32(addr)
  1966  	vlo := v & ((1 << 16) - 1)
  1967  	vhi := v >> 16
  1968  	if vlo != vhi {
  1969  		t.Fatalf("Int32: %#x != %#x", vlo, vhi)
  1970  	}
  1971  	new := v + 1 + 1<<16
  1972  	if vlo == 1e4 {
  1973  		new = 0
  1974  	}
  1975  	StoreInt32(addr, new)
  1976  }
  1977  
  1978  func hammerStoreLoadInt32Method(t *testing.T, paddr unsafe.Pointer) {
  1979  	addr := (*int32)(paddr)
  1980  	v := LoadInt32(addr)
  1981  	vlo := v & ((1 << 16) - 1)
  1982  	vhi := v >> 16
  1983  	if vlo != vhi {
  1984  		t.Fatalf("Int32: %#x != %#x", vlo, vhi)
  1985  	}
  1986  	new := v + 1 + 1<<16
  1987  	if vlo == 1e4 {
  1988  		new = 0
  1989  	}
  1990  	StoreInt32(addr, new)
  1991  }
  1992  
  1993  func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
  1994  	addr := (*uint32)(paddr)
  1995  	v := LoadUint32(addr)
  1996  	vlo := v & ((1 << 16) - 1)
  1997  	vhi := v >> 16
  1998  	if vlo != vhi {
  1999  		t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
  2000  	}
  2001  	new := v + 1 + 1<<16
  2002  	if vlo == 1e4 {
  2003  		new = 0
  2004  	}
  2005  	StoreUint32(addr, new)
  2006  }
  2007  
  2008  func hammerStoreLoadUint32Method(t *testing.T, paddr unsafe.Pointer) {
  2009  	addr := (*Uint32)(paddr)
  2010  	v := addr.Load()
  2011  	vlo := v & ((1 << 16) - 1)
  2012  	vhi := v >> 16
  2013  	if vlo != vhi {
  2014  		t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
  2015  	}
  2016  	new := v + 1 + 1<<16
  2017  	if vlo == 1e4 {
  2018  		new = 0
  2019  	}
  2020  	addr.Store(new)
  2021  }
  2022  
  2023  func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
  2024  	addr := (*int64)(paddr)
  2025  	v := LoadInt64(addr)
  2026  	vlo := v & ((1 << 32) - 1)
  2027  	vhi := v >> 32
  2028  	if vlo != vhi {
  2029  		t.Fatalf("Int64: %#x != %#x", vlo, vhi)
  2030  	}
  2031  	new := v + 1 + 1<<32
  2032  	StoreInt64(addr, new)
  2033  }
  2034  
  2035  func hammerStoreLoadInt64Method(t *testing.T, paddr unsafe.Pointer) {
  2036  	addr := (*Int64)(paddr)
  2037  	v := addr.Load()
  2038  	vlo := v & ((1 << 32) - 1)
  2039  	vhi := v >> 32
  2040  	if vlo != vhi {
  2041  		t.Fatalf("Int64: %#x != %#x", vlo, vhi)
  2042  	}
  2043  	new := v + 1 + 1<<32
  2044  	addr.Store(new)
  2045  }
  2046  
  2047  func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
  2048  	addr := (*uint64)(paddr)
  2049  	v := LoadUint64(addr)
  2050  	vlo := v & ((1 << 32) - 1)
  2051  	vhi := v >> 32
  2052  	if vlo != vhi {
  2053  		t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
  2054  	}
  2055  	new := v + 1 + 1<<32
  2056  	StoreUint64(addr, new)
  2057  }
  2058  
  2059  func hammerStoreLoadUint64Method(t *testing.T, paddr unsafe.Pointer) {
  2060  	addr := (*Uint64)(paddr)
  2061  	v := addr.Load()
  2062  	vlo := v & ((1 << 32) - 1)
  2063  	vhi := v >> 32
  2064  	if vlo != vhi {
  2065  		t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
  2066  	}
  2067  	new := v + 1 + 1<<32
  2068  	addr.Store(new)
  2069  }
  2070  
  2071  func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
  2072  	addr := (*uintptr)(paddr)
  2073  	v := LoadUintptr(addr)
  2074  	new := v
  2075  	if arch32 {
  2076  		vlo := v & ((1 << 16) - 1)
  2077  		vhi := v >> 16
  2078  		if vlo != vhi {
  2079  			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
  2080  		}
  2081  		new = v + 1 + 1<<16
  2082  		if vlo == 1e4 {
  2083  			new = 0
  2084  		}
  2085  	} else {
  2086  		vlo := v & ((1 << 32) - 1)
  2087  		vhi := v >> 32
  2088  		if vlo != vhi {
  2089  			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
  2090  		}
  2091  		inc := uint64(1 + 1<<32)
  2092  		new = v + uintptr(inc)
  2093  	}
  2094  	StoreUintptr(addr, new)
  2095  }
  2096  
  2097  //go:nocheckptr
  2098  func hammerStoreLoadUintptrMethod(t *testing.T, paddr unsafe.Pointer) {
  2099  	addr := (*Uintptr)(paddr)
  2100  	v := addr.Load()
  2101  	new := v
  2102  	if arch32 {
  2103  		vlo := v & ((1 << 16) - 1)
  2104  		vhi := v >> 16
  2105  		if vlo != vhi {
  2106  			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
  2107  		}
  2108  		new = v + 1 + 1<<16
  2109  		if vlo == 1e4 {
  2110  			new = 0
  2111  		}
  2112  	} else {
  2113  		vlo := v & ((1 << 32) - 1)
  2114  		vhi := v >> 32
  2115  		if vlo != vhi {
  2116  			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
  2117  		}
  2118  		inc := uint64(1 + 1<<32)
  2119  		new = v + uintptr(inc)
  2120  	}
  2121  	addr.Store(new)
  2122  }
  2123  
  2124  // This code is just testing that LoadPointer/StorePointer operate
  2125  // atomically; it's not actually calculating pointers.
  2126  //
  2127  //go:nocheckptr
  2128  func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
  2129  	addr := (*unsafe.Pointer)(paddr)
  2130  	v := uintptr(LoadPointer(addr))
  2131  	new := v
  2132  	if arch32 {
  2133  		vlo := v & ((1 << 16) - 1)
  2134  		vhi := v >> 16
  2135  		if vlo != vhi {
  2136  			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
  2137  		}
  2138  		new = v + 1 + 1<<16
  2139  		if vlo == 1e4 {
  2140  			new = 0
  2141  		}
  2142  	} else {
  2143  		vlo := v & ((1 << 32) - 1)
  2144  		vhi := v >> 32
  2145  		if vlo != vhi {
  2146  			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
  2147  		}
  2148  		inc := uint64(1 + 1<<32)
  2149  		new = v + uintptr(inc)
  2150  	}
  2151  	StorePointer(addr, unsafe.Pointer(new))
  2152  }
  2153  
  2154  // This code is just testing that LoadPointer/StorePointer operate
  2155  // atomically; it's not actually calculating pointers.
  2156  //
  2157  //go:nocheckptr
  2158  func hammerStoreLoadPointerMethod(t *testing.T, paddr unsafe.Pointer) {
  2159  	addr := (*Pointer[byte])(paddr)
  2160  	v := uintptr(unsafe.Pointer(addr.Load()))
  2161  	new := v
  2162  	if arch32 {
  2163  		vlo := v & ((1 << 16) - 1)
  2164  		vhi := v >> 16
  2165  		if vlo != vhi {
  2166  			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
  2167  		}
  2168  		new = v + 1 + 1<<16
  2169  		if vlo == 1e4 {
  2170  			new = 0
  2171  		}
  2172  	} else {
  2173  		vlo := v & ((1 << 32) - 1)
  2174  		vhi := v >> 32
  2175  		if vlo != vhi {
  2176  			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
  2177  		}
  2178  		inc := uint64(1 + 1<<32)
  2179  		new = v + uintptr(inc)
  2180  	}
  2181  	addr.Store((*byte)(unsafe.Pointer(new)))
  2182  }
  2183  
  2184  func TestHammerStoreLoad(t *testing.T) {
  2185  	tests := []func(*testing.T, unsafe.Pointer){
  2186  		hammerStoreLoadInt32, hammerStoreLoadUint32,
  2187  		hammerStoreLoadUintptr, hammerStoreLoadPointer,
  2188  		hammerStoreLoadInt32Method, hammerStoreLoadUint32Method,
  2189  		hammerStoreLoadUintptrMethod, hammerStoreLoadPointerMethod,
  2190  		hammerStoreLoadInt64, hammerStoreLoadUint64,
  2191  		hammerStoreLoadInt64Method, hammerStoreLoadUint64Method,
  2192  	}
  2193  	n := int(1e6)
  2194  	if testing.Short() {
  2195  		n = int(1e4)
  2196  	}
  2197  	const procs = 8
  2198  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))
  2199  	// Disable the GC because hammerStoreLoadPointer invokes
  2200  	// write barriers on values that aren't real pointers.
  2201  	defer debug.SetGCPercent(debug.SetGCPercent(-1))
  2202  	// Ensure any in-progress GC is finished.
  2203  	runtime.GC()
  2204  	for _, tt := range tests {
  2205  		c := make(chan int)
  2206  		var val uint64
  2207  		for p := 0; p < procs; p++ {
  2208  			go func() {
  2209  				for i := 0; i < n; i++ {
  2210  					tt(t, unsafe.Pointer(&val))
  2211  				}
  2212  				c <- 1
  2213  			}()
  2214  		}
  2215  		for p := 0; p < procs; p++ {
  2216  			<-c
  2217  		}
  2218  	}
  2219  }
  2220  
  2221  func TestStoreLoadSeqCst32(t *testing.T) {
  2222  	if runtime.NumCPU() == 1 {
  2223  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  2224  	}
  2225  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  2226  	N := int32(1e3)
  2227  	if testing.Short() {
  2228  		N = int32(1e2)
  2229  	}
  2230  	c := make(chan bool, 2)
  2231  	X := [2]int32{}
  2232  	ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}}
  2233  	for p := 0; p < 2; p++ {
  2234  		go func(me int) {
  2235  			he := 1 - me
  2236  			for i := int32(1); i < N; i++ {
  2237  				StoreInt32(&X[me], i)
  2238  				my := LoadInt32(&X[he])
  2239  				StoreInt32(&ack[me][i%3], my)
  2240  				for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ {
  2241  					if w%1000 == 0 {
  2242  						runtime.Gosched()
  2243  					}
  2244  				}
  2245  				his := LoadInt32(&ack[he][i%3])
  2246  				if (my != i && my != i-1) || (his != i && his != i-1) {
  2247  					t.Errorf("invalid values: %d/%d (%d)", my, his, i)
  2248  					break
  2249  				}
  2250  				if my != i && his != i {
  2251  					t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
  2252  					break
  2253  				}
  2254  				StoreInt32(&ack[me][(i-1)%3], -1)
  2255  			}
  2256  			c <- true
  2257  		}(p)
  2258  	}
  2259  	<-c
  2260  	<-c
  2261  }
  2262  
  2263  func TestStoreLoadSeqCst64(t *testing.T) {
  2264  	if runtime.NumCPU() == 1 {
  2265  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  2266  	}
  2267  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  2268  	N := int64(1e3)
  2269  	if testing.Short() {
  2270  		N = int64(1e2)
  2271  	}
  2272  	c := make(chan bool, 2)
  2273  	X := [2]int64{}
  2274  	ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}}
  2275  	for p := 0; p < 2; p++ {
  2276  		go func(me int) {
  2277  			he := 1 - me
  2278  			for i := int64(1); i < N; i++ {
  2279  				StoreInt64(&X[me], i)
  2280  				my := LoadInt64(&X[he])
  2281  				StoreInt64(&ack[me][i%3], my)
  2282  				for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ {
  2283  					if w%1000 == 0 {
  2284  						runtime.Gosched()
  2285  					}
  2286  				}
  2287  				his := LoadInt64(&ack[he][i%3])
  2288  				if (my != i && my != i-1) || (his != i && his != i-1) {
  2289  					t.Errorf("invalid values: %d/%d (%d)", my, his, i)
  2290  					break
  2291  				}
  2292  				if my != i && his != i {
  2293  					t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
  2294  					break
  2295  				}
  2296  				StoreInt64(&ack[me][(i-1)%3], -1)
  2297  			}
  2298  			c <- true
  2299  		}(p)
  2300  	}
  2301  	<-c
  2302  	<-c
  2303  }
  2304  
  2305  func TestStoreLoadRelAcq32(t *testing.T) {
  2306  	if runtime.NumCPU() == 1 {
  2307  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  2308  	}
  2309  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  2310  	N := int32(1e3)
  2311  	if testing.Short() {
  2312  		N = int32(1e2)
  2313  	}
  2314  	c := make(chan bool, 2)
  2315  	type Data struct {
  2316  		signal int32
  2317  		pad1   [128]int8
  2318  		data1  int32
  2319  		pad2   [128]int8
  2320  		data2  float32
  2321  	}
  2322  	var X Data
  2323  	for p := int32(0); p < 2; p++ {
  2324  		go func(p int32) {
  2325  			for i := int32(1); i < N; i++ {
  2326  				if (i+p)%2 == 0 {
  2327  					X.data1 = i
  2328  					X.data2 = float32(i)
  2329  					StoreInt32(&X.signal, i)
  2330  				} else {
  2331  					for w := 1; LoadInt32(&X.signal) != i; w++ {
  2332  						if w%1000 == 0 {
  2333  							runtime.Gosched()
  2334  						}
  2335  					}
  2336  					d1 := X.data1
  2337  					d2 := X.data2
  2338  					if d1 != i || d2 != float32(i) {
  2339  						t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
  2340  						break
  2341  					}
  2342  				}
  2343  			}
  2344  			c <- true
  2345  		}(p)
  2346  	}
  2347  	<-c
  2348  	<-c
  2349  }
  2350  
  2351  func TestStoreLoadRelAcq64(t *testing.T) {
  2352  	if runtime.NumCPU() == 1 {
  2353  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  2354  	}
  2355  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  2356  	N := int64(1e3)
  2357  	if testing.Short() {
  2358  		N = int64(1e2)
  2359  	}
  2360  	c := make(chan bool, 2)
  2361  	type Data struct {
  2362  		signal int64
  2363  		pad1   [128]int8
  2364  		data1  int64
  2365  		pad2   [128]int8
  2366  		data2  float64
  2367  	}
  2368  	var X Data
  2369  	for p := int64(0); p < 2; p++ {
  2370  		go func(p int64) {
  2371  			for i := int64(1); i < N; i++ {
  2372  				if (i+p)%2 == 0 {
  2373  					X.data1 = i
  2374  					X.data2 = float64(i)
  2375  					StoreInt64(&X.signal, i)
  2376  				} else {
  2377  					for w := 1; LoadInt64(&X.signal) != i; w++ {
  2378  						if w%1000 == 0 {
  2379  							runtime.Gosched()
  2380  						}
  2381  					}
  2382  					d1 := X.data1
  2383  					d2 := X.data2
  2384  					if d1 != i || d2 != float64(i) {
  2385  						t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
  2386  						break
  2387  					}
  2388  				}
  2389  			}
  2390  			c <- true
  2391  		}(p)
  2392  	}
  2393  	<-c
  2394  	<-c
  2395  }
  2396  
  2397  func shouldPanic(t *testing.T, name string, f func()) {
  2398  	defer func() {
  2399  		// Check that all GC maps are sane.
  2400  		runtime.GC()
  2401  
  2402  		err := recover()
  2403  		want := "unaligned 64-bit atomic operation"
  2404  		if err == nil {
  2405  			t.Errorf("%s did not panic", name)
  2406  		} else if s, _ := err.(string); s != want {
  2407  			t.Errorf("%s: wanted panic %q, got %q", name, want, err)
  2408  		}
  2409  	}()
  2410  	f()
  2411  }
  2412  
  2413  func TestUnaligned64(t *testing.T) {
  2414  	// Unaligned 64-bit atomics on 32-bit systems are
  2415  	// a continual source of pain. Test that on 32-bit systems they crash
  2416  	// instead of failing silently.
  2417  	if !arch32 {
  2418  		t.Skip("test only runs on 32-bit systems")
  2419  	}
  2420  
  2421  	x := make([]uint32, 4)
  2422  	p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
  2423  
  2424  	shouldPanic(t, "LoadUint64", func() { LoadUint64(p) })
  2425  	shouldPanic(t, "LoadUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Load() })
  2426  	shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) })
  2427  	shouldPanic(t, "StoreUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Store(1) })
  2428  	shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
  2429  	shouldPanic(t, "CompareAndSwapUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).CompareAndSwap(1, 2) })
  2430  	shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
  2431  	shouldPanic(t, "AddUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Add(3) })
  2432  }
  2433  
  2434  func TestAutoAligned64(t *testing.T) {
  2435  	var signed struct {
  2436  		_ uint32
  2437  		i Int64
  2438  	}
  2439  	if o := reflect.TypeOf(&signed).Elem().Field(1).Offset; o != 8 {
  2440  		t.Fatalf("Int64 offset = %d, want 8", o)
  2441  	}
  2442  	if p := reflect.ValueOf(&signed).Elem().Field(1).Addr().Pointer(); p&7 != 0 {
  2443  		t.Fatalf("Int64 pointer = %#x, want 8-aligned", p)
  2444  	}
  2445  
  2446  	var unsigned struct {
  2447  		_ uint32
  2448  		i Uint64
  2449  	}
  2450  	if o := reflect.TypeOf(&unsigned).Elem().Field(1).Offset; o != 8 {
  2451  		t.Fatalf("Uint64 offset = %d, want 8", o)
  2452  	}
  2453  	if p := reflect.ValueOf(&unsigned).Elem().Field(1).Addr().Pointer(); p&7 != 0 {
  2454  		t.Fatalf("Int64 pointer = %#x, want 8-aligned", p)
  2455  	}
  2456  }
  2457  
  2458  func TestNilDeref(t *testing.T) {
  2459  	funcs := [...]func(){
  2460  		func() { CompareAndSwapInt32(nil, 0, 0) },
  2461  		func() { (*Int32)(nil).CompareAndSwap(0, 0) },
  2462  		func() { CompareAndSwapInt64(nil, 0, 0) },
  2463  		func() { (*Int64)(nil).CompareAndSwap(0, 0) },
  2464  		func() { CompareAndSwapUint32(nil, 0, 0) },
  2465  		func() { (*Uint32)(nil).CompareAndSwap(0, 0) },
  2466  		func() { CompareAndSwapUint64(nil, 0, 0) },
  2467  		func() { (*Uint64)(nil).CompareAndSwap(0, 0) },
  2468  		func() { CompareAndSwapUintptr(nil, 0, 0) },
  2469  		func() { (*Uintptr)(nil).CompareAndSwap(0, 0) },
  2470  		func() { CompareAndSwapPointer(nil, nil, nil) },
  2471  		func() { (*Pointer[byte])(nil).CompareAndSwap(nil, nil) },
  2472  		func() { SwapInt32(nil, 0) },
  2473  		func() { (*Int32)(nil).Swap(0) },
  2474  		func() { SwapUint32(nil, 0) },
  2475  		func() { (*Uint32)(nil).Swap(0) },
  2476  		func() { SwapInt64(nil, 0) },
  2477  		func() { (*Int64)(nil).Swap(0) },
  2478  		func() { SwapUint64(nil, 0) },
  2479  		func() { (*Uint64)(nil).Swap(0) },
  2480  		func() { SwapUintptr(nil, 0) },
  2481  		func() { (*Uintptr)(nil).Swap(0) },
  2482  		func() { SwapPointer(nil, nil) },
  2483  		func() { (*Pointer[byte])(nil).Swap(nil) },
  2484  		func() { AddInt32(nil, 0) },
  2485  		func() { (*Int32)(nil).Add(0) },
  2486  		func() { AddUint32(nil, 0) },
  2487  		func() { (*Uint32)(nil).Add(0) },
  2488  		func() { AddInt64(nil, 0) },
  2489  		func() { (*Int64)(nil).Add(0) },
  2490  		func() { AddUint64(nil, 0) },
  2491  		func() { (*Uint64)(nil).Add(0) },
  2492  		func() { AddUintptr(nil, 0) },
  2493  		func() { (*Uintptr)(nil).Add(0) },
  2494  		func() { LoadInt32(nil) },
  2495  		func() { (*Int32)(nil).Load() },
  2496  		func() { LoadInt64(nil) },
  2497  		func() { (*Int64)(nil).Load() },
  2498  		func() { LoadUint32(nil) },
  2499  		func() { (*Uint32)(nil).Load() },
  2500  		func() { LoadUint64(nil) },
  2501  		func() { (*Uint64)(nil).Load() },
  2502  		func() { LoadUintptr(nil) },
  2503  		func() { (*Uintptr)(nil).Load() },
  2504  		func() { LoadPointer(nil) },
  2505  		func() { (*Pointer[byte])(nil).Load() },
  2506  		func() { StoreInt32(nil, 0) },
  2507  		func() { (*Int32)(nil).Store(0) },
  2508  		func() { StoreInt64(nil, 0) },
  2509  		func() { (*Int64)(nil).Store(0) },
  2510  		func() { StoreUint32(nil, 0) },
  2511  		func() { (*Uint32)(nil).Store(0) },
  2512  		func() { StoreUint64(nil, 0) },
  2513  		func() { (*Uint64)(nil).Store(0) },
  2514  		func() { StoreUintptr(nil, 0) },
  2515  		func() { (*Uintptr)(nil).Store(0) },
  2516  		func() { StorePointer(nil, nil) },
  2517  		func() { (*Pointer[byte])(nil).Store(nil) },
  2518  	}
  2519  	for _, f := range funcs {
  2520  		func() {
  2521  			defer func() {
  2522  				runtime.GC()
  2523  				recover()
  2524  			}()
  2525  			f()
  2526  		}()
  2527  	}
  2528  }
  2529  
  2530  // Test that this compiles.
  2531  // When atomic.Pointer used _ [0]T, it did not.
  2532  type List struct {
  2533  	Next Pointer[List]
  2534  }
  2535  

View as plain text