mirror of
https://github.com/jwinterm/xmr-stak.git
synced 2026-10-21 06:18:34 +02:00
add generic backend files
- add Plugin.h to load a backend - add backend interface
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional permission under GNU GPL version 3 section 7
|
||||
*
|
||||
* If you modify this Program, or any covered work, by linking or combining
|
||||
* it with OpenSSL (or a modified version of that library), containing parts
|
||||
* covered by the terms of OpenSSL License and SSLeay License, the licensors
|
||||
* of this Program grant you additional permission to convey the resulting work.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <bitset>
|
||||
|
||||
#include "IBackend.hpp"
|
||||
#include "BackendConnector.hpp"
|
||||
|
||||
#include "cpu/minethd.h"
|
||||
#ifndef CONF_NO_CUDA
|
||||
# include "nvidia/minethd.h"
|
||||
#endif
|
||||
#ifndef CONF_NO_OPENCL
|
||||
# include "amd/minethd.h"
|
||||
#endif
|
||||
#include "miner_work.h"
|
||||
#include "GlobalStates.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
#include "Plugin.hpp"
|
||||
|
||||
namespace xmrstak
|
||||
{
|
||||
|
||||
|
||||
bool BackendConnector::self_test()
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<IBackend*>* BackendConnector::thread_starter(miner_work& pWork)
|
||||
{
|
||||
GlobalStates::iGlobalJobNo = 0;
|
||||
GlobalStates::iConsumeCnt = 0;
|
||||
|
||||
|
||||
std::vector<IBackend*>* pvThreads = new std::vector<IBackend*>;
|
||||
|
||||
auto cpuThreads = cpu::minethd::thread_starter(pvThreads->size(), pWork);
|
||||
pvThreads->insert(std::end(*pvThreads), std::begin(cpuThreads), std::end(cpuThreads));
|
||||
if(cpuThreads.size() == 0)
|
||||
printer::inst()->print_msg(L0, "WARNING: backend CPU disabled.");
|
||||
|
||||
#ifndef CONF_NO_CUDA
|
||||
Plugin nvidiaPlugin("NVIDIA", "./libxmrstak_cuda_backend");
|
||||
std::vector<IBackend*>* nvidiaThreads = nvidiaPlugin.startBackend(pvThreads->size(), pWork);
|
||||
pvThreads->insert(std::end(*pvThreads), std::begin(*nvidiaThreads), std::end(*nvidiaThreads));
|
||||
if(nvidiaThreads->size() == 0)
|
||||
printer::inst()->print_msg(L0, "WARNING: backend NVIDIA disabled.");
|
||||
#endif
|
||||
|
||||
#ifndef CONF_NO_OPENCL
|
||||
Plugin amdPlugin("AMD", "./libxmrstak_opencl_backend");
|
||||
std::vector<IBackend*>* amdThreads = amdPlugin.startBackend(pvThreads->size(), pWork);
|
||||
pvThreads->insert(std::end(*pvThreads), std::begin(*amdThreads), std::end(*amdThreads));
|
||||
if(amdThreads->size() == 0)
|
||||
printer::inst()->print_msg(L0, "WARNING: backend AMD disabled.");
|
||||
#endif
|
||||
|
||||
GlobalStates::iThreadCount = pvThreads->size();
|
||||
return pvThreads;
|
||||
}
|
||||
|
||||
} // namepsace xmrstak
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include "IBackend.hpp"
|
||||
#include "miner_work.h"
|
||||
|
||||
namespace xmrstak
|
||||
{
|
||||
|
||||
struct BackendConnector
|
||||
{
|
||||
static std::vector<IBackend*>* thread_starter(miner_work& pWork);
|
||||
static bool self_test();
|
||||
};
|
||||
|
||||
} // namepsace xmrstak
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional permission under GNU GPL version 3 section 7
|
||||
*
|
||||
* If you modify this Program, or any covered work, by linking or combining
|
||||
* it with OpenSSL (or a modified version of that library), containing parts
|
||||
* covered by the terms of OpenSSL License and SSLeay License, the licensors
|
||||
* of this Program grant you additional permission to convey the resulting work.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
#include "miner_work.h"
|
||||
#include "GlobalStates.hpp"
|
||||
|
||||
namespace xmrstak
|
||||
{
|
||||
|
||||
std::atomic<uint64_t> GlobalStates::iGlobalJobNo;
|
||||
std::atomic<uint64_t> GlobalStates::iConsumeCnt; //Threads get jobs as they are initialized
|
||||
miner_work GlobalStates::oGlobalWork;
|
||||
uint64_t GlobalStates::iThreadCount = 0;
|
||||
|
||||
void GlobalStates::switch_work(miner_work& pWork)
|
||||
{
|
||||
// iConsumeCnt is a basic lock-like polling mechanism just in case we happen to push work
|
||||
// faster than threads can consume them. This should never happen in real life.
|
||||
// Pool cant physically send jobs faster than every 250ms or so due to net latency.
|
||||
|
||||
while (iConsumeCnt.load(std::memory_order_seq_cst) < iThreadCount)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
oGlobalWork = pWork;
|
||||
iConsumeCnt.store(0, std::memory_order_seq_cst);
|
||||
iGlobalJobNo++;
|
||||
}
|
||||
|
||||
} // namepsace xmrstak
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include "miner_work.h"
|
||||
|
||||
namespace xmrstak
|
||||
{
|
||||
|
||||
struct GlobalStates
|
||||
{
|
||||
|
||||
static void switch_work(miner_work& pWork);
|
||||
|
||||
static miner_work oGlobalWork;
|
||||
static std::atomic<uint64_t> iGlobalJobNo;
|
||||
static std::atomic<uint64_t> iConsumeCnt;
|
||||
static uint64_t iThreadCount;
|
||||
|
||||
};
|
||||
|
||||
} // namepsace xmrstak
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace xmrstak
|
||||
{
|
||||
|
||||
struct IBackend
|
||||
{
|
||||
std::atomic<uint64_t> iHashCount;
|
||||
std::atomic<uint64_t> iTimestamp;
|
||||
|
||||
IBackend() : iHashCount(0), iTimestamp(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namepsace xmrstak
|
||||
@@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "IBackend.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#ifndef USE_PRECOMPILED_HEADERS
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
namespace xmrstak
|
||||
{
|
||||
|
||||
struct Plugin
|
||||
{
|
||||
|
||||
Plugin(const std::string backendName, const std::string libName) : fn_starterBackend(nullptr), m_backendName(backendName)
|
||||
{
|
||||
#ifdef WIN32
|
||||
libBackend = LoadLibrary(TEXT((libName + ".dll").c_str()));
|
||||
#else
|
||||
libBackend = dlopen((libName + ".so").c_str(), RTLD_LAZY);
|
||||
#endif
|
||||
if (!libBackend)
|
||||
{
|
||||
std::cerr << "WARNING: "<< m_backendName <<" cannot load backend library: " << dlerror() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
fn_starterBackend = (func_t*) GetProcAddress(libBackend, "xmrstak_start_backend");
|
||||
if (!fn_starterBackend)
|
||||
{
|
||||
std::cerr << "WARNING: backend plugin " << libName << " contains no entry 'xmrstak_start_backend'" << std::endl;
|
||||
}
|
||||
#else
|
||||
// reset last error
|
||||
dlerror();
|
||||
fn_starterBackend = (starterBackend_t) dlsym(libBackend, "xmrstak_start_backend");
|
||||
const char* dlsym_error = dlerror();
|
||||
if (dlsym_error)
|
||||
{
|
||||
std::cerr << "WARNING: backend plugin " << libName << " contains no entry 'xmrstak_start_backend'" << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<IBackend*>* startBackend(uint32_t threadOffset, miner_work& pWork)
|
||||
{
|
||||
if(fn_starterBackend == nullptr)
|
||||
{
|
||||
std::vector<IBackend*>* pvThreads = new std::vector<IBackend*>();
|
||||
std::cerr << "WARNING: " << m_backendName << " Backend disabled"<< std::endl;
|
||||
return pvThreads;
|
||||
}
|
||||
|
||||
return fn_starterBackend(threadOffset, pWork);
|
||||
}
|
||||
|
||||
std::string m_backendName;
|
||||
|
||||
typedef std::vector<IBackend*>* (*starterBackend_t)(uint32_t threadOffset, miner_work& pWork);
|
||||
|
||||
starterBackend_t fn_starterBackend;
|
||||
|
||||
#ifdef WIN32
|
||||
HINSTANCE libBackend;
|
||||
#else
|
||||
void *libBackend;
|
||||
#endif
|
||||
|
||||
/* \todo add unload to destructor and change usage of Plugin that libs keeped open until the miner endss
|
||||
#ifdef WIN32
|
||||
FreeLibrary(libBackend);
|
||||
#else
|
||||
dlclose(libBackend);
|
||||
#endif
|
||||
* */
|
||||
};
|
||||
|
||||
} // namepsace xmrstak
|
||||
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <cstdint>
|
||||
#include <climits>
|
||||
#include <iostream>
|
||||
|
||||
namespace xmrstak
|
||||
{
|
||||
// only allowed for unsigned value \todo add static assert
|
||||
template<typename T>
|
||||
T reverseBits(T value)
|
||||
{
|
||||
/* init with value (to get LSB) */
|
||||
T result = value;
|
||||
/* extra shift needed at end */
|
||||
int s = sizeof(T) * CHAR_BIT - 1;
|
||||
for (value >>= 1; value; value >>= 1)
|
||||
{
|
||||
result <<= 1;
|
||||
result |= value & 1;
|
||||
s--;
|
||||
}
|
||||
/* shift when values highest bits are zero */
|
||||
result <<= s;
|
||||
return result;
|
||||
}
|
||||
|
||||
struct miner_work
|
||||
{
|
||||
char sJobID[64];
|
||||
uint8_t bWorkBlob[112];
|
||||
uint32_t iWorkSize;
|
||||
uint32_t iResumeCnt;
|
||||
uint64_t iTarget;
|
||||
// \todo remove workaround needed for amd
|
||||
uint32_t iTarget32;
|
||||
bool bNiceHash;
|
||||
bool bStall;
|
||||
size_t iPoolId;
|
||||
|
||||
miner_work() : iWorkSize(0), bNiceHash(false), bStall(true), iPoolId(0) { }
|
||||
|
||||
miner_work(const char* sJobID, const uint8_t* bWork, uint32_t iWorkSize, uint32_t iResumeCnt,
|
||||
uint64_t iTarget, size_t iPoolId) : iWorkSize(iWorkSize), iResumeCnt(iResumeCnt),
|
||||
iTarget(iTarget), bNiceHash(false), 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;
|
||||
iTarget32 = from.iTarget32;
|
||||
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),iTarget32(from.iTarget32),
|
||||
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;
|
||||
iTarget32 = from.iTarget32;
|
||||
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;
|
||||
}
|
||||
};
|
||||
} // namepsace xmrstak
|
||||
Reference in New Issue
Block a user