mirror of
https://github.com/GOSTSec/sgminer
synced 2025-09-03 09:42:17 +00:00
Add command line parsing, and multiple threads.
This commit is contained in:
parent
45a29ac997
commit
5b6e9a92f1
2
Makefile
2
Makefile
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
CFLAGS= -O2 -Wall -g
|
CFLAGS= -O2 -Wall -g -march=native -pthread
|
||||||
|
|
||||||
PROG = minerd
|
PROG = minerd
|
||||||
|
|
||||||
|
148
cpu-miner.c
148
cpu-miner.c
@ -10,20 +10,47 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <argp.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
|
|
||||||
|
#define PROGRAM_NAME "minerd"
|
||||||
|
|
||||||
#include "sha256_generic.c"
|
#include "sha256_generic.c"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
POW_SLEEP_INTERVAL = 5,
|
STAT_SLEEP_INTERVAL = 10,
|
||||||
|
POW_SLEEP_INTERVAL = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const bool opt_verbose = false;
|
static bool opt_verbose;
|
||||||
static const bool opt_debug = false;
|
static bool opt_debug;
|
||||||
|
static bool program_running = true;
|
||||||
static const bool opt_time = true;
|
static const bool opt_time = true;
|
||||||
|
static int opt_n_threads = 1;
|
||||||
|
static pthread_mutex_t stats_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static uint64_t hash_ctr;
|
||||||
|
|
||||||
|
static struct argp_option options[] = {
|
||||||
|
{ "threads", 't', "N", 0,
|
||||||
|
"Number of miner threads" },
|
||||||
|
{ "debug", 'D', NULL, 0,
|
||||||
|
"Enable debug output" },
|
||||||
|
{ "verbose", 'v', NULL, 0,
|
||||||
|
"Enable verbose output" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char doc[] =
|
||||||
|
PROGRAM_NAME " - CPU miner for bitcoin";
|
||||||
|
|
||||||
|
static error_t parse_opt (int key, char *arg, struct argp_state *state);
|
||||||
|
|
||||||
|
static const struct argp argp = { options, parse_opt, NULL, doc };
|
||||||
|
|
||||||
struct data_buffer {
|
struct data_buffer {
|
||||||
void *buf;
|
void *buf;
|
||||||
@ -289,6 +316,15 @@ err_out:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void inc_stats(uint64_t n_hashes)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&stats_mutex);
|
||||||
|
|
||||||
|
hash_ctr += n_hashes;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&stats_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
#define ___constant_swab32(x) ((u32)( \
|
#define ___constant_swab32(x) ((u32)( \
|
||||||
(((u32)(x) & (u32)0x000000ffUL) << 24) | \
|
(((u32)(x) & (u32)0x000000ffUL) << 24) | \
|
||||||
(((u32)(x) & (u32)0x0000ff00UL) << 8) | \
|
(((u32)(x) & (u32)0x0000ff00UL) << 8) | \
|
||||||
@ -318,9 +354,6 @@ static uint32_t scanhash(unsigned char *midstate, unsigned char *data,
|
|||||||
uint32_t *hash32 = (uint32_t *) hash;
|
uint32_t *hash32 = (uint32_t *) hash;
|
||||||
uint32_t *nonce = (uint32_t *)(data + 12);
|
uint32_t *nonce = (uint32_t *)(data + 12);
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
time_t t_start;
|
|
||||||
|
|
||||||
t_start = time(NULL);
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
n = *nonce;
|
n = *nonce;
|
||||||
@ -344,15 +377,10 @@ static uint32_t scanhash(unsigned char *midstate, unsigned char *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((n & 0xffffff) == 0) {
|
if ((n & 0xffffff) == 0) {
|
||||||
time_t t_end = time(NULL);
|
inc_stats(n);
|
||||||
time_t diff = t_end - t_start;
|
|
||||||
long double nd = n;
|
if (opt_debug)
|
||||||
long double sd = diff;
|
fprintf(stderr, "DBG: end of nonce range\n");
|
||||||
if (opt_time) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"DBG: end of nonce range, %.2Lf khps\n",
|
|
||||||
(nd / sd) / 1000.0);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,7 +443,7 @@ out:
|
|||||||
free(hexstr);
|
free(hexstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int main_loop(void)
|
static void *miner_thread(void *dummy)
|
||||||
{
|
{
|
||||||
static const char *rpc_req =
|
static const char *rpc_req =
|
||||||
"{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
|
"{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
|
||||||
@ -429,7 +457,7 @@ static int main_loop(void)
|
|||||||
val = json_rpc_call(url, userpass, rpc_req);
|
val = json_rpc_call(url, userpass, rpc_req);
|
||||||
if (!val) {
|
if (!val) {
|
||||||
fprintf(stderr, "json_rpc_call failed\n");
|
fprintf(stderr, "json_rpc_call failed\n");
|
||||||
return 1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_verbose) {
|
if (opt_verbose) {
|
||||||
@ -442,7 +470,7 @@ static int main_loop(void)
|
|||||||
work = work_decode(json_object_get(val, "result"));
|
work = work_decode(json_object_get(val, "result"));
|
||||||
if (!work) {
|
if (!work) {
|
||||||
fprintf(stderr, "work decode failed\n");
|
fprintf(stderr, "work decode failed\n");
|
||||||
return 1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
json_decref(val);
|
json_decref(val);
|
||||||
@ -463,11 +491,91 @@ static int main_loop(void)
|
|||||||
work_free(work);
|
work_free(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static error_t parse_opt (int key, char *arg, struct argp_state *state)
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
|
||||||
|
switch(key) {
|
||||||
|
case 'v':
|
||||||
|
opt_verbose = true;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
opt_debug = true;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
v = atoi(arg);
|
||||||
|
if (v < 1 || v > 9999) /* sanity check */
|
||||||
|
argp_usage(state);
|
||||||
|
|
||||||
|
opt_n_threads = v;
|
||||||
|
break;
|
||||||
|
case ARGP_KEY_ARG:
|
||||||
|
argp_usage(state); /* too many args */
|
||||||
|
break;
|
||||||
|
case ARGP_KEY_END:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ARGP_ERR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void calc_stats(void)
|
||||||
|
{
|
||||||
|
uint64_t hashes;
|
||||||
|
long double hd, sd;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&stats_mutex);
|
||||||
|
|
||||||
|
hashes = hash_ctr;
|
||||||
|
hash_ctr = 0;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&stats_mutex);
|
||||||
|
|
||||||
|
hashes = hashes / 1000;
|
||||||
|
|
||||||
|
hd = hashes;
|
||||||
|
sd = STAT_SLEEP_INTERVAL;
|
||||||
|
|
||||||
|
fprintf(stderr, "wildly inaccurate HashMeter: %.2Lf khash/sec\n", hd / sd);
|
||||||
|
}
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
int main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
return main_loop();
|
error_t aprc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
aprc = argp_parse(&argp, argc, argv, 0, NULL, NULL);
|
||||||
|
if (aprc) {
|
||||||
|
fprintf(stderr, "argp_parse failed: %s\n", strerror(aprc));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setpriority(PRIO_PROCESS, 0, 19))
|
||||||
|
perror("setpriority");
|
||||||
|
|
||||||
|
for (i = 0; i < opt_n_threads; i++) {
|
||||||
|
pthread_t t;
|
||||||
|
|
||||||
|
if (pthread_create(&t, NULL, miner_thread, NULL)) {
|
||||||
|
fprintf(stderr, "thread %d create failed\n", i);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1); /* don't pound server all at once */
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "%d miner threads started.\n", opt_n_threads);
|
||||||
|
|
||||||
|
while (program_running) {
|
||||||
|
sleep(STAT_SLEEP_INTERVAL);
|
||||||
|
calc_stats();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user