From 6c514adb8a662171a00decf4aefbf5048974a17d Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Tue, 22 Dec 2020 21:03:27 +0100 Subject: [PATCH] ui/progress: Use mutex instead of atomic The counter value needs to be aligned to 64 bit in memory for the atomic functions to work on some platform (such as 32 bit ARM). The atomic package says in its documentation: > These functions require great care to be used correctly. Except for > special, low-level applications, synchronization is better done with > channels or the facilities of the sync package. This commit replaces the atomic functions with a simple sync.Mutex, so we don't have to care about alignment. --- internal/ui/progress/counter.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/internal/ui/progress/counter.go b/internal/ui/progress/counter.go index a27a38575..3b0009649 100644 --- a/internal/ui/progress/counter.go +++ b/internal/ui/progress/counter.go @@ -3,7 +3,6 @@ package progress import ( "os" "sync" - "sync/atomic" "time" "github.com/restic/restic/internal/debug" @@ -25,7 +24,9 @@ type Counter struct { stopped chan struct{} // Closed by run. stop chan struct{} // Close to stop run. tick *time.Ticker - value uint64 + + valueMutex sync.Mutex + value uint64 } // New starts a new Counter. @@ -52,7 +53,10 @@ func (c *Counter) Add(v uint64) { if c == nil { return } - atomic.AddUint64(&c.value, v) + + c.valueMutex.Lock() + c.value += v + c.valueMutex.Unlock() } // Done tells a Counter to stop and waits for it to report its final value. @@ -66,7 +70,13 @@ func (c *Counter) Done() { *c = Counter{} // Prevent reuse. } -func (c *Counter) get() uint64 { return atomic.LoadUint64(&c.value) } +func (c *Counter) get() uint64 { + c.valueMutex.Lock() + v := c.value + c.valueMutex.Unlock() + + return v +} func (c *Counter) run() { defer close(c.stopped)