mirror of
https://git.zx2c4.com/wireguard-go
synced 2025-09-18 20:57:50 +02:00
All atomic access must be aligned to 64 bits, even on 32-bit platforms. Go promises that the start of allocated structs is aligned to 64 bits. So, place the atomically-accessed things first in the struct so that they benefit from that alignment. As a side bonus, it cleanly separates fields that are accessed by atomic ops, and those that should be accessed under mu. Also adds a test that will fail consistently on 32-bit platforms if the struct ever changes again to violate the rules. This is likely not needed because unaligned access crashes reliably, but this will reliably fail even if tests accidentally pass due to lucky alignment. Signed-Off-By: David Anderson <danderson@tailscale.com>
30 lines
866 B
Go
30 lines
866 B
Go
/* SPDX-License-Identifier: MIT
|
|
*
|
|
* Copyright (C) 2017-2019 WireGuard LLC. All Rights Reserved.
|
|
*/
|
|
|
|
package device
|
|
|
|
import (
|
|
"testing"
|
|
"unsafe"
|
|
)
|
|
|
|
func checkAlignment(t *testing.T, name string, offset uintptr) {
|
|
t.Helper()
|
|
if offset%8 != 0 {
|
|
t.Errorf("offset of %q within struct is %d bytes, which does not align to 64-bit word boundaries (missing %d bytes). Atomic operations will crash on 32-bit systems.", name, offset, 8-(offset%8))
|
|
}
|
|
}
|
|
|
|
// TestPeerAlignment checks that atomically-accessed fields are
|
|
// aligned to 64-bit boundaries, as required by the atomic package.
|
|
//
|
|
// Unfortunately, violating this rule on 32-bit platforms results in a
|
|
// hard segfault at runtime.
|
|
func TestPeerAlignment(t *testing.T) {
|
|
var p Peer
|
|
checkAlignment(t, "Peer.stats", unsafe.Offsetof(p.stats))
|
|
checkAlignment(t, "Peer.isRunning", unsafe.Offsetof(p.isRunning))
|
|
}
|