1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#pragma once
#include <thread>
#include <atomic>
#include "crypto/cryptonight.h"
class telemetry
{
public:
telemetry(size_t iThd);
void push_perf_value(size_t iThd, uint64_t iHashCount, uint64_t iTimestamp);
double calc_telemetry_data(size_t iLastMilisec, size_t iThread);
private:
constexpr static size_t iBucketSize = 2 << 11; //Power of 2 to simplify calculations
constexpr static size_t iBucketMask = iBucketSize - 1;
uint32_t* iBucketTop;
uint64_t** ppHashCounts;
uint64_t** ppTimestamps;
};
class minethd
{
public:
struct miner_work
{
char sJobID[64];
uint8_t bWorkBlob[112];
uint32_t iWorkSize;
uint32_t iResumeCnt;
uint64_t iTarget;
bool bNiceHash;
bool bStall;
size_t iPoolId;
miner_work() : iWorkSize(0), bStall(true), iPoolId(0) { }
miner_work(const char* sJobID, const uint8_t* bWork, uint32_t iWorkSize, uint32_t iResumeCnt,
uint64_t iTarget, bool bNiceHash, size_t iPoolId) : iWorkSize(iWorkSize), iResumeCnt(iResumeCnt),
iTarget(iTarget), bNiceHash(bNiceHash), bStall(false), iPoolId(iPoolId)
{
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(this->sJobID, sJobID, sizeof(miner_work::sJobID));
memcpy(this->bWorkBlob, bWork, iWorkSize);
}
miner_work(miner_work const&) = delete;
miner_work& operator=(miner_work const& from)
{
assert(this != &from);
iWorkSize = from.iWorkSize;
iResumeCnt = from.iResumeCnt;
iTarget = from.iTarget;
bNiceHash = from.bNiceHash;
bStall = from.bStall;
iPoolId = from.iPoolId;
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(sJobID, from.sJobID, sizeof(sJobID));
memcpy(bWorkBlob, from.bWorkBlob, iWorkSize);
return *this;
}
miner_work(miner_work&& from) : iWorkSize(from.iWorkSize), iTarget(from.iTarget),
bStall(from.bStall), iPoolId(from.iPoolId)
{
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(sJobID, from.sJobID, sizeof(sJobID));
memcpy(bWorkBlob, from.bWorkBlob, iWorkSize);
}
miner_work& operator=(miner_work&& from)
{
assert(this != &from);
iWorkSize = from.iWorkSize;
iResumeCnt = from.iResumeCnt;
iTarget = from.iTarget;
bNiceHash = from.bNiceHash;
bStall = from.bStall;
iPoolId = from.iPoolId;
assert(iWorkSize <= sizeof(bWorkBlob));
memcpy(sJobID, from.sJobID, sizeof(sJobID));
memcpy(bWorkBlob, from.bWorkBlob, iWorkSize);
return *this;
}
};
static void switch_work(miner_work& pWork);
static std::vector<minethd*>* thread_starter(miner_work& pWork);
static bool self_test();
std::atomic<uint64_t> iHashCount;
std::atomic<uint64_t> iTimestamp;
private:
typedef void (*cn_hash_fun)(const void*, size_t, void*, cryptonight_ctx*);
typedef void (*cn_hash_fun_dbl)(const void*, size_t, void*, cryptonight_ctx* __restrict, cryptonight_ctx* __restrict);
minethd(miner_work& pWork, size_t iNo, bool double_work, bool no_prefetch);
// We use the top 10 bits of the nonce for thread and resume
// This allows us to resume up to 128 threads 4 times before
// we get nonce collisions
// Bottom 22 bits allow for an hour of work at 1000 H/s
inline uint32_t calc_start_nonce(uint32_t resume)
{ return (resume * iThreadCount + iThreadNo) << 22; }
// Limited version of the nonce calc above
inline uint32_t calc_nicehash_nonce(uint32_t start, uint32_t resume)
{ return start | (resume * iThreadCount + iThreadNo) << 18; }
static cn_hash_fun func_selector(bool bHaveAes, bool bNoPrefetch, bool bMulx);
static cn_hash_fun_dbl func_dbl_selector(bool bHaveAes, bool bNoPrefetch, bool bMulx);
void work_main();
void double_work_main();
void consume_work();
static std::atomic<uint64_t> iGlobalJobNo;
static std::atomic<uint64_t> iConsumeCnt;
static uint64_t iThreadCount;
uint64_t iJobNo;
static miner_work oGlobalWork;
miner_work oWork;
std::thread oWorkThd;
uint8_t iThreadNo;
bool bQuit;
bool bNoPrefetch;
};
|