From d36501a6e54e1c794af0c7109e937f7f7c74de79 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 26 Mar 2015 17:45:03 +0100 Subject: [PATCH] Fixed miner * Miners could stall because the worker wasn't aware the miner was done --- miner/agent.go | 23 ++++++++++++++++------- miner/remote_agent.go | 1 + miner/worker.go | 26 ++++++++++++++++++-------- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/miner/agent.go b/miner/agent.go index 5661d2982..c650fa2f3 100644 --- a/miner/agent.go +++ b/miner/agent.go @@ -1,12 +1,15 @@ package miner import ( + "sync" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/pow" ) type CpuMiner struct { + chMu sync.Mutex c chan *types.Block quit chan struct{} quitCurrentOp chan struct{} @@ -43,16 +46,13 @@ func (self *CpuMiner) Start() { } func (self *CpuMiner) update() { - justStarted := true out: for { select { case block := <-self.c: - if justStarted { - justStarted = true - } else { - self.quitCurrentOp <- struct{}{} - } + self.chMu.Lock() + self.quitCurrentOp <- struct{}{} + self.chMu.Unlock() go self.mine(block) case <-self.quit: @@ -60,6 +60,7 @@ out: } } + close(self.quitCurrentOp) done: // Empty channel for { @@ -75,12 +76,20 @@ done: func (self *CpuMiner) mine(block *types.Block) { minerlogger.Debugf("(re)started agent[%d]. mining...\n", self.index) + + // Reset the channel + self.chMu.Lock() + self.quitCurrentOp = make(chan struct{}, 1) + self.chMu.Unlock() + + // Mine nonce, mixDigest, _ := self.pow.Search(block, self.quitCurrentOp) if nonce != 0 { block.SetNonce(nonce) block.Header().MixDigest = common.BytesToHash(mixDigest) self.returnCh <- block - //self.returnCh <- Work{block.Number().Uint64(), nonce, mixDigest, seedHash} + } else { + self.returnCh <- nil } } diff --git a/miner/remote_agent.go b/miner/remote_agent.go index e92dd5963..aa04a58aa 100644 --- a/miner/remote_agent.go +++ b/miner/remote_agent.go @@ -50,6 +50,7 @@ out: break out case work := <-a.workCh: a.work = work + a.returnCh <- nil } } } diff --git a/miner/worker.go b/miner/worker.go index e0287ea8d..e3680dea3 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -5,6 +5,7 @@ import ( "math/big" "sort" "sync" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/common" @@ -58,13 +59,14 @@ type Agent interface { } type worker struct { - mu sync.Mutex + mu sync.Mutex + agents []Agent recv chan *types.Block mux *event.TypeMux quit chan struct{} pow pow.PoW - atWork int + atWork int64 eth core.Backend chain *core.ChainManager @@ -107,7 +109,7 @@ func (self *worker) start() { func (self *worker) stop() { self.mining = false - self.atWork = 0 + atomic.StoreInt64(&self.atWork, 0) close(self.quit) } @@ -135,9 +137,6 @@ out: self.uncleMu.Unlock() } - if self.atWork == 0 { - self.commitNewWork() - } case <-self.quit: // stop all agents for _, agent := range self.agents { @@ -146,6 +145,11 @@ out: break out case <-timer.C: minerlogger.Infoln("Hash rate:", self.HashRate(), "Khash") + + // XXX In case all mined a possible uncle + if atomic.LoadInt64(&self.atWork) == 0 { + self.commitNewWork() + } } } @@ -155,6 +159,12 @@ out: func (self *worker) wait() { for { for block := range self.recv { + atomic.AddInt64(&self.atWork, -1) + + if block == nil { + continue + } + if err := self.chain.InsertChain(types.Blocks{block}); err == nil { for _, uncle := range block.Uncles() { delete(self.possibleUncles, uncle.Hash()) @@ -170,7 +180,6 @@ func (self *worker) wait() { } else { self.commitNewWork() } - self.atWork-- } } } @@ -182,8 +191,9 @@ func (self *worker) push() { // push new work to agents for _, agent := range self.agents { + atomic.AddInt64(&self.atWork, 1) + agent.Work() <- self.current.block.Copy() - self.atWork++ } } }