github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/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 << 16); 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 << 16); 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 << 16); 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 << 16); 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  	"AddInt32":              hammerAddInt32,
   763  	"AddUint32":             hammerAddUint32,
   764  	"AddUintptr":            hammerAddUintptr32,
   765  	"CompareAndSwapInt32":   hammerCompareAndSwapInt32,
   766  	"CompareAndSwapUint32":  hammerCompareAndSwapUint32,
   767  	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr32,
   768  }
   769  
   770  func init() {
   771  	var v uint64 = 1 << 50
   772  	if uintptr(v) != 0 {
   773  		// 64-bit system; clear uintptr tests
   774  		delete(hammer32, "SwapUintptr")
   775  		delete(hammer32, "SwapPointer")
   776  		delete(hammer32, "AddUintptr")
   777  		delete(hammer32, "CompareAndSwapUintptr")
   778  		delete(hammer32, "CompareAndSwapPointer")
   779  	}
   780  }
   781  
   782  func hammerSwapInt32(uaddr *uint32, count int) {
   783  	addr := (*int32)(unsafe.Pointer(uaddr))
   784  	seed := int(uintptr(unsafe.Pointer(&count)))
   785  	for i := 0; i < count; i++ {
   786  		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
   787  		old := uint32(SwapInt32(addr, int32(new)))
   788  		if old>>16 != old<<16>>16 {
   789  			panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
   790  		}
   791  	}
   792  }
   793  
   794  func hammerSwapUint32(addr *uint32, count int) {
   795  	seed := int(uintptr(unsafe.Pointer(&count)))
   796  	for i := 0; i < count; i++ {
   797  		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
   798  		old := SwapUint32(addr, new)
   799  		if old>>16 != old<<16>>16 {
   800  			panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
   801  		}
   802  	}
   803  }
   804  
   805  func hammerSwapUintptr32(uaddr *uint32, count int) {
   806  	// only safe when uintptr is 32-bit.
   807  	// not called on 64-bit systems.
   808  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   809  	seed := int(uintptr(unsafe.Pointer(&count)))
   810  	for i := 0; i < count; i++ {
   811  		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
   812  		old := SwapUintptr(addr, new)
   813  		if old>>16 != old<<16>>16 {
   814  			panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old))
   815  		}
   816  	}
   817  }
   818  
   819  func hammerAddInt32(uaddr *uint32, count int) {
   820  	addr := (*int32)(unsafe.Pointer(uaddr))
   821  	for i := 0; i < count; i++ {
   822  		AddInt32(addr, 1)
   823  	}
   824  }
   825  
   826  func hammerAddUint32(addr *uint32, count int) {
   827  	for i := 0; i < count; i++ {
   828  		AddUint32(addr, 1)
   829  	}
   830  }
   831  
   832  func hammerAddUintptr32(uaddr *uint32, count int) {
   833  	// only safe when uintptr is 32-bit.
   834  	// not called on 64-bit systems.
   835  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   836  	for i := 0; i < count; i++ {
   837  		AddUintptr(addr, 1)
   838  	}
   839  }
   840  
   841  func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
   842  	addr := (*int32)(unsafe.Pointer(uaddr))
   843  	for i := 0; i < count; i++ {
   844  		for {
   845  			v := LoadInt32(addr)
   846  			if CompareAndSwapInt32(addr, v, v+1) {
   847  				break
   848  			}
   849  		}
   850  	}
   851  }
   852  
   853  func hammerCompareAndSwapUint32(addr *uint32, count int) {
   854  	for i := 0; i < count; i++ {
   855  		for {
   856  			v := LoadUint32(addr)
   857  			if CompareAndSwapUint32(addr, v, v+1) {
   858  				break
   859  			}
   860  		}
   861  	}
   862  }
   863  
   864  func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
   865  	// only safe when uintptr is 32-bit.
   866  	// not called on 64-bit systems.
   867  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   868  	for i := 0; i < count; i++ {
   869  		for {
   870  			v := LoadUintptr(addr)
   871  			if CompareAndSwapUintptr(addr, v, v+1) {
   872  				break
   873  			}
   874  		}
   875  	}
   876  }
   877  
   878  func TestHammer32(t *testing.T) {
   879  	const p = 4
   880  	n := 100000
   881  	if testing.Short() {
   882  		n = 1000
   883  	}
   884  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
   885  
   886  	for name, testf := range hammer32 {
   887  		c := make(chan int)
   888  		var val uint32
   889  		for i := 0; i < p; i++ {
   890  			go func() {
   891  				defer func() {
   892  					if err := recover(); err != nil {
   893  						t.Error(err.(string))
   894  					}
   895  					c <- 1
   896  				}()
   897  				testf(&val, n)
   898  			}()
   899  		}
   900  		for i := 0; i < p; i++ {
   901  			<-c
   902  		}
   903  		if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p {
   904  			t.Fatalf("%s: val=%d want %d", name, val, n*p)
   905  		}
   906  	}
   907  }
   908  
   909  var hammer64 = map[string]func(*uint64, int){
   910  	"SwapInt64":             hammerSwapInt64,
   911  	"SwapUint64":            hammerSwapUint64,
   912  	"SwapUintptr":           hammerSwapUintptr64,
   913  	"AddInt64":              hammerAddInt64,
   914  	"AddUint64":             hammerAddUint64,
   915  	"AddUintptr":            hammerAddUintptr64,
   916  	"CompareAndSwapInt64":   hammerCompareAndSwapInt64,
   917  	"CompareAndSwapUint64":  hammerCompareAndSwapUint64,
   918  	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr64,
   919  }
   920  
   921  func init() {
   922  	var v uint64 = 1 << 50
   923  	if uintptr(v) == 0 {
   924  		// 32-bit system; clear uintptr tests
   925  		delete(hammer64, "SwapUintptr")
   926  		delete(hammer64, "SwapPointer")
   927  		delete(hammer64, "AddUintptr")
   928  		delete(hammer64, "CompareAndSwapUintptr")
   929  		delete(hammer64, "CompareAndSwapPointer")
   930  	}
   931  }
   932  
   933  func hammerSwapInt64(uaddr *uint64, count int) {
   934  	addr := (*int64)(unsafe.Pointer(uaddr))
   935  	seed := int(uintptr(unsafe.Pointer(&count)))
   936  	for i := 0; i < count; i++ {
   937  		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
   938  		old := uint64(SwapInt64(addr, int64(new)))
   939  		if old>>32 != old<<32>>32 {
   940  			panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
   941  		}
   942  	}
   943  }
   944  
   945  func hammerSwapUint64(addr *uint64, count int) {
   946  	seed := int(uintptr(unsafe.Pointer(&count)))
   947  	for i := 0; i < count; i++ {
   948  		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
   949  		old := SwapUint64(addr, new)
   950  		if old>>32 != old<<32>>32 {
   951  			panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
   952  		}
   953  	}
   954  }
   955  
   956  func hammerSwapUintptr64(uaddr *uint64, count int) {
   957  	// only safe when uintptr is 64-bit.
   958  	// not called on 32-bit systems.
   959  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   960  	seed := int(uintptr(unsafe.Pointer(&count)))
   961  	for i := 0; i < count; i++ {
   962  		new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
   963  		old := SwapUintptr(addr, new)
   964  		if old>>32 != old<<32>>32 {
   965  			panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
   966  		}
   967  	}
   968  }
   969  
   970  func hammerAddInt64(uaddr *uint64, count int) {
   971  	addr := (*int64)(unsafe.Pointer(uaddr))
   972  	for i := 0; i < count; i++ {
   973  		AddInt64(addr, 1)
   974  	}
   975  }
   976  
   977  func hammerAddUint64(addr *uint64, count int) {
   978  	for i := 0; i < count; i++ {
   979  		AddUint64(addr, 1)
   980  	}
   981  }
   982  
   983  func hammerAddUintptr64(uaddr *uint64, count int) {
   984  	// only safe when uintptr is 64-bit.
   985  	// not called on 32-bit systems.
   986  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   987  	for i := 0; i < count; i++ {
   988  		AddUintptr(addr, 1)
   989  	}
   990  }
   991  
   992  func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
   993  	addr := (*int64)(unsafe.Pointer(uaddr))
   994  	for i := 0; i < count; i++ {
   995  		for {
   996  			v := LoadInt64(addr)
   997  			if CompareAndSwapInt64(addr, v, v+1) {
   998  				break
   999  			}
  1000  		}
  1001  	}
  1002  }
  1003  
  1004  func hammerCompareAndSwapUint64(addr *uint64, count int) {
  1005  	for i := 0; i < count; i++ {
  1006  		for {
  1007  			v := LoadUint64(addr)
  1008  			if CompareAndSwapUint64(addr, v, v+1) {
  1009  				break
  1010  			}
  1011  		}
  1012  	}
  1013  }
  1014  
  1015  func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
  1016  	// only safe when uintptr is 64-bit.
  1017  	// not called on 32-bit systems.
  1018  	addr := (*uintptr)(unsafe.Pointer(uaddr))
  1019  	for i := 0; i < count; i++ {
  1020  		for {
  1021  			v := LoadUintptr(addr)
  1022  			if CompareAndSwapUintptr(addr, v, v+1) {
  1023  				break
  1024  			}
  1025  		}
  1026  	}
  1027  }
  1028  
  1029  func TestHammer64(t *testing.T) {
  1030  	if test64err != nil {
  1031  		t.Skipf("Skipping 64-bit tests: %v", test64err)
  1032  	}
  1033  	const p = 4
  1034  	n := 100000
  1035  	if testing.Short() {
  1036  		n = 1000
  1037  	}
  1038  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
  1039  
  1040  	for name, testf := range hammer64 {
  1041  		c := make(chan int)
  1042  		var val uint64
  1043  		for i := 0; i < p; i++ {
  1044  			go func() {
  1045  				defer func() {
  1046  					if err := recover(); err != nil {
  1047  						t.Error(err.(string))
  1048  					}
  1049  					c <- 1
  1050  				}()
  1051  				testf(&val, n)
  1052  			}()
  1053  		}
  1054  		for i := 0; i < p; i++ {
  1055  			<-c
  1056  		}
  1057  		if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p {
  1058  			t.Fatalf("%s: val=%d want %d", name, val, n*p)
  1059  		}
  1060  	}
  1061  }
  1062  
  1063  func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
  1064  	addr := (*int32)(paddr)
  1065  	v := LoadInt32(addr)
  1066  	vlo := v & ((1 << 16) - 1)
  1067  	vhi := v >> 16
  1068  	if vlo != vhi {
  1069  		t.Fatalf("Int32: %#x != %#x", vlo, vhi)
  1070  	}
  1071  	new := v + 1 + 1<<16
  1072  	if vlo == 1e4 {
  1073  		new = 0
  1074  	}
  1075  	StoreInt32(addr, new)
  1076  }
  1077  
  1078  func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
  1079  	addr := (*uint32)(paddr)
  1080  	v := LoadUint32(addr)
  1081  	vlo := v & ((1 << 16) - 1)
  1082  	vhi := v >> 16
  1083  	if vlo != vhi {
  1084  		t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
  1085  	}
  1086  	new := v + 1 + 1<<16
  1087  	if vlo == 1e4 {
  1088  		new = 0
  1089  	}
  1090  	StoreUint32(addr, new)
  1091  }
  1092  
  1093  func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
  1094  	addr := (*int64)(paddr)
  1095  	v := LoadInt64(addr)
  1096  	vlo := v & ((1 << 32) - 1)
  1097  	vhi := v >> 32
  1098  	if vlo != vhi {
  1099  		t.Fatalf("Int64: %#x != %#x", vlo, vhi)
  1100  	}
  1101  	new := v + 1 + 1<<32
  1102  	StoreInt64(addr, new)
  1103  }
  1104  
  1105  func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
  1106  	addr := (*uint64)(paddr)
  1107  	v := LoadUint64(addr)
  1108  	vlo := v & ((1 << 32) - 1)
  1109  	vhi := v >> 32
  1110  	if vlo != vhi {
  1111  		t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
  1112  	}
  1113  	new := v + 1 + 1<<32
  1114  	StoreUint64(addr, new)
  1115  }
  1116  
  1117  func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
  1118  	addr := (*uintptr)(paddr)
  1119  	var test64 uint64 = 1 << 50
  1120  	arch32 := uintptr(test64) == 0
  1121  	v := LoadUintptr(addr)
  1122  	new := v
  1123  	if arch32 {
  1124  		vlo := v & ((1 << 16) - 1)
  1125  		vhi := v >> 16
  1126  		if vlo != vhi {
  1127  			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
  1128  		}
  1129  		new = v + 1 + 1<<16
  1130  		if vlo == 1e4 {
  1131  			new = 0
  1132  		}
  1133  	} else {
  1134  		vlo := v & ((1 << 32) - 1)
  1135  		vhi := v >> 32
  1136  		if vlo != vhi {
  1137  			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
  1138  		}
  1139  		inc := uint64(1 + 1<<32)
  1140  		new = v + uintptr(inc)
  1141  	}
  1142  	StoreUintptr(addr, new)
  1143  }
  1144  
  1145  func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
  1146  	addr := (*unsafe.Pointer)(paddr)
  1147  	var test64 uint64 = 1 << 50
  1148  	arch32 := uintptr(test64) == 0
  1149  	v := uintptr(LoadPointer(addr))
  1150  	new := v
  1151  	if arch32 {
  1152  		vlo := v & ((1 << 16) - 1)
  1153  		vhi := v >> 16
  1154  		if vlo != vhi {
  1155  			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
  1156  		}
  1157  		new = v + 1 + 1<<16
  1158  		if vlo == 1e4 {
  1159  			new = 0
  1160  		}
  1161  	} else {
  1162  		vlo := v & ((1 << 32) - 1)
  1163  		vhi := v >> 32
  1164  		if vlo != vhi {
  1165  			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
  1166  		}
  1167  		inc := uint64(1 + 1<<32)
  1168  		new = v + uintptr(inc)
  1169  	}
  1170  	StorePointer(addr, unsafe.Pointer(new))
  1171  }
  1172  
  1173  func TestHammerStoreLoad(t *testing.T) {
  1174  	var tests []func(*testing.T, unsafe.Pointer)
  1175  	tests = append(tests, hammerStoreLoadInt32, hammerStoreLoadUint32,
  1176  		hammerStoreLoadUintptr, hammerStoreLoadPointer)
  1177  	if test64err == nil {
  1178  		tests = append(tests, hammerStoreLoadInt64, hammerStoreLoadUint64)
  1179  	}
  1180  	n := int(1e6)
  1181  	if testing.Short() {
  1182  		n = int(1e4)
  1183  	}
  1184  	const procs = 8
  1185  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))
  1186  	for _, tt := range tests {
  1187  		c := make(chan int)
  1188  		var val uint64
  1189  		for p := 0; p < procs; p++ {
  1190  			go func() {
  1191  				for i := 0; i < n; i++ {
  1192  					tt(t, unsafe.Pointer(&val))
  1193  				}
  1194  				c <- 1
  1195  			}()
  1196  		}
  1197  		for p := 0; p < procs; p++ {
  1198  			<-c
  1199  		}
  1200  	}
  1201  }
  1202  
  1203  func TestStoreLoadSeqCst32(t *testing.T) {
  1204  	if runtime.NumCPU() == 1 {
  1205  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1206  	}
  1207  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1208  	N := int32(1e3)
  1209  	if testing.Short() {
  1210  		N = int32(1e2)
  1211  	}
  1212  	c := make(chan bool, 2)
  1213  	X := [2]int32{}
  1214  	ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}}
  1215  	for p := 0; p < 2; p++ {
  1216  		go func(me int) {
  1217  			he := 1 - me
  1218  			for i := int32(1); i < N; i++ {
  1219  				StoreInt32(&X[me], i)
  1220  				my := LoadInt32(&X[he])
  1221  				StoreInt32(&ack[me][i%3], my)
  1222  				for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ {
  1223  					if w%1000 == 0 {
  1224  						runtime.Gosched()
  1225  					}
  1226  				}
  1227  				his := LoadInt32(&ack[he][i%3])
  1228  				if (my != i && my != i-1) || (his != i && his != i-1) {
  1229  					t.Errorf("invalid values: %d/%d (%d)", my, his, i)
  1230  					break
  1231  				}
  1232  				if my != i && his != i {
  1233  					t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
  1234  					break
  1235  				}
  1236  				StoreInt32(&ack[me][(i-1)%3], -1)
  1237  			}
  1238  			c <- true
  1239  		}(p)
  1240  	}
  1241  	<-c
  1242  	<-c
  1243  }
  1244  
  1245  func TestStoreLoadSeqCst64(t *testing.T) {
  1246  	if runtime.NumCPU() == 1 {
  1247  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1248  	}
  1249  	if test64err != nil {
  1250  		t.Skipf("Skipping 64-bit tests: %v", test64err)
  1251  	}
  1252  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1253  	N := int64(1e3)
  1254  	if testing.Short() {
  1255  		N = int64(1e2)
  1256  	}
  1257  	c := make(chan bool, 2)
  1258  	X := [2]int64{}
  1259  	ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}}
  1260  	for p := 0; p < 2; p++ {
  1261  		go func(me int) {
  1262  			he := 1 - me
  1263  			for i := int64(1); i < N; i++ {
  1264  				StoreInt64(&X[me], i)
  1265  				my := LoadInt64(&X[he])
  1266  				StoreInt64(&ack[me][i%3], my)
  1267  				for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ {
  1268  					if w%1000 == 0 {
  1269  						runtime.Gosched()
  1270  					}
  1271  				}
  1272  				his := LoadInt64(&ack[he][i%3])
  1273  				if (my != i && my != i-1) || (his != i && his != i-1) {
  1274  					t.Errorf("invalid values: %d/%d (%d)", my, his, i)
  1275  					break
  1276  				}
  1277  				if my != i && his != i {
  1278  					t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
  1279  					break
  1280  				}
  1281  				StoreInt64(&ack[me][(i-1)%3], -1)
  1282  			}
  1283  			c <- true
  1284  		}(p)
  1285  	}
  1286  	<-c
  1287  	<-c
  1288  }
  1289  
  1290  func TestStoreLoadRelAcq32(t *testing.T) {
  1291  	if runtime.NumCPU() == 1 {
  1292  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1293  	}
  1294  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1295  	N := int32(1e3)
  1296  	if testing.Short() {
  1297  		N = int32(1e2)
  1298  	}
  1299  	c := make(chan bool, 2)
  1300  	type Data struct {
  1301  		signal int32
  1302  		pad1   [128]int8
  1303  		data1  int32
  1304  		pad2   [128]int8
  1305  		data2  float32
  1306  	}
  1307  	var X Data
  1308  	for p := int32(0); p < 2; p++ {
  1309  		go func(p int32) {
  1310  			for i := int32(1); i < N; i++ {
  1311  				if (i+p)%2 == 0 {
  1312  					X.data1 = i
  1313  					X.data2 = float32(i)
  1314  					StoreInt32(&X.signal, i)
  1315  				} else {
  1316  					for w := 1; LoadInt32(&X.signal) != i; w++ {
  1317  						if w%1000 == 0 {
  1318  							runtime.Gosched()
  1319  						}
  1320  					}
  1321  					d1 := X.data1
  1322  					d2 := X.data2
  1323  					if d1 != i || d2 != float32(i) {
  1324  						t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
  1325  						break
  1326  					}
  1327  				}
  1328  			}
  1329  			c <- true
  1330  		}(p)
  1331  	}
  1332  	<-c
  1333  	<-c
  1334  }
  1335  
  1336  func TestStoreLoadRelAcq64(t *testing.T) {
  1337  	if runtime.NumCPU() == 1 {
  1338  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1339  	}
  1340  	if test64err != nil {
  1341  		t.Skipf("Skipping 64-bit tests: %v", test64err)
  1342  	}
  1343  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1344  	N := int64(1e3)
  1345  	if testing.Short() {
  1346  		N = int64(1e2)
  1347  	}
  1348  	c := make(chan bool, 2)
  1349  	type Data struct {
  1350  		signal int64
  1351  		pad1   [128]int8
  1352  		data1  int64
  1353  		pad2   [128]int8
  1354  		data2  float64
  1355  	}
  1356  	var X Data
  1357  	for p := int64(0); p < 2; p++ {
  1358  		go func(p int64) {
  1359  			for i := int64(1); i < N; i++ {
  1360  				if (i+p)%2 == 0 {
  1361  					X.data1 = i
  1362  					X.data2 = float64(i)
  1363  					StoreInt64(&X.signal, i)
  1364  				} else {
  1365  					for w := 1; LoadInt64(&X.signal) != i; w++ {
  1366  						if w%1000 == 0 {
  1367  							runtime.Gosched()
  1368  						}
  1369  					}
  1370  					d1 := X.data1
  1371  					d2 := X.data2
  1372  					if d1 != i || d2 != float64(i) {
  1373  						t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
  1374  						break
  1375  					}
  1376  				}
  1377  			}
  1378  			c <- true
  1379  		}(p)
  1380  	}
  1381  	<-c
  1382  	<-c
  1383  }
  1384  
  1385  func shouldPanic(t *testing.T, name string, f func()) {
  1386  	defer func() {
  1387  		if recover() == nil {
  1388  			t.Errorf("%s did not panic", name)
  1389  		}
  1390  	}()
  1391  	f()
  1392  }
  1393  
  1394  func TestUnaligned64(t *testing.T) {
  1395  	// Unaligned 64-bit atomics on 32-bit systems are
  1396  	// a continual source of pain. Test that on 32-bit systems they crash
  1397  	// instead of failing silently.
  1398  
  1399  	switch runtime.GOARCH {
  1400  	default:
  1401  		if unsafe.Sizeof(int(0)) != 4 {
  1402  			t.Skip("test only runs on 32-bit systems")
  1403  		}
  1404  	case "amd64p32":
  1405  		// amd64p32 can handle unaligned atomics.
  1406  		t.Skipf("test not needed on %v", runtime.GOARCH)
  1407  	}
  1408  
  1409  	x := make([]uint32, 4)
  1410  	p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
  1411  
  1412  	shouldPanic(t, "LoadUint64", func() { LoadUint64(p) })
  1413  	shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) })
  1414  	shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
  1415  	shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
  1416  }
  1417  
  1418  func TestNilDeref(t *testing.T) {
  1419  	funcs := [...]func(){
  1420  		func() { CompareAndSwapInt32(nil, 0, 0) },
  1421  		func() { CompareAndSwapInt64(nil, 0, 0) },
  1422  		func() { CompareAndSwapUint32(nil, 0, 0) },
  1423  		func() { CompareAndSwapUint64(nil, 0, 0) },
  1424  		func() { CompareAndSwapUintptr(nil, 0, 0) },
  1425  		func() { CompareAndSwapPointer(nil, nil, nil) },
  1426  		func() { SwapInt32(nil, 0) },
  1427  		func() { SwapUint32(nil, 0) },
  1428  		func() { SwapInt64(nil, 0) },
  1429  		func() { SwapUint64(nil, 0) },
  1430  		func() { SwapUintptr(nil, 0) },
  1431  		func() { SwapPointer(nil, nil) },
  1432  		func() { AddInt32(nil, 0) },
  1433  		func() { AddUint32(nil, 0) },
  1434  		func() { AddInt64(nil, 0) },
  1435  		func() { AddUint64(nil, 0) },
  1436  		func() { AddUintptr(nil, 0) },
  1437  		func() { LoadInt32(nil) },
  1438  		func() { LoadInt64(nil) },
  1439  		func() { LoadUint32(nil) },
  1440  		func() { LoadUint64(nil) },
  1441  		func() { LoadUintptr(nil) },
  1442  		func() { LoadPointer(nil) },
  1443  		func() { StoreInt32(nil, 0) },
  1444  		func() { StoreInt64(nil, 0) },
  1445  		func() { StoreUint32(nil, 0) },
  1446  		func() { StoreUint64(nil, 0) },
  1447  		func() { StoreUintptr(nil, 0) },
  1448  		func() { StorePointer(nil, nil) },
  1449  	}
  1450  	for _, f := range funcs {
  1451  		func() {
  1452  			defer func() {
  1453  				runtime.GC()
  1454  				recover()
  1455  			}()
  1456  			f()
  1457  		}()
  1458  	}
  1459  }