Skip to content
Snippets Groups Projects
Commit 2cc79914 authored by psychocrypt's avatar psychocrypt
Browse files

add generic backend files

- add Plugin.h to load a backend
- add backend interface
parent 18a48e11
No related branches found
No related tags found
No related merge requests found
/*
* 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
#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
/*
* 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
#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
#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
#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
#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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment