...

Source file src/sync/atomic/atomic_test.go

Documentation: sync/atomic

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

View as plain text