github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/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) {
   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 !CompareAndSwapUint64(&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 CompareAndSwapUint64(&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 TestCompareAndSwapUintptr(t *testing.T) {
   415  	var x struct {
   416  		before uintptr
   417  		i      uintptr
   418  		after  uintptr
   419  	}
   420  	var m uint64 = magic64
   421  	magicptr := uintptr(m)
   422  	x.before = magicptr
   423  	x.after = magicptr
   424  	for val := uintptr(1); val+val > val; val += val {
   425  		x.i = val
   426  		if !CompareAndSwapUintptr(&x.i, val, val+1) {
   427  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   428  		}
   429  		if x.i != val+1 {
   430  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   431  		}
   432  		x.i = val + 1
   433  		if CompareAndSwapUintptr(&x.i, val, val+2) {
   434  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   435  		}
   436  		if x.i != val+1 {
   437  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   438  		}
   439  	}
   440  	if x.before != magicptr || x.after != magicptr {
   441  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   442  	}
   443  }
   444  
   445  func TestCompareAndSwapPointer(t *testing.T) {
   446  	var x struct {
   447  		before uintptr
   448  		i      unsafe.Pointer
   449  		after  uintptr
   450  	}
   451  	var m uint64 = magic64
   452  	magicptr := uintptr(m)
   453  	x.before = magicptr
   454  	x.after = magicptr
   455  	for val := uintptr(1); val+val > val; val += val {
   456  		x.i = unsafe.Pointer(val)
   457  		if !CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+1)) {
   458  			t.Fatalf("should have swapped %#x %#x", val, val+1)
   459  		}
   460  		if x.i != unsafe.Pointer(val+1) {
   461  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   462  		}
   463  		x.i = unsafe.Pointer(val + 1)
   464  		if CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+2)) {
   465  			t.Fatalf("should not have swapped %#x %#x", val, val+2)
   466  		}
   467  		if x.i != unsafe.Pointer(val+1) {
   468  			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
   469  		}
   470  	}
   471  	if x.before != magicptr || x.after != magicptr {
   472  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   473  	}
   474  }
   475  
   476  func TestLoadInt32(t *testing.T) {
   477  	var x struct {
   478  		before int32
   479  		i      int32
   480  		after  int32
   481  	}
   482  	x.before = magic32
   483  	x.after = magic32
   484  	for delta := int32(1); delta+delta > delta; delta += delta {
   485  		k := LoadInt32(&x.i)
   486  		if k != x.i {
   487  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   488  		}
   489  		x.i += delta
   490  	}
   491  	if x.before != magic32 || x.after != magic32 {
   492  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   493  	}
   494  }
   495  
   496  func TestLoadUint32(t *testing.T) {
   497  	var x struct {
   498  		before uint32
   499  		i      uint32
   500  		after  uint32
   501  	}
   502  	x.before = magic32
   503  	x.after = magic32
   504  	for delta := uint32(1); delta+delta > delta; delta += delta {
   505  		k := LoadUint32(&x.i)
   506  		if k != x.i {
   507  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   508  		}
   509  		x.i += delta
   510  	}
   511  	if x.before != magic32 || x.after != magic32 {
   512  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   513  	}
   514  }
   515  
   516  func TestLoadInt64(t *testing.T) {
   517  	if test64err != nil {
   518  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   519  	}
   520  	var x struct {
   521  		before int64
   522  		i      int64
   523  		after  int64
   524  	}
   525  	x.before = magic64
   526  	x.after = magic64
   527  	for delta := int64(1); delta+delta > delta; delta += delta {
   528  		k := LoadInt64(&x.i)
   529  		if k != x.i {
   530  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   531  		}
   532  		x.i += delta
   533  	}
   534  	if x.before != magic64 || x.after != magic64 {
   535  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   536  	}
   537  }
   538  
   539  func TestLoadUint64(t *testing.T) {
   540  	if test64err != nil {
   541  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   542  	}
   543  	var x struct {
   544  		before uint64
   545  		i      uint64
   546  		after  uint64
   547  	}
   548  	x.before = magic64
   549  	x.after = magic64
   550  	for delta := uint64(1); delta+delta > delta; delta += delta {
   551  		k := LoadUint64(&x.i)
   552  		if k != x.i {
   553  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   554  		}
   555  		x.i += delta
   556  	}
   557  	if x.before != magic64 || x.after != magic64 {
   558  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   559  	}
   560  }
   561  
   562  func TestLoadUintptr(t *testing.T) {
   563  	var x struct {
   564  		before uintptr
   565  		i      uintptr
   566  		after  uintptr
   567  	}
   568  	var m uint64 = magic64
   569  	magicptr := uintptr(m)
   570  	x.before = magicptr
   571  	x.after = magicptr
   572  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   573  		k := LoadUintptr(&x.i)
   574  		if k != x.i {
   575  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   576  		}
   577  		x.i += delta
   578  	}
   579  	if x.before != magicptr || x.after != magicptr {
   580  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   581  	}
   582  }
   583  
   584  func TestLoadPointer(t *testing.T) {
   585  	var x struct {
   586  		before uintptr
   587  		i      unsafe.Pointer
   588  		after  uintptr
   589  	}
   590  	var m uint64 = magic64
   591  	magicptr := uintptr(m)
   592  	x.before = magicptr
   593  	x.after = magicptr
   594  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   595  		k := LoadPointer(&x.i)
   596  		if k != x.i {
   597  			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
   598  		}
   599  		x.i = unsafe.Pointer(uintptr(x.i) + delta)
   600  	}
   601  	if x.before != magicptr || x.after != magicptr {
   602  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   603  	}
   604  }
   605  
   606  func TestStoreInt32(t *testing.T) {
   607  	var x struct {
   608  		before int32
   609  		i      int32
   610  		after  int32
   611  	}
   612  	x.before = magic32
   613  	x.after = magic32
   614  	v := int32(0)
   615  	for delta := int32(1); delta+delta > delta; delta += delta {
   616  		StoreInt32(&x.i, v)
   617  		if x.i != v {
   618  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   619  		}
   620  		v += delta
   621  	}
   622  	if x.before != magic32 || x.after != magic32 {
   623  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   624  	}
   625  }
   626  
   627  func TestStoreUint32(t *testing.T) {
   628  	var x struct {
   629  		before uint32
   630  		i      uint32
   631  		after  uint32
   632  	}
   633  	x.before = magic32
   634  	x.after = magic32
   635  	v := uint32(0)
   636  	for delta := uint32(1); delta+delta > delta; delta += delta {
   637  		StoreUint32(&x.i, v)
   638  		if x.i != v {
   639  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   640  		}
   641  		v += delta
   642  	}
   643  	if x.before != magic32 || x.after != magic32 {
   644  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
   645  	}
   646  }
   647  
   648  func TestStoreInt64(t *testing.T) {
   649  	if test64err != nil {
   650  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   651  	}
   652  	var x struct {
   653  		before int64
   654  		i      int64
   655  		after  int64
   656  	}
   657  	x.before = magic64
   658  	x.after = magic64
   659  	v := int64(0)
   660  	for delta := int64(1); delta+delta > delta; delta += delta {
   661  		StoreInt64(&x.i, v)
   662  		if x.i != v {
   663  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   664  		}
   665  		v += delta
   666  	}
   667  	if x.before != magic64 || x.after != magic64 {
   668  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   669  	}
   670  }
   671  
   672  func TestStoreUint64(t *testing.T) {
   673  	if test64err != nil {
   674  		t.Skipf("Skipping 64-bit tests: %v", test64err)
   675  	}
   676  	var x struct {
   677  		before uint64
   678  		i      uint64
   679  		after  uint64
   680  	}
   681  	x.before = magic64
   682  	x.after = magic64
   683  	v := uint64(0)
   684  	for delta := uint64(1); delta+delta > delta; delta += delta {
   685  		StoreUint64(&x.i, v)
   686  		if x.i != v {
   687  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   688  		}
   689  		v += delta
   690  	}
   691  	if x.before != magic64 || x.after != magic64 {
   692  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
   693  	}
   694  }
   695  
   696  func TestStoreUintptr(t *testing.T) {
   697  	var x struct {
   698  		before uintptr
   699  		i      uintptr
   700  		after  uintptr
   701  	}
   702  	var m uint64 = magic64
   703  	magicptr := uintptr(m)
   704  	x.before = magicptr
   705  	x.after = magicptr
   706  	v := uintptr(0)
   707  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   708  		StoreUintptr(&x.i, v)
   709  		if x.i != v {
   710  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   711  		}
   712  		v += delta
   713  	}
   714  	if x.before != magicptr || x.after != magicptr {
   715  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   716  	}
   717  }
   718  
   719  func TestStorePointer(t *testing.T) {
   720  	var x struct {
   721  		before uintptr
   722  		i      unsafe.Pointer
   723  		after  uintptr
   724  	}
   725  	var m uint64 = magic64
   726  	magicptr := uintptr(m)
   727  	x.before = magicptr
   728  	x.after = magicptr
   729  	v := unsafe.Pointer(uintptr(0))
   730  	for delta := uintptr(1); delta+delta > delta; delta += delta {
   731  		StorePointer(&x.i, unsafe.Pointer(v))
   732  		if x.i != v {
   733  			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
   734  		}
   735  		v = unsafe.Pointer(uintptr(v) + delta)
   736  	}
   737  	if x.before != magicptr || x.after != magicptr {
   738  		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
   739  	}
   740  }
   741  
   742  // Tests of correct behavior, with contention.
   743  // (Is the function atomic?)
   744  //
   745  // For each function, we write a "hammer" function that repeatedly
   746  // uses the atomic operation to add 1 to a value.  After running
   747  // multiple hammers in parallel, check that we end with the correct
   748  // total.
   749  // Swap can't add 1, so it uses a different scheme.
   750  // The functions repeatedly generate a pseudo-random number such that
   751  // low bits are equal to high bits, swap, check that the old value
   752  // has low and high bits equal.
   753  
   754  var hammer32 = map[string]func(*uint32, int){
   755  	"SwapInt32":             hammerSwapInt32,
   756  	"SwapUint32":            hammerSwapUint32,
   757  	"SwapUintptr":           hammerSwapUintptr32,
   758  	"SwapPointer":           hammerSwapPointer32,
   759  	"AddInt32":              hammerAddInt32,
   760  	"AddUint32":             hammerAddUint32,
   761  	"AddUintptr":            hammerAddUintptr32,
   762  	"CompareAndSwapInt32":   hammerCompareAndSwapInt32,
   763  	"CompareAndSwapUint32":  hammerCompareAndSwapUint32,
   764  	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr32,
   765  	"CompareAndSwapPointer": hammerCompareAndSwapPointer32,
   766  }
   767  
   768  func init() {
   769  	var v uint64 = 1 << 50
   770  	if uintptr(v) != 0 {
   771  		// 64-bit system; clear uintptr tests
   772  		delete(hammer32, "SwapUintptr")
   773  		delete(hammer32, "SwapPointer")
   774  		delete(hammer32, "AddUintptr")
   775  		delete(hammer32, "CompareAndSwapUintptr")
   776  		delete(hammer32, "CompareAndSwapPointer")
   777  	}
   778  }
   779  
   780  func hammerSwapInt32(uaddr *uint32, count int) {
   781  	addr := (*int32)(unsafe.Pointer(uaddr))
   782  	seed := int(uintptr(unsafe.Pointer(&count)))
   783  	for i := 0; i < count; i++ {
   784  		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
   785  		old := uint32(SwapInt32(addr, int32(new)))
   786  		if old>>16 != old<<16>>16 {
   787  			panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
   788  		}
   789  	}
   790  }
   791  
   792  func hammerSwapUint32(addr *uint32, count int) {
   793  	seed := int(uintptr(unsafe.Pointer(&count)))
   794  	for i := 0; i < count; i++ {
   795  		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
   796  		old := SwapUint32(addr, new)
   797  		if old>>16 != old<<16>>16 {
   798  			panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
   799  		}
   800  	}
   801  }
   802  
   803  func hammerSwapUintptr32(uaddr *uint32, count int) {
   804  	// only safe when uintptr is 32-bit.
   805  	// not called on 64-bit systems.
   806  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   807  	seed := int(uintptr(unsafe.Pointer(&count)))
   808  	for i := 0; i < count; i++ {
   809  		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
   810  		old := SwapUintptr(addr, new)
   811  		if old>>16 != old<<16>>16 {
   812  			panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
   813  		}
   814  	}
   815  }
   816  
   817  func hammerSwapPointer32(uaddr *uint32, count int) {
   818  	// only safe when uintptr is 32-bit.
   819  	// not called on 64-bit systems.
   820  	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
   821  	seed := int(uintptr(unsafe.Pointer(&count)))
   822  	for i := 0; i < count; i++ {
   823  		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
   824  		old := uintptr(SwapPointer(addr, unsafe.Pointer(new)))
   825  		if old>>16 != old<<16>>16 {
   826  			panic(fmt.Sprintf("SwapPointer is not atomic: %v", old))
   827  		}
   828  	}
   829  }
   830  
   831  func hammerAddInt32(uaddr *uint32, count int) {
   832  	addr := (*int32)(unsafe.Pointer(uaddr))
   833  	for i := 0; i < count; i++ {
   834  		AddInt32(addr, 1)
   835  	}
   836  }
   837  
   838  func hammerAddUint32(addr *uint32, count int) {
   839  	for i := 0; i < count; i++ {
   840  		AddUint32(addr, 1)
   841  	}
   842  }
   843  
   844  func hammerAddUintptr32(uaddr *uint32, count int) {
   845  	// only safe when uintptr is 32-bit.
   846  	// not called on 64-bit systems.
   847  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   848  	for i := 0; i < count; i++ {
   849  		AddUintptr(addr, 1)
   850  	}
   851  }
   852  
   853  func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
   854  	addr := (*int32)(unsafe.Pointer(uaddr))
   855  	for i := 0; i < count; i++ {
   856  		for {
   857  			v := *addr
   858  			if CompareAndSwapInt32(addr, v, v+1) {
   859  				break
   860  			}
   861  		}
   862  	}
   863  }
   864  
   865  func hammerCompareAndSwapUint32(addr *uint32, count int) {
   866  	for i := 0; i < count; i++ {
   867  		for {
   868  			v := *addr
   869  			if CompareAndSwapUint32(addr, v, v+1) {
   870  				break
   871  			}
   872  		}
   873  	}
   874  }
   875  
   876  func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
   877  	// only safe when uintptr is 32-bit.
   878  	// not called on 64-bit systems.
   879  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   880  	for i := 0; i < count; i++ {
   881  		for {
   882  			v := *addr
   883  			if CompareAndSwapUintptr(addr, v, v+1) {
   884  				break
   885  			}
   886  		}
   887  	}
   888  }
   889  
   890  func hammerCompareAndSwapPointer32(uaddr *uint32, count int) {
   891  	// only safe when uintptr is 32-bit.
   892  	// not called on 64-bit systems.
   893  	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
   894  	for i := 0; i < count; i++ {
   895  		for {
   896  			v := *addr
   897  			if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
   898  				break
   899  			}
   900  		}
   901  	}
   902  }
   903  
   904  func TestHammer32(t *testing.T) {
   905  	const p = 4
   906  	n := 100000
   907  	if testing.Short() {
   908  		n = 1000
   909  	}
   910  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
   911  
   912  	for name, testf := range hammer32 {
   913  		c := make(chan int)
   914  		var val uint32
   915  		for i := 0; i < p; i++ {
   916  			go func() {
   917  				defer func() {
   918  					if err := recover(); err != nil {
   919  						t.Error(err.(string))
   920  					}
   921  					c <- 1
   922  				}()
   923  				testf(&val, n)
   924  			}()
   925  		}
   926  		for i := 0; i < p; i++ {
   927  			<-c
   928  		}
   929  		if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p {
   930  			t.Fatalf("%s: val=%d want %d", name, val, n*p)
   931  		}
   932  	}
   933  }
   934  
   935  var hammer64 = map[string]func(*uint64, int){
   936  	"SwapInt64":             hammerSwapInt64,
   937  	"SwapUint64":            hammerSwapUint64,
   938  	"SwapUintptr":           hammerSwapUintptr64,
   939  	"SwapPointer":           hammerSwapPointer64,
   940  	"AddInt64":              hammerAddInt64,
   941  	"AddUint64":             hammerAddUint64,
   942  	"AddUintptr":            hammerAddUintptr64,
   943  	"CompareAndSwapInt64":   hammerCompareAndSwapInt64,
   944  	"CompareAndSwapUint64":  hammerCompareAndSwapUint64,
   945  	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr64,
   946  	"CompareAndSwapPointer": hammerCompareAndSwapPointer64,
   947  }
   948  
   949  func init() {
   950  	var v uint64 = 1 << 50
   951  	if uintptr(v) == 0 {
   952  		// 32-bit system; clear uintptr tests
   953  		delete(hammer64, "SwapUintptr")
   954  		delete(hammer64, "SwapPointer")
   955  		delete(hammer64, "AddUintptr")
   956  		delete(hammer64, "CompareAndSwapUintptr")
   957  		delete(hammer64, "CompareAndSwapPointer")
   958  	}
   959  }
   960  
   961  func hammerSwapInt64(uaddr *uint64, count int) {
   962  	addr := (*int64)(unsafe.Pointer(uaddr))
   963  	seed := int(uintptr(unsafe.Pointer(&count)))
   964  	for i := 0; i < count; i++ {
   965  		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
   966  		old := uint64(SwapInt64(addr, int64(new)))
   967  		if old>>32 != old<<32>>32 {
   968  			panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
   969  		}
   970  	}
   971  }
   972  
   973  func hammerSwapUint64(addr *uint64, count int) {
   974  	seed := int(uintptr(unsafe.Pointer(&count)))
   975  	for i := 0; i < count; i++ {
   976  		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
   977  		old := SwapUint64(addr, new)
   978  		if old>>32 != old<<32>>32 {
   979  			panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
   980  		}
   981  	}
   982  }
   983  
   984  func hammerSwapUintptr64(uaddr *uint64, count int) {
   985  	// only safe when uintptr is 64-bit.
   986  	// not called on 32-bit systems.
   987  	addr := (*uintptr)(unsafe.Pointer(uaddr))
   988  	seed := int(uintptr(unsafe.Pointer(&count)))
   989  	for i := 0; i < count; i++ {
   990  		new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
   991  		old := SwapUintptr(addr, new)
   992  		if old>>32 != old<<32>>32 {
   993  			panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
   994  		}
   995  	}
   996  }
   997  
   998  func hammerSwapPointer64(uaddr *uint64, count int) {
   999  	// only safe when uintptr is 64-bit.
  1000  	// not called on 32-bit systems.
  1001  	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
  1002  	seed := int(uintptr(unsafe.Pointer(&count)))
  1003  	for i := 0; i < count; i++ {
  1004  		new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
  1005  		old := uintptr(SwapPointer(addr, unsafe.Pointer(new)))
  1006  		if old>>32 != old<<32>>32 {
  1007  			panic(fmt.Sprintf("SwapPointer is not atomic: %v", old))
  1008  		}
  1009  	}
  1010  }
  1011  
  1012  func hammerAddInt64(uaddr *uint64, count int) {
  1013  	addr := (*int64)(unsafe.Pointer(uaddr))
  1014  	for i := 0; i < count; i++ {
  1015  		AddInt64(addr, 1)
  1016  	}
  1017  }
  1018  
  1019  func hammerAddUint64(addr *uint64, count int) {
  1020  	for i := 0; i < count; i++ {
  1021  		AddUint64(addr, 1)
  1022  	}
  1023  }
  1024  
  1025  func hammerAddUintptr64(uaddr *uint64, count int) {
  1026  	// only safe when uintptr is 64-bit.
  1027  	// not called on 32-bit systems.
  1028  	addr := (*uintptr)(unsafe.Pointer(uaddr))
  1029  	for i := 0; i < count; i++ {
  1030  		AddUintptr(addr, 1)
  1031  	}
  1032  }
  1033  
  1034  func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
  1035  	addr := (*int64)(unsafe.Pointer(uaddr))
  1036  	for i := 0; i < count; i++ {
  1037  		for {
  1038  			v := *addr
  1039  			if CompareAndSwapInt64(addr, v, v+1) {
  1040  				break
  1041  			}
  1042  		}
  1043  	}
  1044  }
  1045  
  1046  func hammerCompareAndSwapUint64(addr *uint64, count int) {
  1047  	for i := 0; i < count; i++ {
  1048  		for {
  1049  			v := *addr
  1050  			if CompareAndSwapUint64(addr, v, v+1) {
  1051  				break
  1052  			}
  1053  		}
  1054  	}
  1055  }
  1056  
  1057  func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
  1058  	// only safe when uintptr is 64-bit.
  1059  	// not called on 32-bit systems.
  1060  	addr := (*uintptr)(unsafe.Pointer(uaddr))
  1061  	for i := 0; i < count; i++ {
  1062  		for {
  1063  			v := *addr
  1064  			if CompareAndSwapUintptr(addr, v, v+1) {
  1065  				break
  1066  			}
  1067  		}
  1068  	}
  1069  }
  1070  
  1071  func hammerCompareAndSwapPointer64(uaddr *uint64, count int) {
  1072  	// only safe when uintptr is 64-bit.
  1073  	// not called on 32-bit systems.
  1074  	addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
  1075  	for i := 0; i < count; i++ {
  1076  		for {
  1077  			v := *addr
  1078  			if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
  1079  				break
  1080  			}
  1081  		}
  1082  	}
  1083  }
  1084  
  1085  func TestHammer64(t *testing.T) {
  1086  	if test64err != nil {
  1087  		t.Skipf("Skipping 64-bit tests: %v", test64err)
  1088  	}
  1089  	const p = 4
  1090  	n := 100000
  1091  	if testing.Short() {
  1092  		n = 1000
  1093  	}
  1094  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
  1095  
  1096  	for name, testf := range hammer64 {
  1097  		c := make(chan int)
  1098  		var val uint64
  1099  		for i := 0; i < p; i++ {
  1100  			go func() {
  1101  				defer func() {
  1102  					if err := recover(); err != nil {
  1103  						t.Error(err.(string))
  1104  					}
  1105  					c <- 1
  1106  				}()
  1107  				testf(&val, n)
  1108  			}()
  1109  		}
  1110  		for i := 0; i < p; i++ {
  1111  			<-c
  1112  		}
  1113  		if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p {
  1114  			t.Fatalf("%s: val=%d want %d", name, val, n*p)
  1115  		}
  1116  	}
  1117  }
  1118  
  1119  func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
  1120  	addr := (*int32)(paddr)
  1121  	v := LoadInt32(addr)
  1122  	vlo := v & ((1 << 16) - 1)
  1123  	vhi := v >> 16
  1124  	if vlo != vhi {
  1125  		t.Fatalf("Int32: %#x != %#x", vlo, vhi)
  1126  	}
  1127  	new := v + 1 + 1<<16
  1128  	if vlo == 1e4 {
  1129  		new = 0
  1130  	}
  1131  	StoreInt32(addr, new)
  1132  }
  1133  
  1134  func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
  1135  	addr := (*uint32)(paddr)
  1136  	v := LoadUint32(addr)
  1137  	vlo := v & ((1 << 16) - 1)
  1138  	vhi := v >> 16
  1139  	if vlo != vhi {
  1140  		t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
  1141  	}
  1142  	new := v + 1 + 1<<16
  1143  	if vlo == 1e4 {
  1144  		new = 0
  1145  	}
  1146  	StoreUint32(addr, new)
  1147  }
  1148  
  1149  func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
  1150  	addr := (*int64)(paddr)
  1151  	v := LoadInt64(addr)
  1152  	vlo := v & ((1 << 32) - 1)
  1153  	vhi := v >> 32
  1154  	if vlo != vhi {
  1155  		t.Fatalf("Int64: %#x != %#x", vlo, vhi)
  1156  	}
  1157  	new := v + 1 + 1<<32
  1158  	StoreInt64(addr, new)
  1159  }
  1160  
  1161  func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
  1162  	addr := (*uint64)(paddr)
  1163  	v := LoadUint64(addr)
  1164  	vlo := v & ((1 << 32) - 1)
  1165  	vhi := v >> 32
  1166  	if vlo != vhi {
  1167  		t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
  1168  	}
  1169  	new := v + 1 + 1<<32
  1170  	StoreUint64(addr, new)
  1171  }
  1172  
  1173  func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
  1174  	addr := (*uintptr)(paddr)
  1175  	var test64 uint64 = 1 << 50
  1176  	arch32 := uintptr(test64) == 0
  1177  	v := LoadUintptr(addr)
  1178  	new := v
  1179  	if arch32 {
  1180  		vlo := v & ((1 << 16) - 1)
  1181  		vhi := v >> 16
  1182  		if vlo != vhi {
  1183  			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
  1184  		}
  1185  		new = v + 1 + 1<<16
  1186  		if vlo == 1e4 {
  1187  			new = 0
  1188  		}
  1189  	} else {
  1190  		vlo := v & ((1 << 32) - 1)
  1191  		vhi := v >> 32
  1192  		if vlo != vhi {
  1193  			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
  1194  		}
  1195  		inc := uint64(1 + 1<<32)
  1196  		new = v + uintptr(inc)
  1197  	}
  1198  	StoreUintptr(addr, new)
  1199  }
  1200  
  1201  func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
  1202  	addr := (*unsafe.Pointer)(paddr)
  1203  	var test64 uint64 = 1 << 50
  1204  	arch32 := uintptr(test64) == 0
  1205  	v := uintptr(LoadPointer(addr))
  1206  	new := v
  1207  	if arch32 {
  1208  		vlo := v & ((1 << 16) - 1)
  1209  		vhi := v >> 16
  1210  		if vlo != vhi {
  1211  			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
  1212  		}
  1213  		new = v + 1 + 1<<16
  1214  		if vlo == 1e4 {
  1215  			new = 0
  1216  		}
  1217  	} else {
  1218  		vlo := v & ((1 << 32) - 1)
  1219  		vhi := v >> 32
  1220  		if vlo != vhi {
  1221  			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
  1222  		}
  1223  		inc := uint64(1 + 1<<32)
  1224  		new = v + uintptr(inc)
  1225  	}
  1226  	StorePointer(addr, unsafe.Pointer(new))
  1227  }
  1228  
  1229  func TestHammerStoreLoad(t *testing.T) {
  1230  	var tests []func(*testing.T, unsafe.Pointer)
  1231  	tests = append(tests, hammerStoreLoadInt32, hammerStoreLoadUint32,
  1232  		hammerStoreLoadUintptr, hammerStoreLoadPointer)
  1233  	if test64err == nil {
  1234  		tests = append(tests, hammerStoreLoadInt64, hammerStoreLoadUint64)
  1235  	}
  1236  	n := int(1e6)
  1237  	if testing.Short() {
  1238  		n = int(1e4)
  1239  	}
  1240  	const procs = 8
  1241  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))
  1242  	for _, tt := range tests {
  1243  		c := make(chan int)
  1244  		var val uint64
  1245  		for p := 0; p < procs; p++ {
  1246  			go func() {
  1247  				for i := 0; i < n; i++ {
  1248  					tt(t, unsafe.Pointer(&val))
  1249  				}
  1250  				c <- 1
  1251  			}()
  1252  		}
  1253  		for p := 0; p < procs; p++ {
  1254  			<-c
  1255  		}
  1256  	}
  1257  }
  1258  
  1259  func TestStoreLoadSeqCst32(t *testing.T) {
  1260  	if runtime.NumCPU() == 1 {
  1261  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1262  	}
  1263  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1264  	N := int32(1e3)
  1265  	if testing.Short() {
  1266  		N = int32(1e2)
  1267  	}
  1268  	c := make(chan bool, 2)
  1269  	X := [2]int32{}
  1270  	ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}}
  1271  	for p := 0; p < 2; p++ {
  1272  		go func(me int) {
  1273  			he := 1 - me
  1274  			for i := int32(1); i < N; i++ {
  1275  				StoreInt32(&X[me], i)
  1276  				my := LoadInt32(&X[he])
  1277  				StoreInt32(&ack[me][i%3], my)
  1278  				for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ {
  1279  					if w%1000 == 0 {
  1280  						runtime.Gosched()
  1281  					}
  1282  				}
  1283  				his := LoadInt32(&ack[he][i%3])
  1284  				if (my != i && my != i-1) || (his != i && his != i-1) {
  1285  					t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
  1286  				}
  1287  				if my != i && his != i {
  1288  					t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
  1289  				}
  1290  				StoreInt32(&ack[me][(i-1)%3], -1)
  1291  			}
  1292  			c <- true
  1293  		}(p)
  1294  	}
  1295  	<-c
  1296  	<-c
  1297  }
  1298  
  1299  func TestStoreLoadSeqCst64(t *testing.T) {
  1300  	if runtime.NumCPU() == 1 {
  1301  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1302  	}
  1303  	if test64err != nil {
  1304  		t.Skipf("Skipping 64-bit tests: %v", test64err)
  1305  	}
  1306  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1307  	N := int64(1e3)
  1308  	if testing.Short() {
  1309  		N = int64(1e2)
  1310  	}
  1311  	c := make(chan bool, 2)
  1312  	X := [2]int64{}
  1313  	ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}}
  1314  	for p := 0; p < 2; p++ {
  1315  		go func(me int) {
  1316  			he := 1 - me
  1317  			for i := int64(1); i < N; i++ {
  1318  				StoreInt64(&X[me], i)
  1319  				my := LoadInt64(&X[he])
  1320  				StoreInt64(&ack[me][i%3], my)
  1321  				for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ {
  1322  					if w%1000 == 0 {
  1323  						runtime.Gosched()
  1324  					}
  1325  				}
  1326  				his := LoadInt64(&ack[he][i%3])
  1327  				if (my != i && my != i-1) || (his != i && his != i-1) {
  1328  					t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
  1329  				}
  1330  				if my != i && his != i {
  1331  					t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
  1332  				}
  1333  				StoreInt64(&ack[me][(i-1)%3], -1)
  1334  			}
  1335  			c <- true
  1336  		}(p)
  1337  	}
  1338  	<-c
  1339  	<-c
  1340  }
  1341  
  1342  func TestStoreLoadRelAcq32(t *testing.T) {
  1343  	if runtime.NumCPU() == 1 {
  1344  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1345  	}
  1346  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1347  	N := int32(1e3)
  1348  	if testing.Short() {
  1349  		N = int32(1e2)
  1350  	}
  1351  	c := make(chan bool, 2)
  1352  	type Data struct {
  1353  		signal int32
  1354  		pad1   [128]int8
  1355  		data1  int32
  1356  		pad2   [128]int8
  1357  		data2  float32
  1358  	}
  1359  	var X Data
  1360  	for p := int32(0); p < 2; p++ {
  1361  		go func(p int32) {
  1362  			for i := int32(1); i < N; i++ {
  1363  				if (i+p)%2 == 0 {
  1364  					X.data1 = i
  1365  					X.data2 = float32(i)
  1366  					StoreInt32(&X.signal, i)
  1367  				} else {
  1368  					for w := 1; LoadInt32(&X.signal) != i; w++ {
  1369  						if w%1000 == 0 {
  1370  							runtime.Gosched()
  1371  						}
  1372  					}
  1373  					d1 := X.data1
  1374  					d2 := X.data2
  1375  					if d1 != i || d2 != float32(i) {
  1376  						t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
  1377  					}
  1378  				}
  1379  			}
  1380  			c <- true
  1381  		}(p)
  1382  	}
  1383  	<-c
  1384  	<-c
  1385  }
  1386  
  1387  func TestStoreLoadRelAcq64(t *testing.T) {
  1388  	if runtime.NumCPU() == 1 {
  1389  		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
  1390  	}
  1391  	if test64err != nil {
  1392  		t.Skipf("Skipping 64-bit tests: %v", test64err)
  1393  	}
  1394  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  1395  	N := int64(1e3)
  1396  	if testing.Short() {
  1397  		N = int64(1e2)
  1398  	}
  1399  	c := make(chan bool, 2)
  1400  	type Data struct {
  1401  		signal int64
  1402  		pad1   [128]int8
  1403  		data1  int64
  1404  		pad2   [128]int8
  1405  		data2  float64
  1406  	}
  1407  	var X Data
  1408  	for p := int64(0); p < 2; p++ {
  1409  		go func(p int64) {
  1410  			for i := int64(1); i < N; i++ {
  1411  				if (i+p)%2 == 0 {
  1412  					X.data1 = i
  1413  					X.data2 = float64(i)
  1414  					StoreInt64(&X.signal, i)
  1415  				} else {
  1416  					for w := 1; LoadInt64(&X.signal) != i; w++ {
  1417  						if w%1000 == 0 {
  1418  							runtime.Gosched()
  1419  						}
  1420  					}
  1421  					d1 := X.data1
  1422  					d2 := X.data2
  1423  					if d1 != i || d2 != float64(i) {
  1424  						t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
  1425  					}
  1426  				}
  1427  			}
  1428  			c <- true
  1429  		}(p)
  1430  	}
  1431  	<-c
  1432  	<-c
  1433  }
  1434  
  1435  func shouldPanic(t *testing.T, name string, f func()) {
  1436  	defer func() {
  1437  		if recover() == nil {
  1438  			t.Errorf("%s did not panic", name)
  1439  		}
  1440  	}()
  1441  	f()
  1442  }
  1443  
  1444  func TestUnaligned64(t *testing.T) {
  1445  	// Unaligned 64-bit atomics on 32-bit systems are
  1446  	// a continual source of pain. Test that on 32-bit systems they crash
  1447  	// instead of failing silently.
  1448  	if unsafe.Sizeof(int(0)) != 4 {
  1449  		t.Skip("test only runs on 32-bit systems")
  1450  	}
  1451  
  1452  	x := make([]uint32, 4)
  1453  	p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
  1454  
  1455  	shouldPanic(t, "LoadUint64", func() { LoadUint64(p) })
  1456  	shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) })
  1457  	shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
  1458  	shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
  1459  }
  1460  
  1461  func TestNilDeref(t *testing.T) {
  1462  	funcs := [...]func(){
  1463  		func() { CompareAndSwapInt32(nil, 0, 0) },
  1464  		func() { CompareAndSwapInt64(nil, 0, 0) },
  1465  		func() { CompareAndSwapUint32(nil, 0, 0) },
  1466  		func() { CompareAndSwapUint64(nil, 0, 0) },
  1467  		func() { CompareAndSwapUintptr(nil, 0, 0) },
  1468  		func() { CompareAndSwapPointer(nil, nil, nil) },
  1469  		func() { SwapInt32(nil, 0) },
  1470  		func() { SwapUint32(nil, 0) },
  1471  		func() { SwapInt64(nil, 0) },
  1472  		func() { SwapUint64(nil, 0) },
  1473  		func() { SwapUintptr(nil, 0) },
  1474  		func() { SwapPointer(nil, nil) },
  1475  		func() { AddInt32(nil, 0) },
  1476  		func() { AddUint32(nil, 0) },
  1477  		func() { AddInt64(nil, 0) },
  1478  		func() { AddUint64(nil, 0) },
  1479  		func() { AddUintptr(nil, 0) },
  1480  		func() { LoadInt32(nil) },
  1481  		func() { LoadInt64(nil) },
  1482  		func() { LoadUint32(nil) },
  1483  		func() { LoadUint64(nil) },
  1484  		func() { LoadUintptr(nil) },
  1485  		func() { LoadPointer(nil) },
  1486  		func() { StoreInt32(nil, 0) },
  1487  		func() { StoreInt64(nil, 0) },
  1488  		func() { StoreUint32(nil, 0) },
  1489  		func() { StoreUint64(nil, 0) },
  1490  		func() { StoreUintptr(nil, 0) },
  1491  		func() { StorePointer(nil, nil) },
  1492  	}
  1493  	for _, f := range funcs {
  1494  		func() {
  1495  			defer func() {
  1496  				runtime.GC()
  1497  				recover()
  1498  			}()
  1499  			f()
  1500  		}()
  1501  	}
  1502  }