code: func (s *Ethereum) StartMining(threads int) error {
  	// Update the thread count within the consensus engine
  	type threaded interface {
  		SetThreads(threads int)
  	}
  	if th, ok := s.engine.(threaded); ok {
  		log.Info("Updated mining threads", "threads", threads)
  		if threads == 0 {
  			threads = -1 // Disable the miner from within
  		}
  		th.SetThreads(threads)
  	}
  	// If the miner was not running, initialize it
  	if !s.IsMining() {
  		// Propagate the initial price point to the transaction pool
  		s.lock.RLock()
  		price := s.gasPrice
  		s.lock.RUnlock()
  		s.txPool.SetGasPrice(price)
  
  		// Configure the local mining address
  		eb, err := s.Etherbase()
  		if err != nil {
  			log.Error("Cannot start mining without etherbase", "err", err)
  			return fmt.Errorf("etherbase missing: %v", err)
  		}
  		if clique, ok := s.engine.(*clique.Clique); ok {
  			wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
  			if wallet == nil || err != nil {
  				log.Error("Etherbase account unavailable locally", "err", err)
  				return fmt.Errorf("signer missing: %v", err)
  			}
  			clique.Authorize(eb, wallet.SignData)
  		}
  		// If mining is started, we can disable the transaction rejection mechanism
  		// introduced to speed sync times.
  		atomic.StoreUint32(&s.protocolManager.acceptTxs, 1)
  
  		go s.miner.Start(eb)
  	}
  	return nil
  }
docs: // StartMining starts the miner with the given number of CPU threads. If mining
  // is already running, this method adjust the number of threads allowed to use
  // and updates the minimum price required by the transaction pool.