Browse Source

etcdserver: move atomics to make etcd work on arm64

Follow the simple rule in the atomic package:

"On both ARM and x86-32, it is the caller's responsibility to arrange
for 64-bit alignment of 64-bit words accessed atomically. The first word
in a global variable or in an allocated struct or slice can be relied
upon to be 64-bit aligned."

Tested on a system with /proc/cpuinfo reporting:

processor       : 0
model name      : ARMv7 Processor rev 1 (v7l)
Features        : swp half thumb fastmult vfp edsp thumbee neon vfpv3
tls vfpv4 idiva idivt vfpd32 lpae evtstrm
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc0d
CPU revision    : 1
Brandon Philips 10 years ago
parent
commit
fb1951204c
3 changed files with 16 additions and 8 deletions
  1. 7 5
      etcdserver/raft.go
  2. 4 2
      etcdserver/server.go
  3. 5 1
      store/watcher_hub.go

+ 7 - 5
etcdserver/raft.go

@@ -79,6 +79,13 @@ type apply struct {
 }
 
 type raftNode struct {
+	// Cache of the latest raft index and raft term the server has seen.
+	// These three unit64 fields must be the first elements to keep 64-bit
+	// alignment for atomic access to the fields.
+	index uint64
+	term  uint64
+	lead  uint64
+
 	raft.Node
 
 	// a chan to send out apply
@@ -99,11 +106,6 @@ type raftNode struct {
 	// If transport is nil, server will panic.
 	transport rafthttp.Transporter
 
-	// Cache of the latest raft index and raft term the server has seen
-	index uint64
-	term  uint64
-	lead  uint64
-
 	stopped chan struct{}
 	done    chan struct{}
 }

+ 4 - 2
etcdserver/server.go

@@ -141,11 +141,13 @@ type Server interface {
 
 // EtcdServer is the production implementation of the Server interface
 type EtcdServer struct {
+	// r must be the first element to keep 64-bit alignment for atomic
+	// access to fields
+	r raftNode
+
 	cfg       *ServerConfig
 	snapCount uint64
 
-	r raftNode
-
 	w          wait.Wait
 	stop       chan struct{}
 	done       chan struct{}

+ 5 - 1
store/watcher_hub.go

@@ -31,9 +31,13 @@ import (
 // event happens between the end of the first watch command and the start
 // of the second command.
 type watcherHub struct {
+	// count must be the first element to keep 64-bit alignment for atomic
+	// access
+
+	count int64 // current number of watchers.
+
 	mutex        sync.Mutex
 	watchers     map[string]*list.List
-	count        int64 // current number of watchers.
 	EventHistory *EventHistory
 }