github.com/hongwozai/go-src-1.4.3@v0.0.0-20191127132709-dc3fce3dbccb/src/sync/atomic/atomic_test.go (about)

     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  	"runtime"
    10  	"strings"
    11  	. "sync/atomic"
    12  	"testing"
    13  	"unsafe"
    14  )
    15  
    16  // Tests of correct behavior, without contention.
    17  // (Does the function work as advertised?)
    18  //
    19  // Test that the Add functions add correctly.
    20  // Test that the CompareAndSwap functions actually
    21  // do the comparison and the swap correctly.
    22  //
    23  // The loop over power-of-two values is meant to
    24  // ensure that the operations apply to the full word size.
    25  // The struct fields x.before and x.after check that the
    26  // operations do not extend past the full word size.
    27  
    28  const (
    29  	magic32 = 0xdedbeef
    30  	magic64 = 0xdeddeadbeefbeef
    31  )
    32  
    33  // Do the 64-bit functions panic?  If so, don't bother testing.
    34  var test64err = func() (err interface{}) {
    35  	defer func() {
    36  		err = recover()
    37  	}()
    38  	var x int64
    39  	AddInt64(&x, 1)
    40  	return nil
    41  }()
    42  
    43  func TestSwapInt32(t *testing.T) {
    44  	var x struct {
    45  		before int32
    46  		i      int32
    47  		after  int32
    48  	}
    49  	x.before = magic32
    50  	x.after = magic32
    51  	var j int32
    52  	for delta := int32(1); delta+delta > delta; delta += delta {
    53  		k := SwapInt32(&x.i, delta)
    54  		if x.i != delta || k != j {
    55  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    56  		}
    57  		j = delta
    58  	}
    59  	if x.before != magic32 || x.after != magic32 {
    60  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    61  	}
    62  }
    63  
    64  func TestSwapUint32(t *testing.T) {
    65  	var x struct {
    66  		before uint32
    67  		i      uint32
    68  		after  uint32
    69  	}
    70  	x.before = magic32
    71  	x.after = magic32
    72  	var j uint32
    73  	for delta := uint32(1); delta+delta > delta; delta += delta {
    74  		k := SwapUint32(&x.i, delta)
    75  		if x.i != delta || k != j {
    76  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    77  		}
    78  		j = delta
    79  	}
    80  	if x.before != magic32 || x.after != magic32 {
    81  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    82  	}
    83  }
    84  
    85  func TestSwapInt64(t *testing.T) {
    86  	if test64err != nil {
    87  		t.Skipf("Skipping 64-bit tests: %v", test64err)
    88  	}
    89  	var x struct {
    90  		before int64
    91  		i      int64
    92  		after  int64
    93  	}
    94  	x.before = magic64
    95  	x.after = magic64
    96  	var j int64
    97  	for delta := int64(1); delta+delta > delta; delta += delta {
    98  		k := SwapInt64(&x.i, delta)
    99  		if x.i != delta || k != j {
   100  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   101  		}
   102  		j = delta
   103  	}
   104  	if x.before != magic64 || x.after != magic64 {
   105  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   106  	}
   107  }
   108  
   109  func TestSwapUint64(t *testing.T) {
   110  	if test64err != nil {
   111  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   112  	}
   113  	var x struct {
   114  		before uint64
   115  		i      uint64
   116  		after  uint64
   117  	}
   118  	x.before = magic64
   119  	x.after = magic64
   120  	var j uint64
   121  	for delta := uint64(1); delta+delta > delta; delta += delta {
   122  		k := SwapUint64(&x.i, delta)
   123  		if x.i != delta || k != j {
   124  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   125  		}
   126  		j = delta
   127  	}
   128  	if x.before != magic64 || x.after != magic64 {
   129  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   130  	}
   131  }
   132  
   133  func TestSwapUintptr(t *testing.T) {
   134  	var x struct {
   135  		before uintptr
   136  		i      uintptr
   137  		after  uintptr
   138  	}
   139  	var m uint64 = magic64
   140  	magicptr := uintptr(m)
   141  	x.before = magicptr
   142  	x.after = magicptr
   143  	var j uintptr
   144  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   145  		k := SwapUintptr(&x.i, delta)
   146  		if x.i != delta || k != j {
   147  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   148  		}
   149  		j = delta
   150  	}
   151  	if x.before != magicptr || x.after != magicptr {
   152  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   153  	}
   154  }
   155  
   156  func TestSwapPointer(t *testing.T) {
   157  	var x struct {
   158  		before uintptr
   159  		i      unsafe.Pointer
   160  		after  uintptr
   161  	}
   162  	var m uint64 = magic64
   163  	magicptr := uintptr(m)
   164  	x.before = magicptr
   165  	x.after = magicptr
   166  	var j uintptr
   167  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   168  		k := SwapPointer(&x.i, unsafe.Pointer(delta))
   169  		if uintptr(x.i) != delta || uintptr(k) != j {
   170  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   171  		}
   172  		j = delta
   173  	}
   174  	if x.before != magicptr || x.after != magicptr {
   175  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   176  	}
   177  }
   178  
   179  func TestAddInt32(t *testing.T) {
   180  	var x struct {
   181  		before int32
   182  		i      int32
   183  		after  int32
   184  	}
   185  	x.before = magic32
   186  	x.after = magic32
   187  	var j int32
   188  	for delta := int32(1); delta+delta > delta; delta += delta {
   189  		k := AddInt32(&x.i, delta)
   190  		j += delta
   191  		if x.i != j || k != j {
   192  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   193  		}
   194  	}
   195  	if x.before != magic32 || x.after != magic32 {
   196  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   197  	}
   198  }
   199  
   200  func TestAddUint32(t *testing.T) {
   201  	var x struct {
   202  		before uint32
   203  		i      uint32
   204  		after  uint32
   205  	}
   206  	x.before = magic32
   207  	x.after = magic32
   208  	var j uint32
   209  	for delta := uint32(1); delta+delta > delta; delta += delta {
   210  		k := AddUint32(&x.i, delta)
   211  		j += delta
   212  		if x.i != j || k != j {
   213  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   214  		}
   215  	}
   216  	if x.before != magic32 || x.after != magic32 {
   217  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   218  	}
   219  }
   220  
   221  func TestAddInt64(t *testing.T) {
   222  	if test64err != nil {
   223  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   224  	}
   225  	var x struct {
   226  		before int64
   227  		i      int64
   228  		after  int64
   229  	}
   230  	x.before = magic64
   231  	x.after = magic64
   232  	var j int64
   233  	for delta := int64(1); delta+delta > delta; delta += delta {
   234  		k := AddInt64(&x.i, delta)
   235  		j += delta
   236  		if x.i != j || k != j {
   237  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   238  		}
   239  	}
   240  	if x.before != magic64 || x.after != magic64 {
   241  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, int64(magic64), int64(magic64))
   242  	}
   243  }
   244  
   245  func TestAddUint64(t *testing.T) {
   246  	if test64err != nil {
   247  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   248  	}
   249  	var x struct {
   250  		before uint64
   251  		i      uint64
   252  		after  uint64
   253  	}
   254  	x.before = magic64
   255  	x.after = magic64
   256  	var j uint64
   257  	for delta := uint64(1); delta+delta > delta; delta += delta {
   258  		k := AddUint64(&x.i, delta)
   259  		j += delta
   260  		if x.i != j || k != j {
   261  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   262  		}
   263  	}
   264  	if x.before != magic64 || x.after != magic64 {
   265  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   266  	}
   267  }
   268  
   269  func TestAddUintptr(t *testing.T) {
   270  	var x struct {
   271  		before uintptr
   272  		i      uintptr
   273  		after  uintptr
   274  	}
   275  	var m uint64 = magic64
   276  	magicptr := uintptr(m)
   277  	x.before = magicptr
   278  	x.after = magicptr
   279  	var j uintptr
   280  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   281  		k := AddUintptr(&x.i, delta)
   282  		j += delta
   283  		if x.i != j || k != j {
   284  			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
   285  		}
   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 TestCompareAndSwapInt32(t *testing.T) {
   293  	var x struct {
   294  		before int32
   295  		i      int32
   296  		after  int32
   297  	}
   298  	x.before = magic32
   299  	x.after = magic32
   300  	for val := int32(1); val+val > val; val += val {
   301  		x.i = val
   302  		if !CompareAndSwapInt32(&x.i, val, val+1) {
   303  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   304  		}
   305  		if x.i != val+1 {
   306  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   307  		}
   308  		x.i = val + 1
   309  		if CompareAndSwapInt32(&x.i, val, val+2) {
   310  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   311  		}
   312  		if x.i != val+1 {
   313  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   314  		}
   315  	}
   316  	if x.before != magic32 || x.after != magic32 {
   317  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   318  	}
   319  }
   320  
   321  func TestCompareAndSwapUint32(t *testing.T) {
   322  	var x struct {
   323  		before uint32
   324  		i      uint32
   325  		after  uint32
   326  	}
   327  	x.before = magic32
   328  	x.after = magic32
   329  	for val := uint32(1); val+val > val; val += val {
   330  		x.i = val
   331  		if !CompareAndSwapUint32(&x.i, val, val+1) {
   332  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   333  		}
   334  		if x.i != val+1 {
   335  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   336  		}
   337  		x.i = val + 1
   338  		if CompareAndSwapUint32(&x.i, val, val+2) {
   339  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   340  		}
   341  		if x.i != val+1 {
   342  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   343  		}
   344  	}
   345  	if x.before != magic32 || x.after != magic32 {
   346  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   347  	}
   348  }
   349  
   350  func TestCompareAndSwapInt64(t *testing.T) {
   351  	if test64err != nil {
   352  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   353  	}
   354  	var x struct {
   355  		before int64
   356  		i      int64
   357  		after  int64
   358  	}
   359  	x.before = magic64
   360  	x.after = magic64
   361  	for val := int64(1); val+val > val; val += val {
   362  		x.i = val
   363  		if !CompareAndSwapInt64(&x.i, val, val+1) {
   364  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   365  		}
   366  		if x.i != val+1 {
   367  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   368  		}
   369  		x.i = val + 1
   370  		if CompareAndSwapInt64(&x.i, val, val+2) {
   371  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   372  		}
   373  		if x.i != val+1 {
   374  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   375  		}
   376  	}
   377  	if x.before != magic64 || x.after != magic64 {
   378  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   379  	}
   380  }
   381  
   382  func testCompareAndSwapUint64(t *testing.T, cas func(*uint64, uint64, uint64) bool) {
   383  	if test64err != nil {
   384  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   385  	}
   386  	var x struct {
   387  		before uint64
   388  		i      uint64
   389  		after  uint64
   390  	}
   391  	x.before = magic64
   392  	x.after = magic64
   393  	for val := uint64(1); val+val > val; val += val {
   394  		x.i = val
   395  		if !cas(&x.i, val, val+1) {
   396  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   397  		}
   398  		if x.i != val+1 {
   399  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   400  		}
   401  		x.i = val + 1
   402  		if cas(&x.i, val, val+2) {
   403  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   404  		}
   405  		if x.i != val+1 {
   406  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   407  		}
   408  	}
   409  	if x.before != magic64 || x.after != magic64 {
   410  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   411  	}
   412  }
   413  
   414  func TestCompareAndSwapUint64(t *testing.T) {
   415  	testCompareAndSwapUint64(t, CompareAndSwapUint64)
   416  }
   417  
   418  func TestCompareAndSwapUintptr(t *testing.T) {
   419  	var x struct {
   420  		before uintptr
   421  		i      uintptr
   422  		after  uintptr
   423  	}
   424  	var m uint64 = magic64
   425  	magicptr := uintptr(m)
   426  	x.before = magicptr
   427  	x.after = magicptr
   428  	for val := uintptr(1); val+val > val; val += val {
   429  		x.i = val
   430  		if !CompareAndSwapUintptr(&x.i, val, val+1) {
   431  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   432  		}
   433  		if x.i != val+1 {
   434  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   435  		}
   436  		x.i = val + 1
   437  		if CompareAndSwapUintptr(&x.i, val, val+2) {
   438  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   439  		}
   440  		if x.i != val+1 {
   441  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   442  		}
   443  	}
   444  	if x.before != magicptr || x.after != magicptr {
   445  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   446  	}
   447  }
   448  
   449  func TestCompareAndSwapPointer(t *testing.T) {
   450  	var x struct {
   451  		before uintptr
   452  		i      unsafe.Pointer
   453  		after  uintptr
   454  	}
   455  	var m uint64 = magic64
   456  	magicptr := uintptr(m)
   457  	x.before = magicptr
   458  	x.after = magicptr
   459  	for val := uintptr(1); val+val > val; val += val {
   460  		x.i = unsafe.Pointer(val)
   461  		if !CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+1)) {
   462  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   463  		}
   464  		if x.i != unsafe.Pointer(val+1) {
   465  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   466  		}
   467  		x.i = unsafe.Pointer(val + 1)
   468  		if CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+2)) {
   469  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   470  		}
   471  		if x.i != unsafe.Pointer(val+1) {
   472  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   473  		}
   474  	}
   475  	if x.before != magicptr || x.after != magicptr {
   476  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   477  	}
   478  }
   479  
   480  func TestLoadInt32(t *testing.T) {
   481  	var x struct {
   482  		before int32
   483  		i      int32
   484  		after  int32
   485  	}
   486  	x.before = magic32
   487  	x.after = magic32
   488  	for delta := int32(1); delta+delta > delta; delta += delta {
   489  		k := LoadInt32(&x.i)
   490  		if k != x.i {
   491  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   492  		}
   493  		x.i += delta
   494  	}
   495  	if x.before != magic32 || x.after != magic32 {
   496  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   497  	}
   498  }
   499  
   500  func TestLoadUint32(t *testing.T) {
   501  	var x struct {
   502  		before uint32
   503  		i      uint32
   504  		after  uint32
   505  	}
   506  	x.before = magic32
   507  	x.after = magic32
   508  	for delta := uint32(1); delta+delta > delta; delta += delta {
   509  		k := LoadUint32(&x.i)
   510  		if k != x.i {
   511  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   512  		}
   513  		x.i += delta
   514  	}
   515  	if x.before != magic32 || x.after != magic32 {
   516  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   517  	}
   518  }
   519  
   520  func TestLoadInt64(t *testing.T) {
   521  	if test64err != nil {
   522  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   523  	}
   524  	var x struct {
   525  		before int64
   526  		i      int64
   527  		after  int64
   528  	}
   529  	x.before = magic64
   530  	x.after = magic64
   531  	for delta := int64(1); delta+delta > delta; delta += delta {
   532  		k := LoadInt64(&x.i)
   533  		if k != x.i {
   534  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   535  		}
   536  		x.i += delta
   537  	}
   538  	if x.before != magic64 || x.after != magic64 {
   539  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   540  	}
   541  }
   542  
   543  func TestLoadUint64(t *testing.T) {
   544  	if test64err != nil {
   545  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   546  	}
   547  	var x struct {
   548  		before uint64
   549  		i      uint64
   550  		after  uint64
   551  	}
   552  	x.before = magic64
   553  	x.after = magic64
   554  	for delta := uint64(1); delta+delta > delta; delta += delta {
   555  		k := LoadUint64(&x.i)
   556  		if k != x.i {
   557  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   558  		}
   559  		x.i += delta
   560  	}
   561  	if x.before != magic64 || x.after != magic64 {
   562  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   563  	}
   564  }
   565  
   566  func TestLoadUintptr(t *testing.T) {
   567  	var x struct {
   568  		before uintptr
   569  		i      uintptr
   570  		after  uintptr
   571  	}
   572  	var m uint64 = magic64
   573  	magicptr := uintptr(m)
   574  	x.before = magicptr
   575  	x.after = magicptr
   576  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   577  		k := LoadUintptr(&x.i)
   578  		if k != x.i {
   579  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   580  		}
   581  		x.i += delta
   582  	}
   583  	if x.before != magicptr || x.after != magicptr {
   584  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   585  	}
   586  }
   587  
   588  func TestLoadPointer(t *testing.T) {
   589  	var x struct {
   590  		before uintptr
   591  		i      unsafe.Pointer
   592  		after  uintptr
   593  	}
   594  	var m uint64 = magic64
   595  	magicptr := uintptr(m)
   596  	x.before = magicptr
   597  	x.after = magicptr
   598  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   599  		k := LoadPointer(&x.i)
   600  		if k != x.i {
   601  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   602  		}
   603  		x.i = unsafe.Pointer(uintptr(x.i) + delta)
   604  	}
   605  	if x.before != magicptr || x.after != magicptr {
   606  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   607  	}
   608  }
   609  
   610  func TestStoreInt32(t *testing.T) {
   611  	var x struct {
   612  		before int32
   613  		i      int32
   614  		after  int32
   615  	}
   616  	x.before = magic32
   617  	x.after = magic32
   618  	v := int32(0)
   619  	for delta := int32(1); delta+delta > delta; delta += delta {
   620  		StoreInt32(&x.i, v)
   621  		if x.i != v {
   622  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   623  		}
   624  		v += delta
   625  	}
   626  	if x.before != magic32 || x.after != magic32 {
   627  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   628  	}
   629  }
   630  
   631  func TestStoreUint32(t *testing.T) {
   632  	var x struct {
   633  		before uint32
   634  		i      uint32
   635  		after  uint32
   636  	}
   637  	x.before = magic32
   638  	x.after = magic32
   639  	v := uint32(0)
   640  	for delta := uint32(1); delta+delta > delta; delta += delta {
   641  		StoreUint32(&x.i, v)
   642  		if x.i != v {
   643  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   644  		}
   645  		v += delta
   646  	}
   647  	if x.before != magic32 || x.after != magic32 {
   648  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   649  	}
   650  }
   651  
   652  func TestStoreInt64(t *testing.T) {
   653  	if test64err != nil {
   654  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   655  	}
   656  	var x struct {
   657  		before int64
   658  		i      int64
   659  		after  int64
   660  	}
   661  	x.before = magic64
   662  	x.after = magic64
   663  	v := int64(0)
   664  	for delta := int64(1); delta+delta > delta; delta += delta {
   665  		StoreInt64(&x.i, v)
   666  		if x.i != v {
   667  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   668  		}
   669  		v += delta
   670  	}
   671  	if x.before != magic64 || x.after != magic64 {
   672  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   673  	}
   674  }
   675  
   676  func TestStoreUint64(t *testing.T) {
   677  	if test64err != nil {
   678  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   679  	}
   680  	var x struct {
   681  		before uint64
   682  		i      uint64
   683  		after  uint64
   684  	}
   685  	x.before = magic64
   686  	x.after = magic64
   687  	v := uint64(0)
   688  	for delta := uint64(1); delta+delta > delta; delta += delta {
   689  		StoreUint64(&x.i, v)
   690  		if x.i != v {
   691  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   692  		}
   693  		v += delta
   694  	}
   695  	if x.before != magic64 || x.after != magic64 {
   696  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   697  	}
   698  }
   699  
   700  func TestStoreUintptr(t *testing.T) {
   701  	var x struct {
   702  		before uintptr
   703  		i      uintptr
   704  		after  uintptr
   705  	}
   706  	var m uint64 = magic64
   707  	magicptr := uintptr(m)
   708  	x.before = magicptr
   709  	x.after = magicptr
   710  	v := uintptr(0)
   711  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   712  		StoreUintptr(&x.i, v)
   713  		if x.i != v {
   714  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   715  		}
   716  		v += delta
   717  	}
   718  	if x.before != magicptr || x.after != magicptr {
   719  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   720  	}
   721  }
   722  
   723  func TestStorePointer(t *testing.T) {
   724  	var x struct {
   725  		before uintptr
   726  		i      unsafe.Pointer
   727  		after  uintptr
   728  	}
   729  	var m uint64 = magic64
   730  	magicptr := uintptr(m)
   731  	x.before = magicptr
   732  	x.after = magicptr
   733  	v := unsafe.Pointer(uintptr(0))
   734  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   735  		StorePointer(&x.i, unsafe.Pointer(v))
   736  		if x.i != v {
   737  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   738  		}
   739  		v = unsafe.Pointer(uintptr(v) + delta)
   740  	}
   741  	if x.before != magicptr || x.after != magicptr {
   742  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   743  	}
   744  }
   745  
   746  // Tests of correct behavior, with contention.
   747  // (Is the function atomic?)
   748  //
   749  // For each function, we write a "hammer" function that repeatedly
   750  // uses the atomic operation to add 1 to a value.  After running
   751  // multiple hammers in parallel, check that we end with the correct
   752  // total.
   753  // Swap can't add 1, so it uses a different scheme.
   754  // The functions repeatedly generate a pseudo-random number such that
   755  // low bits are equal to high bits, swap, check that the old value
   756  // has low and high bits equal.
   757  
   758  var hammer32 = map[string]func(*uint32, int){
   759  	"SwapInt32":             hammerSwapInt32,
   760  	"SwapUint32":            hammerSwapUint32,
   761  	"SwapUintptr":           hammerSwapUintptr32,
   762  	"SwapPointer":           hammerSwapPointer32,
   763  	"AddInt32":              hammerAddInt32,
   764  	"AddUint32":             hammerAddUint32,
   765  	"AddUintptr":            hammerAddUintptr32,
   766  	"CompareAndSwapInt32":   hammerCompareAndSwapInt32,
   767  	"CompareAndSwapUint32":  hammerCompareAndSwapUint32,
   768  	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr32,
   769  	"CompareAndSwapPointer": hammerCompareAndSwapPointer32,
   770  }
   771  
   772  func init() {
   773  	var v uint64 = 1 << 50
   774  	if uintptr(v) != 0 {
   775  		// 64-bit system; clear uintptr tests
   776  		delete(hammer32, "SwapUintptr")
   777  		delete(hammer32, "SwapPointer")
   778  		delete(hammer32, "AddUintptr")
   779  		delete(hammer32, "CompareAndSwapUintptr")
   780  		delete(hammer32, "CompareAndSwapPointer")
   781  	}
   782  }
   783  
   784  func hammerSwapInt32(uaddr *uint32, count int) {
   785  	addr := (*int32)(unsafe.Pointer(uaddr))
   786  	seed := int(uintptr(unsafe.Pointer(&count)))
   787  	for i := 0; i < count; i++ {
   788  		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
   789  		old := uint32(SwapInt32(addr, int32(new)))
   790  		if old>>16 != old<<16>>16 {
   791  			panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
   792  		}
   793  	}
   794  }
   795  
   796  func hammerSwapUint32(addr *uint32, count int) {
   797  	seed := int(uintptr(unsafe.Pointer(&count)))
   798  	for i := 0; i < count; i++ {
   799  		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
   800  		old := SwapUint32(addr, new)
   801  		if old>>16 != old<<16>>16 {
   802  			panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
   803  		}
   804  	}
   805  }
   806  
   807  func hammerSwapUintptr32(uaddr *uint32, count int) {
   808  	// only safe when uintptr is 32-bit.
   809  	// not called on 64-bit systems.
   810  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   811  	seed := int(uintptr(unsafe.Pointer(&count)))
   812  	for i := 0; i < count; i++ {
   813  		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
   814  		old := SwapUintptr(addr, new)
   815  		if old>>16 != old<<16>>16 {
   816  			panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old))
   817  		}
   818  	}
   819  }
   820  
   821  func hammerSwapPointer32(uaddr *uint32, count int) {
   822  	// only safe when uintptr is 32-bit.
   823  	// not called on 64-bit systems.
   824  	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
   825  	seed := int(uintptr(unsafe.Pointer(&count)))
   826  	for i := 0; i < count; i++ {
   827  		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
   828  		old := uintptr(SwapPointer(addr, unsafe.Pointer(new)))
   829  		if old>>16 != old<<16>>16 {
   830  			panic(fmt.Sprintf("SwapPointer is not atomic: %#08x", old))
   831  		}
   832  	}
   833  }
   834  
   835  func hammerAddInt32(uaddr *uint32, count int) {
   836  	addr := (*int32)(unsafe.Pointer(uaddr))
   837  	for i := 0; i < count; i++ {
   838  		AddInt32(addr, 1)
   839  	}
   840  }
   841  
   842  func hammerAddUint32(addr *uint32, count int) {
   843  	for i := 0; i < count; i++ {
   844  		AddUint32(addr, 1)
   845  	}
   846  }
   847  
   848  func hammerAddUintptr32(uaddr *uint32, count int) {
   849  	// only safe when uintptr is 32-bit.
   850  	// not called on 64-bit systems.
   851  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   852  	for i := 0; i < count; i++ {
   853  		AddUintptr(addr, 1)
   854  	}
   855  }
   856  
   857  func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
   858  	addr := (*int32)(unsafe.Pointer(uaddr))
   859  	for i := 0; i < count; i++ {
   860  		for {
   861  			v := LoadInt32(addr)
   862  			if CompareAndSwapInt32(addr, v, v+1) {
   863  				break
   864  			}
   865  		}
   866  	}
   867  }
   868  
   869  func hammerCompareAndSwapUint32(addr *uint32, count int) {
   870  	for i := 0; i < count; i++ {
   871  		for {
   872  			v := LoadUint32(addr)
   873  			if CompareAndSwapUint32(addr, v, v+1) {
   874  				break
   875  			}
   876  		}
   877  	}
   878  }
   879  
   880  func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
   881  	// only safe when uintptr is 32-bit.
   882  	// not called on 64-bit systems.
   883  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   884  	for i := 0; i < count; i++ {
   885  		for {
   886  			v := LoadUintptr(addr)
   887  			if CompareAndSwapUintptr(addr, v, v+1) {
   888  				break
   889  			}
   890  		}
   891  	}
   892  }
   893  
   894  func hammerCompareAndSwapPointer32(uaddr *uint32, count int) {
   895  	// only safe when uintptr is 32-bit.
   896  	// not called on 64-bit systems.
   897  	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
   898  	for i := 0; i < count; i++ {
   899  		for {
   900  			v := LoadPointer(addr)
   901  			if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
   902  				break
   903  			}
   904  		}
   905  	}
   906  }
   907  
   908  func TestHammer32(t *testing.T) {
   909  	const p = 4
   910  	n := 100000
   911  	if testing.Short() {
   912  		n = 1000
   913  	}
   914  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
   915  
   916  	for name, testf := range hammer32 {
   917  		c := make(chan int)
   918  		var val uint32
   919  		for i := 0; i < p; i++ {
   920  			go func() {
   921  				defer func() {
   922  					if err := recover(); err != nil {
   923  						t.Error(err.(string))
   924  					}
   925  					c <- 1
   926  				}()
   927  				testf(&val, n)
   928  			}()
   929  		}
   930  		for i := 0; i < p; i++ {
   931  			<-c
   932  		}
   933  		if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p {
   934  			t.Fatalf("%s: val=%d want %d", name, val, n*p)
   935  		}
   936  	}
   937  }
   938  
   939  var hammer64 = map[string]func(*uint64, int){
   940  	"SwapInt64":             hammerSwapInt64,
   941  	"SwapUint64":            hammerSwapUint64,
   942  	"SwapUintptr":           hammerSwapUintptr64,
   943  	"SwapPointer":           hammerSwapPointer64,
   944  	"AddInt64":              hammerAddInt64,
   945  	"AddUint64":             hammerAddUint64,
   946  	"AddUintptr":            hammerAddUintptr64,
   947  	"CompareAndSwapInt64":   hammerCompareAndSwapInt64,
   948  	"CompareAndSwapUint64":  hammerCompareAndSwapUint64,
   949  	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr64,
   950  	"CompareAndSwapPointer": hammerCompareAndSwapPointer64,
   951  }
   952  
   953  func init() {
   954  	var v uint64 = 1 << 50
   955  	if uintptr(v) == 0 {
   956  		// 32-bit system; clear uintptr tests
   957  		delete(hammer64, "SwapUintptr")
   958  		delete(hammer64, "SwapPointer")
   959  		delete(hammer64, "AddUintptr")
   960  		delete(hammer64, "CompareAndSwapUintptr")
   961  		delete(hammer64, "CompareAndSwapPointer")
   962  	}
   963  }
   964  
   965  func hammerSwapInt64(uaddr *uint64, count int) {
   966  	addr := (*int64)(unsafe.Pointer(uaddr))
   967  	seed := int(uintptr(unsafe.Pointer(&count)))
   968  	for i := 0; i < count; i++ {
   969  		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
   970  		old := uint64(SwapInt64(addr, int64(new)))
   971  		if old>>32 != old<<32>>32 {
   972  			panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
   973  		}
   974  	}
   975  }
   976  
   977  func hammerSwapUint64(addr *uint64, count int) {
   978  	seed := int(uintptr(unsafe.Pointer(&count)))
   979  	for i := 0; i < count; i++ {
   980  		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
   981  		old := SwapUint64(addr, new)
   982  		if old>>32 != old<<32>>32 {
   983  			panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
   984  		}
   985  	}
   986  }
   987  
   988  func hammerSwapUintptr64(uaddr *uint64, count int) {
   989  	// only safe when uintptr is 64-bit.
   990  	// not called on 32-bit systems.
   991  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   992  	seed := int(uintptr(unsafe.Pointer(&count)))
   993  	for i := 0; i < count; i++ {
   994  		new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
   995  		old := SwapUintptr(addr, new)
   996  		if old>>32 != old<<32>>32 {
   997  			panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
   998  		}
   999  	}
  1000  }
  1001  
  1002  func hammerSwapPointer64(uaddr *uint64, count int) {
  1003  	// only safe when uintptr is 64-bit.
  1004  	// not called on 32-bit systems.
  1005  	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
  1006  	seed := int(uintptr(unsafe.Pointer(&count)))
  1007  	for i := 0; i < count; i++ {
  1008  		new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
  1009  		old := uintptr(SwapPointer(addr, unsafe.Pointer(new)))
  1010  		if old>>32 != old<<32>>32 {
  1011  			panic(fmt.Sprintf("SwapPointer is not atomic: %v", old))
  1012  		}
  1013  	}
  1014  }
  1015  
  1016  func hammerAddInt64(uaddr *uint64, count int) {
  1017  	addr := (*int64)(unsafe.Pointer(uaddr))
  1018  	for i := 0; i < count; i++ {
  1019  		AddInt64(addr, 1)
  1020  	}
  1021  }
  1022  
  1023  func hammerAddUint64(addr *uint64, count int) {
  1024  	for i := 0; i < count; i++ {
  1025  		AddUint64(addr, 1)
  1026  	}
  1027  }
  1028  
  1029  func hammerAddUintptr64(uaddr *uint64, count int) {
  1030  	// only safe when uintptr is 64-bit.
  1031  	// not called on 32-bit systems.
  1032  	addr := (*uintptr)(unsafe.Pointer(uaddr))
  1033  	for i := 0; i < count; i++ {
  1034  		AddUintptr(addr, 1)
  1035  	}
  1036  }
  1037  
  1038  func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
  1039  	addr := (*int64)(unsafe.Pointer(uaddr))
  1040  	for i := 0; i < count; i++ {
  1041  		for {
  1042  			v := LoadInt64(addr)
  1043  			if CompareAndSwapInt64(addr, v, v+1) {
  1044  				break
  1045  			}
  1046  		}
  1047  	}
  1048  }
  1049  
  1050  func hammerCompareAndSwapUint64(addr *uint64, count int) {
  1051  	for i := 0; i < count; i++ {
  1052  		for {
  1053  			v := LoadUint64(addr)
  1054  			if CompareAndSwapUint64(addr, v, v+1) {
  1055  				break
  1056  			}
  1057  		}
  1058  	}
  1059  }
  1060  
  1061  func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
  1062  	// only safe when uintptr is 64-bit.
  1063  	// not called on 32-bit systems.
  1064  	addr := (*uintptr)(unsafe.Pointer(uaddr))
  1065  	for i := 0; i < count; i++ {
  1066  		for {
  1067  			v := LoadUintptr(addr)
  1068  			if CompareAndSwapUintptr(addr, v, v+1) {
  1069  				break
  1070  			}
  1071  		}
  1072  	}
  1073  }
  1074  
  1075  func hammerCompareAndSwapPointer64(uaddr *uint64, count int) {
  1076  	// only safe when uintptr is 64-bit.
  1077  	// not called on 32-bit systems.
  1078  	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
  1079  	for i := 0; i < count; i++ {
  1080  		for {
  1081  			v := LoadPointer(addr)
  1082  			if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
  1083  				break
  1084  			}
  1085  		}
  1086  	}
  1087  }
  1088  
  1089  func TestHammer64(t *testing.T) {
  1090  	if test64err != nil {
  1091  		t.Skipf("Skipping 64-bit tests: %v", test64err)
  1092  	}
  1093  	const p = 4
  1094  	n := 100000
  1095  	if testing.Short() {
  1096  		n = 1000
  1097  	}
  1098  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
  1099  
  1100  	for name, testf := range hammer64 {
  1101  		c := make(chan int)
  1102  		var val uint64
  1103  		for i := 0; i < p; i++ {
  1104  			go func() {
  1105  				defer func() {
  1106  					if err := recover(); err != nil {
  1107  						t.Error(err.(string))
  1108  					}
  1109  					c <- 1
  1110  				}()
  1111  				testf(&val, n)
  1112  			}()
  1113  		}
  1114  		for i := 0; i < p; i++ {
  1115  			<-c
  1116  		}
  1117  		if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p {
  1118  			t.Fatalf("%s: val=%d want %d", name, val, n*p)
  1119  		}
  1120  	}
  1121  }
  1122  
  1123  func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
  1124  	addr := (*int32)(paddr)
  1125  	v := LoadInt32(addr)
  1126  	vlo := v & ((1 << 16) - 1)
  1127  	vhi := v >> 16
  1128  	if vlo != vhi {
  1129  		t.Fatalf("Int32: %#x != %#x", vlo, vhi)
  1130  	}
  1131  	new := v + 1 + 1<<16
  1132  	if vlo == 1e4 {
  1133  		new = 0
  1134  	}
  1135  	StoreInt32(addr, new)
  1136  }
  1137  
  1138  func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
  1139  	addr := (*uint32)(paddr)
  1140  	v := LoadUint32(addr)
  1141  	vlo := v & ((1 << 16) - 1)
  1142  	vhi := v >> 16
  1143  	if vlo != vhi {
  1144  		t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
  1145  	}
  1146  	new := v + 1 + 1<<16
  1147  	if vlo == 1e4 {
  1148  		new = 0
  1149  	}
  1150  	StoreUint32(addr, new)
  1151  }
  1152  
  1153  func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
  1154  	addr := (*int64)(paddr)
  1155  	v := LoadInt64(addr)
  1156  	vlo := v & ((1 << 32) - 1)
  1157  	vhi := v >> 32
  1158  	if vlo != vhi {
  1159  		t.Fatalf("Int64: %#x != %#x", vlo, vhi)
  1160  	}
  1161  	new := v + 1 + 1<<32
  1162  	StoreInt64(addr, new)
  1163  }
  1164  
  1165  func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
  1166  	addr := (*uint64)(paddr)
  1167  	v := LoadUint64(addr)
  1168  	vlo := v & ((1 << 32) - 1)
  1169  	vhi := v >> 32
  1170  	if vlo != vhi {
  1171  		t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
  1172  	}
  1173  	new := v + 1 + 1<<32
  1174  	StoreUint64(addr, new)
  1175  }
  1176  
  1177  func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
  1178  	addr := (*uintptr)(paddr)
  1179  	var test64 uint64 = 1 << 50
  1180  	arch32 := uintptr(test64) == 0
  1181  	v := LoadUintptr(addr)
  1182  	new := v
  1183  	if arch32 {
  1184  		vlo := v & ((1 << 16) - 1)
  1185  		vhi := v >> 16
  1186  		if vlo != vhi {
  1187  			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
  1188  		}
  1189  		new = v + 1 + 1<<16
  1190  		if vlo == 1e4 {
  1191  			new = 0
  1192  		}
  1193  	} else {
  1194  		vlo := v & ((1 << 32) - 1)
  1195  		vhi := v >> 32
  1196  		if vlo != vhi {
  1197  			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
  1198  		}
  1199  		inc := uint64(1 + 1<<32)
  1200  		new = v + uintptr(inc)
  1201  	}
  1202  	StoreUintptr(addr, new)
  1203  }
  1204  
  1205  func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
  1206  	addr := (*unsafe.Pointer)(paddr)
  1207  	var test64 uint64 = 1 << 50
  1208  	arch32 := uintptr(test64) == 0
  1209  	v := uintptr(LoadPointer(addr))
  1210  	new := v
  1211  	if arch32 {
  1212  		vlo := v & ((1 << 16) - 1)
  1213  		vhi := v >> 16
  1214  		if vlo != vhi {
  1215  			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
  1216  		}
  1217  		new = v + 1 + 1<<16
  1218  		if vlo == 1e4 {
  1219  			new = 0
  1220  		}
  1221  	} else {
  1222  		vlo := v & ((1 << 32) - 1)
  1223  		vhi := v >> 32
  1224  		if vlo != vhi {
  1225  			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
  1226  		}
  1227  		inc := uint64(1 + 1<<32)
  1228  		new = v + uintptr(inc)
  1229  	}
  1230  	StorePointer(addr, unsafe.Pointer(new))
  1231  }
  1232  
  1233  func TestHammerStoreLoad(t *testing.T) {
  1234  	var tests []func(*testing.T, unsafe.Pointer)
  1235  	tests = append(tests, hammerStoreLoadInt32, hammerStoreLoadUint32,
  1236  		hammerStoreLoadUintptr, hammerStoreLoadPointer)
  1237  	if test64err == nil {
  1238  		tests = append(tests, hammerStoreLoadInt64, hammerStoreLoadUint64)
  1239  	}
  1240  	n := int(1e6)
  1241  	if testing.Short() {
  1242  		n = int(1e4)
  1243  	}
  1244  	const procs = 8
  1245  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))
  1246  	for _, tt := range tests {
  1247  		c := make(chan int)
  1248  		var val uint64
  1249  		for p := 0; p < procs; p++ {
  1250  			go func() {
  1251  				for i := 0; i < n; i++ {
  1252  					tt(t, unsafe.Pointer(&val))
  1253  				}
  1254  				c <- 1
  1255  			}()
  1256  		}
  1257  		for p := 0; p < procs; p++ {
  1258  			<-c
  1259  		}
  1260  	}
  1261  }
  1262  
  1263  func TestStoreLoadSeqCst32(t *testing.T) {
  1264  	if runtime.NumCPU() == 1 {
  1265  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1266  	}
  1267  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1268  	N := int32(1e3)
  1269  	if testing.Short() {
  1270  		N = int32(1e2)
  1271  	}
  1272  	c := make(chan bool, 2)
  1273  	X := [2]int32{}
  1274  	ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}}
  1275  	for p := 0; p < 2; p++ {
  1276  		go func(me int) {
  1277  			he := 1 - me
  1278  			for i := int32(1); i < N; i++ {
  1279  				StoreInt32(&X[me], i)
  1280  				my := LoadInt32(&X[he])
  1281  				StoreInt32(&ack[me][i%3], my)
  1282  				for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ {
  1283  					if w%1000 == 0 {
  1284  						runtime.Gosched()
  1285  					}
  1286  				}
  1287  				his := LoadInt32(&ack[he][i%3])
  1288  				if (my != i && my != i-1) || (his != i && his != i-1) {
  1289  					t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
  1290  				}
  1291  				if my != i && his != i {
  1292  					t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
  1293  				}
  1294  				StoreInt32(&ack[me][(i-1)%3], -1)
  1295  			}
  1296  			c <- true
  1297  		}(p)
  1298  	}
  1299  	<-c
  1300  	<-c
  1301  }
  1302  
  1303  func TestStoreLoadSeqCst64(t *testing.T) {
  1304  	if runtime.NumCPU() == 1 {
  1305  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1306  	}
  1307  	if test64err != nil {
  1308  		t.Skipf("Skipping 64-bit tests: %v", test64err)
  1309  	}
  1310  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1311  	N := int64(1e3)
  1312  	if testing.Short() {
  1313  		N = int64(1e2)
  1314  	}
  1315  	c := make(chan bool, 2)
  1316  	X := [2]int64{}
  1317  	ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}}
  1318  	for p := 0; p < 2; p++ {
  1319  		go func(me int) {
  1320  			he := 1 - me
  1321  			for i := int64(1); i < N; i++ {
  1322  				StoreInt64(&X[me], i)
  1323  				my := LoadInt64(&X[he])
  1324  				StoreInt64(&ack[me][i%3], my)
  1325  				for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ {
  1326  					if w%1000 == 0 {
  1327  						runtime.Gosched()
  1328  					}
  1329  				}
  1330  				his := LoadInt64(&ack[he][i%3])
  1331  				if (my != i && my != i-1) || (his != i && his != i-1) {
  1332  					t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
  1333  				}
  1334  				if my != i && his != i {
  1335  					t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
  1336  				}
  1337  				StoreInt64(&ack[me][(i-1)%3], -1)
  1338  			}
  1339  			c <- true
  1340  		}(p)
  1341  	}
  1342  	<-c
  1343  	<-c
  1344  }
  1345  
  1346  func TestStoreLoadRelAcq32(t *testing.T) {
  1347  	if runtime.NumCPU() == 1 {
  1348  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1349  	}
  1350  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1351  	N := int32(1e3)
  1352  	if testing.Short() {
  1353  		N = int32(1e2)
  1354  	}
  1355  	c := make(chan bool, 2)
  1356  	type Data struct {
  1357  		signal int32
  1358  		pad1   [128]int8
  1359  		data1  int32
  1360  		pad2   [128]int8
  1361  		data2  float32
  1362  	}
  1363  	var X Data
  1364  	for p := int32(0); p < 2; p++ {
  1365  		go func(p int32) {
  1366  			for i := int32(1); i < N; i++ {
  1367  				if (i+p)%2 == 0 {
  1368  					X.data1 = i
  1369  					X.data2 = float32(i)
  1370  					StoreInt32(&X.signal, i)
  1371  				} else {
  1372  					for w := 1; LoadInt32(&X.signal) != i; w++ {
  1373  						if w%1000 == 0 {
  1374  							runtime.Gosched()
  1375  						}
  1376  					}
  1377  					d1 := X.data1
  1378  					d2 := X.data2
  1379  					if d1 != i || d2 != float32(i) {
  1380  						t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
  1381  					}
  1382  				}
  1383  			}
  1384  			c <- true
  1385  		}(p)
  1386  	}
  1387  	<-c
  1388  	<-c
  1389  }
  1390  
  1391  func TestStoreLoadRelAcq64(t *testing.T) {
  1392  	if runtime.NumCPU() == 1 {
  1393  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1394  	}
  1395  	if test64err != nil {
  1396  		t.Skipf("Skipping 64-bit tests: %v", test64err)
  1397  	}
  1398  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1399  	N := int64(1e3)
  1400  	if testing.Short() {
  1401  		N = int64(1e2)
  1402  	}
  1403  	c := make(chan bool, 2)
  1404  	type Data struct {
  1405  		signal int64
  1406  		pad1   [128]int8
  1407  		data1  int64
  1408  		pad2   [128]int8
  1409  		data2  float64
  1410  	}
  1411  	var X Data
  1412  	for p := int64(0); p < 2; p++ {
  1413  		go func(p int64) {
  1414  			for i := int64(1); i < N; i++ {
  1415  				if (i+p)%2 == 0 {
  1416  					X.data1 = i
  1417  					X.data2 = float64(i)
  1418  					StoreInt64(&X.signal, i)
  1419  				} else {
  1420  					for w := 1; LoadInt64(&X.signal) != i; w++ {
  1421  						if w%1000 == 0 {
  1422  							runtime.Gosched()
  1423  						}
  1424  					}
  1425  					d1 := X.data1
  1426  					d2 := X.data2
  1427  					if d1 != i || d2 != float64(i) {
  1428  						t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
  1429  					}
  1430  				}
  1431  			}
  1432  			c <- true
  1433  		}(p)
  1434  	}
  1435  	<-c
  1436  	<-c
  1437  }
  1438  
  1439  func shouldPanic(t *testing.T, name string, f func()) {
  1440  	defer func() {
  1441  		if recover() == nil {
  1442  			t.Errorf("%s did not panic", name)
  1443  		}
  1444  	}()
  1445  	f()
  1446  }
  1447  
  1448  func TestUnaligned64(t *testing.T) {
  1449  	// Unaligned 64-bit atomics on 32-bit systems are
  1450  	// a continual source of pain. Test that on 32-bit systems they crash
  1451  	// instead of failing silently.
  1452  	if unsafe.Sizeof(int(0)) != 4 {
  1453  		t.Skip("test only runs on 32-bit systems")
  1454  	}
  1455  
  1456  	x := make([]uint32, 4)
  1457  	p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
  1458  
  1459  	shouldPanic(t, "LoadUint64", func() { LoadUint64(p) })
  1460  	shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) })
  1461  	shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
  1462  	shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
  1463  }
  1464  
  1465  func TestNilDeref(t *testing.T) {
  1466  	if p := runtime.GOOS + "/" + runtime.GOARCH; p == "freebsd/arm" || p == "netbsd/arm" {
  1467  		t.Skipf("issue 7338: skipping test on %q", p)
  1468  	}
  1469  	funcs := [...]func(){
  1470  		func() { CompareAndSwapInt32(nil, 0, 0) },
  1471  		func() { CompareAndSwapInt64(nil, 0, 0) },
  1472  		func() { CompareAndSwapUint32(nil, 0, 0) },
  1473  		func() { CompareAndSwapUint64(nil, 0, 0) },
  1474  		func() { CompareAndSwapUintptr(nil, 0, 0) },
  1475  		func() { CompareAndSwapPointer(nil, nil, nil) },
  1476  		func() { SwapInt32(nil, 0) },
  1477  		func() { SwapUint32(nil, 0) },
  1478  		func() { SwapInt64(nil, 0) },
  1479  		func() { SwapUint64(nil, 0) },
  1480  		func() { SwapUintptr(nil, 0) },
  1481  		func() { SwapPointer(nil, nil) },
  1482  		func() { AddInt32(nil, 0) },
  1483  		func() { AddUint32(nil, 0) },
  1484  		func() { AddInt64(nil, 0) },
  1485  		func() { AddUint64(nil, 0) },
  1486  		func() { AddUintptr(nil, 0) },
  1487  		func() { LoadInt32(nil) },
  1488  		func() { LoadInt64(nil) },
  1489  		func() { LoadUint32(nil) },
  1490  		func() { LoadUint64(nil) },
  1491  		func() { LoadUintptr(nil) },
  1492  		func() { LoadPointer(nil) },
  1493  		func() { StoreInt32(nil, 0) },
  1494  		func() { StoreInt64(nil, 0) },
  1495  		func() { StoreUint32(nil, 0) },
  1496  		func() { StoreUint64(nil, 0) },
  1497  		func() { StoreUintptr(nil, 0) },
  1498  		func() { StorePointer(nil, nil) },
  1499  	}
  1500  	for _, f := range funcs {
  1501  		func() {
  1502  			defer func() {
  1503  				runtime.GC()
  1504  				recover()
  1505  			}()
  1506  			f()
  1507  		}()
  1508  	}
  1509  }