Browse Source

Merge branch 'master' of https://github.com/ckolivas/cgminer.git

nfactor-troky
Paul Sheppard 12 years ago
parent
commit
df9e76bd73
  1. 5
      adl.c
  2. 12
      api.c
  3. 288
      cgminer.c
  4. 2
      driver-cpu.c
  5. 6
      driver-icarus.c
  6. 37
      driver-opencl.c
  7. 2
      driver-ztex.c
  8. 50
      fpgautils.c
  9. 20
      miner.h
  10. 111
      miner.php
  11. 17
      util.c

5
adl.c

@ -695,6 +695,11 @@ int gpu_fanpercent(int gpu)
applog(LOG_WARNING, "You will need to start cgminer from scratch to correct this"); applog(LOG_WARNING, "You will need to start cgminer from scratch to correct this");
applog(LOG_WARNING, "Disabling fanspeed monitoring on this device"); applog(LOG_WARNING, "Disabling fanspeed monitoring on this device");
ga->has_fanspeed = false; ga->has_fanspeed = false;
if (ga->twin) {
applog(LOG_WARNING, "Disabling fanspeed linking on GPU twins");
ga->twin->twin = NULL;;
ga->twin = NULL;
}
} }
return ret; return ret;
} }

12
api.c

@ -1636,10 +1636,7 @@ static void addpool(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
return; return;
} }
if (add_pool_details(true, url, user, pass) == ADD_POOL_MAXIMUM) { add_pool_details(true, url, user, pass);
strcpy(io_buffer, message(MSG_TOOMANYP, MAX_POOLS, NULL, isjson));
return;
}
ptr = escape_string(url, isjson); ptr = escape_string(url, isjson);
strcpy(io_buffer, message(MSG_ADDPOOL, 0, ptr, isjson)); strcpy(io_buffer, message(MSG_ADDPOOL, 0, ptr, isjson));
@ -2113,12 +2110,13 @@ static int itemstats(int i, char *id, struct cgminer_stats *stats, struct cgmine
if (pool_stats) { if (pool_stats) {
sprintf(buf, isjson sprintf(buf, isjson
? ",\"Pool Calls\":%d,\"Pool Attempts\":%d,\"Pool Wait\":%ld.%06ld,\"Pool Max\":%ld.%06ld,\"Pool Min\":%ld.%06ld" ? ",\"Pool Calls\":%d,\"Pool Attempts\":%d,\"Pool Wait\":%ld.%06ld,\"Pool Max\":%ld.%06ld,\"Pool Min\":%ld.%06ld,\"Pool Av\":%f"
: ",Pool Calls=%d,Pool Attempts=%d,Pool Wait=%ld.%06ld,Pool Max=%ld.%06ld,Pool Min=%ld.%06ld", : ",Pool Calls=%d,Pool Attempts=%d,Pool Wait=%ld.%06ld,Pool Max=%ld.%06ld,Pool Min=%ld.%06ld,Pool Av=%f",
pool_stats->getwork_calls, pool_stats->getwork_attempts, pool_stats->getwork_calls, pool_stats->getwork_attempts,
pool_stats->getwork_wait.tv_sec, pool_stats->getwork_wait.tv_usec, pool_stats->getwork_wait.tv_sec, pool_stats->getwork_wait.tv_usec,
pool_stats->getwork_wait_max.tv_sec, pool_stats->getwork_wait_max.tv_usec, pool_stats->getwork_wait_max.tv_sec, pool_stats->getwork_wait_max.tv_usec,
pool_stats->getwork_wait_min.tv_sec, pool_stats->getwork_wait_min.tv_usec); pool_stats->getwork_wait_min.tv_sec, pool_stats->getwork_wait_min.tv_usec,
pool_stats->getwork_wait_rolling);
strcat(io_buffer, buf); strcat(io_buffer, buf);
} }

288
cgminer.c

@ -116,7 +116,7 @@ struct list_head scan_devices;
static signed int devices_enabled; static signed int devices_enabled;
static bool opt_removedisabled; static bool opt_removedisabled;
int total_devices; int total_devices;
struct cgpu_info *devices[MAX_DEVICES]; struct cgpu_info **devices;
bool have_opencl; bool have_opencl;
int opt_n_threads = -1; int opt_n_threads = -1;
int mining_threads; int mining_threads;
@ -190,7 +190,7 @@ unsigned int found_blocks;
unsigned int local_work; unsigned int local_work;
unsigned int total_go, total_ro; unsigned int total_go, total_ro;
struct pool *pools[MAX_POOLS]; struct pool **pools;
static struct pool *currentpool = NULL; static struct pool *currentpool = NULL;
int total_pools; int total_pools;
@ -395,6 +395,7 @@ static struct pool *add_pool(void)
if (!pool) if (!pool)
quit(1, "Failed to malloc pool in add_pool"); quit(1, "Failed to malloc pool in add_pool");
pool->pool_no = pool->prio = total_pools; pool->pool_no = pool->prio = total_pools;
pools = realloc(pools, sizeof(struct pool *) * (total_pools + 2));
pools[total_pools++] = pool; pools[total_pools++] = pool;
if (unlikely(pthread_mutex_init(&pool->pool_lock, NULL))) if (unlikely(pthread_mutex_init(&pool->pool_lock, NULL)))
quit(1, "Failed to pthread_mutex_init in add_pool"); quit(1, "Failed to pthread_mutex_init in add_pool");
@ -1622,7 +1623,7 @@ static bool submit_upstream_work(const struct work *work, CURL *curl)
int thr_id = work->thr_id; int thr_id = work->thr_id;
struct cgpu_info *cgpu = thr_info[thr_id].cgpu; struct cgpu_info *cgpu = thr_info[thr_id].cgpu;
struct pool *pool = work->pool; struct pool *pool = work->pool;
bool rolltime; int rolltime;
uint32_t *hash32; uint32_t *hash32;
char hashshow[64+1] = ""; char hashshow[64+1] = "";
@ -1837,16 +1838,15 @@ static bool get_upstream_work(struct work *work, CURL *curl)
url = pool->rpc_url; url = pool->rpc_url;
gettimeofday(&tv_start, NULL);
retry: retry:
/* A single failure response here might be reported as a dead pool and /* A single failure response here might be reported as a dead pool and
* there may be temporary denied messages etc. falsely reporting * there may be temporary denied messages etc. falsely reporting
* failure so retry a few times before giving up */ * failure so retry a few times before giving up */
while (!val && retries++ < 3) { while (!val && retries++ < 3) {
pool_stats->getwork_attempts++; pool_stats->getwork_attempts++;
gettimeofday(&tv_start, NULL);
val = json_rpc_call(curl, url, pool->rpc_userpass, rpc_req, val = json_rpc_call(curl, url, pool->rpc_userpass, rpc_req,
false, false, &work->rolltime, pool, false); false, false, &work->rolltime, pool, false);
gettimeofday(&tv_end, NULL);
} }
if (unlikely(!val)) { if (unlikely(!val)) {
applog(LOG_DEBUG, "Failed json_rpc_call in get_upstream_work"); applog(LOG_DEBUG, "Failed json_rpc_call in get_upstream_work");
@ -1856,12 +1856,12 @@ retry:
rc = work_decode(json_object_get(val, "result"), work); rc = work_decode(json_object_get(val, "result"), work);
if (!rc && retries < 3) if (!rc && retries < 3)
goto retry; goto retry;
work->pool = pool;
work->longpoll = false;
total_getworks++;
pool->getwork_requested++;
gettimeofday(&tv_end, NULL);
timersub(&tv_end, &tv_start, &tv_elapsed); timersub(&tv_end, &tv_start, &tv_elapsed);
pool_stats->getwork_wait_rolling += ((double)tv_elapsed.tv_sec + ((double)tv_elapsed.tv_usec / 1000000)) * 0.63;
pool_stats->getwork_wait_rolling /= 1.63;
timeradd(&tv_elapsed, &(pool_stats->getwork_wait), &(pool_stats->getwork_wait)); timeradd(&tv_elapsed, &(pool_stats->getwork_wait), &(pool_stats->getwork_wait));
if (timercmp(&tv_elapsed, &(pool_stats->getwork_wait_max), >)) { if (timercmp(&tv_elapsed, &(pool_stats->getwork_wait_max), >)) {
pool_stats->getwork_wait_max.tv_sec = tv_elapsed.tv_sec; pool_stats->getwork_wait_max.tv_sec = tv_elapsed.tv_sec;
@ -1873,6 +1873,11 @@ retry:
} }
pool_stats->getwork_calls++; pool_stats->getwork_calls++;
work->pool = pool;
work->longpoll = false;
total_getworks++;
pool->getwork_requested++;
json_decref(val); json_decref(val);
out: out:
@ -2154,22 +2159,37 @@ static bool workio_get_work(struct workio_cmd *wc)
static bool stale_work(struct work *work, bool share) static bool stale_work(struct work *work, bool share)
{ {
struct timeval now; struct timeval now;
time_t work_expiry;
struct pool *pool; struct pool *pool;
int getwork_delay;
if (work->mandatory) if (work->mandatory)
return false; return false;
if (share)
work_expiry = opt_expiry;
else if (work->rolltime)
work_expiry = work->rolltime;
else
work_expiry = opt_scantime;
pool = work->pool;
/* Factor in the average getwork delay of this pool, rounding it up to
* the nearest second */
getwork_delay = pool->cgminer_pool_stats.getwork_wait_rolling * 5 + 1;
if (!share) {
work_expiry -= getwork_delay;
if (unlikely(work_expiry < 5))
work_expiry = 5;
} else
work_expiry += getwork_delay;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
if (share) { if ((now.tv_sec - work->tv_staged.tv_sec) >= work_expiry)
if ((now.tv_sec - work->tv_staged.tv_sec) >= opt_expiry)
return true;
} else if ((now.tv_sec - work->tv_staged.tv_sec) >= opt_scantime)
return true; return true;
if (work->work_block != work_block) if (work->work_block != work_block)
return true; return true;
pool = work->pool;
if (opt_fail_only && !share && pool != current_pool() && pool->enabled != POOL_REJECTING) if (opt_fail_only && !share && pool != current_pool() && pool->enabled != POOL_REJECTING)
return true; return true;
@ -2379,8 +2399,11 @@ static void inc_queued(void)
mutex_unlock(&qd_lock); mutex_unlock(&qd_lock);
} }
static void dec_queued(void) static void dec_queued(struct work *work)
{ {
if (work->clone)
return;
mutex_lock(&qd_lock); mutex_lock(&qd_lock);
if (total_queued > 0) if (total_queued > 0)
total_queued--; total_queued--;
@ -2397,17 +2420,28 @@ static int requests_queued(void)
return ret; return ret;
} }
static int discard_stale(void) static void subtract_queued(int work_units)
{
mutex_lock(&qd_lock);
total_queued -= work_units;
if (total_queued < 0)
total_queued = 0;
mutex_unlock(&qd_lock);
}
static void discard_stale(void)
{ {
struct work *work, *tmp; struct work *work, *tmp;
int i, stale = 0; int stale = 0, nonclone = 0;
mutex_lock(stgd_lock); mutex_lock(stgd_lock);
HASH_ITER(hh, staged_work, work, tmp) { HASH_ITER(hh, staged_work, work, tmp) {
if (stale_work(work, false)) { if (stale_work(work, false)) {
HASH_DEL(staged_work, work); HASH_DEL(staged_work, work);
if (work->clone || work->longpoll) if (work->clone)
--staged_extras; --staged_extras;
else
nonclone++;
discard_work(work); discard_work(work);
stale++; stale++;
} }
@ -2417,22 +2451,18 @@ static int discard_stale(void)
applog(LOG_DEBUG, "Discarded %d stales that didn't match current hash", stale); applog(LOG_DEBUG, "Discarded %d stales that didn't match current hash", stale);
/* Dec queued outside the loop to not have recursive locks */ /* Dec queued outside the loop to not have recursive locks */
for (i = 0; i < stale; i++) subtract_queued(nonclone);
dec_queued();
return stale;
} }
static bool queue_request(struct thr_info *thr, bool needed); static bool queue_request(struct thr_info *thr, bool needed);
static void restart_threads(void) static void restart_threads(void)
{ {
int i, stale; int i;
/* Discard staged work that is now stale */ /* Discard staged work that is now stale */
stale = discard_stale(); discard_stale();
for (i = 0; i < stale; i++)
queue_request(NULL, true); queue_request(NULL, true);
for (i = 0; i < mining_threads; i++) for (i = 0; i < mining_threads; i++)
@ -2556,7 +2586,7 @@ static bool hash_push(struct work *work)
if (likely(!getq->frozen)) { if (likely(!getq->frozen)) {
HASH_ADD_INT(staged_work, id, work); HASH_ADD_INT(staged_work, id, work);
HASH_SORT(staged_work, tv_sort); HASH_SORT(staged_work, tv_sort);
if (work->clone || work->longpoll) if (work->clone)
++staged_extras; ++staged_extras;
} else } else
rc = false; rc = false;
@ -3385,7 +3415,7 @@ static bool pool_active(struct pool *pool, bool pinging)
bool ret = false; bool ret = false;
json_t *val; json_t *val;
CURL *curl; CURL *curl;
bool rolltime; int rolltime;
curl = curl_easy_init(); curl = curl_easy_init();
if (unlikely(!curl)) { if (unlikely(!curl)) {
@ -3493,39 +3523,78 @@ static void pool_resus(struct pool *pool)
switch_pools(NULL); switch_pools(NULL);
} }
static long requested_tv_sec; static time_t requested_tv_sec;
static bool control_tset(bool *var)
{
bool ret;
mutex_lock(&control_lock);
ret = *var;
*var = true;
mutex_unlock(&control_lock);
return ret;
}
static void control_tclear(bool *var)
{
mutex_lock(&control_lock);
*var = false;
mutex_unlock(&control_lock);
}
static bool queueing;
static bool queue_request(struct thr_info *thr, bool needed) static bool queue_request(struct thr_info *thr, bool needed)
{ {
int rq = requests_queued();
struct workio_cmd *wc; struct workio_cmd *wc;
struct timeval now; struct timeval now;
time_t scan_post;
int rq, rs;
bool ret = true;
/* Prevent multiple requests being executed at once */
if (control_tset(&queueing))
return ret;
rq = requests_queued();
rs = requests_staged();
/* Grab more work every 2/3 of the scan time to avoid all work expiring
* at the same time */
scan_post = opt_scantime * 2 / 3;
if (scan_post < 5)
scan_post = 5;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
/* Space out retrieval of extra work according to the number of mining /* Test to make sure we have enough work for pools without rolltime
* threads */ * and enough original work for pools with rolltime */
if (rq >= mining_threads + staged_extras && if ((rq >= mining_threads || rs >= mining_threads) &&
(now.tv_sec - requested_tv_sec) < opt_scantime / (mining_threads + 1)) rq > staged_extras + opt_queue &&
return true; now.tv_sec - requested_tv_sec < scan_post)
goto out;
requested_tv_sec = now.tv_sec;
inc_queued();
/* fill out work request message */ /* fill out work request message */
wc = calloc(1, sizeof(*wc)); wc = calloc(1, sizeof(*wc));
if (unlikely(!wc)) { if (unlikely(!wc)) {
applog(LOG_ERR, "Failed to calloc wc in queue_request"); applog(LOG_ERR, "Failed to calloc wc in queue_request");
return false; ret = false;
goto out;
} }
wc->cmd = WC_GET_WORK; wc->cmd = WC_GET_WORK;
if (thr)
wc->thr = thr; wc->thr = thr;
else
wc->thr = NULL;
/* If we're queueing work faster than we can stage it, consider the /* If we're queueing work faster than we can stage it, consider the
* system lagging and allow work to be gathered from another pool if * system lagging and allow work to be gathered from another pool if
* possible */ * possible */
if (rq && needed && !requests_staged() && !opt_fail_only) if (rq && needed && !rs && !opt_fail_only)
wc->lagging = true; wc->lagging = true;
applog(LOG_DEBUG, "Queueing getwork request to work thread"); applog(LOG_DEBUG, "Queueing getwork request to work thread");
@ -3534,12 +3603,13 @@ static bool queue_request(struct thr_info *thr, bool needed)
if (unlikely(!tq_push(thr_info[work_thr_id].q, wc))) { if (unlikely(!tq_push(thr_info[work_thr_id].q, wc))) {
applog(LOG_ERR, "Failed to tq_push in queue_request"); applog(LOG_ERR, "Failed to tq_push in queue_request");
workio_cmd_free(wc); workio_cmd_free(wc);
return false; ret = false;
} }
requested_tv_sec = now.tv_sec; out:
inc_queued(); control_tclear(&queueing);
return true;
return ret;
} }
static struct work *hash_pop(const struct timespec *abstime) static struct work *hash_pop(const struct timespec *abstime)
@ -3554,7 +3624,7 @@ static struct work *hash_pop(const struct timespec *abstime)
if (HASH_COUNT(staged_work)) { if (HASH_COUNT(staged_work)) {
work = staged_work; work = staged_work;
HASH_DEL(staged_work, work); HASH_DEL(staged_work, work);
if (work->clone || work->longpoll) if (work->clone)
--staged_extras; --staged_extras;
} }
mutex_unlock(stgd_lock); mutex_unlock(stgd_lock);
@ -3571,8 +3641,7 @@ static inline bool should_roll(struct work *work)
static inline bool can_roll(struct work *work) static inline bool can_roll(struct work *work)
{ {
return (work->pool && !stale_work(work, false) && work->rolltime && return (work->pool && !stale_work(work, false) && work->rolltime && !work->clone);
work->rolls < 11 && !work->clone);
} }
static void roll_work(struct work *work) static void roll_work(struct work *work)
@ -3603,6 +3672,58 @@ static bool reuse_work(struct work *work)
return false; return false;
} }
static struct work *make_clone(struct work *work)
{
struct work *work_clone = make_work();
memcpy(work_clone, work, sizeof(struct work));
work_clone->clone = true;
work_clone->longpoll = false;
/* Make cloned work appear slightly older to bias towards keeping the
* master work item which can be further rolled */
work_clone->tv_staged.tv_sec -= 1;
return work_clone;
}
/* Clones work by rolling it if possible, and returning a clone instead of the
* original work item which gets staged again to possibly be rolled again in
* the future */
static struct work *clone_work(struct work *work)
{
int mrs = mining_threads - requests_staged();
struct work *work_clone;
bool cloned;
if (mrs < 1)
return work;
cloned = false;
work_clone = make_clone(work);
while (mrs-- > 0 && can_roll(work) && should_roll(work)) {
applog(LOG_DEBUG, "Pushing rolled converted work to stage thread");
if (unlikely(!stage_work(work_clone))) {
cloned = false;
break;
}
roll_work(work);
work_clone = make_clone(work);
/* Roll it again to prevent duplicates should this be used
* directly later on */
roll_work(work);
cloned = true;
}
if (cloned) {
stage_work(work);
return work_clone;
}
free_work(work_clone);
return work;
}
static bool get_work(struct work *work, bool requested, struct thr_info *thr, static bool get_work(struct work *work, bool requested, struct thr_info *thr,
const int thr_id) const int thr_id)
{ {
@ -3674,7 +3795,7 @@ retry:
} }
if (stale_work(work_heap, false)) { if (stale_work(work_heap, false)) {
dec_queued(); dec_queued(work_heap);
discard_work(work_heap); discard_work(work_heap);
goto retry; goto retry;
} }
@ -3687,18 +3808,10 @@ retry:
pool_resus(pool); pool_resus(pool);
} }
memcpy(work, work_heap, sizeof(*work)); work_heap = clone_work(work_heap);
memcpy(work, work_heap, sizeof(struct work));
/* Hand out a clone if we can roll this work item */ dec_queued(work_heap);
if (reuse_work(work_heap)) {
applog(LOG_DEBUG, "Pushing divided work to get queue head");
stage_work(work_heap);
work->clone = true;
} else {
dec_queued();
free_work(work_heap); free_work(work_heap);
}
ret = true; ret = true;
out: out:
@ -4023,9 +4136,9 @@ enum {
}; };
/* Stage another work item from the work returned in a longpoll */ /* Stage another work item from the work returned in a longpoll */
static void convert_to_work(json_t *val, bool rolltime, struct pool *pool) static void convert_to_work(json_t *val, int rolltime, struct pool *pool)
{ {
struct work *work, *work_clone; struct work *work;
bool rc; bool rc;
work = make_work(); work = make_work();
@ -4058,25 +4171,16 @@ static void convert_to_work(json_t *val, bool rolltime, struct pool *pool)
return; return;
} }
work_clone = make_work(); work = clone_work(work);
memcpy(work_clone, work, sizeof(struct work));
while (reuse_work(work)) {
work_clone->clone = true;
work_clone->longpoll = false;
applog(LOG_DEBUG, "Pushing rolled converted work to stage thread");
if (unlikely(!stage_work(work_clone)))
break;
work_clone = make_work();
memcpy(work_clone, work, sizeof(struct work));
}
free_work(work_clone);
applog(LOG_DEBUG, "Pushing converted work to stage thread"); applog(LOG_DEBUG, "Pushing converted work to stage thread");
if (unlikely(!stage_work(work))) if (unlikely(!stage_work(work)))
free_work(work); free_work(work);
else else {
inc_queued();
applog(LOG_DEBUG, "Converted longpoll data to work"); applog(LOG_DEBUG, "Converted longpoll data to work");
}
} }
/* If we want longpoll, enable it for the chosen default pool, or, if /* If we want longpoll, enable it for the chosen default pool, or, if
@ -4121,7 +4225,7 @@ static void *longpoll_thread(void *userdata)
struct timeval start, end; struct timeval start, end;
CURL *curl = NULL; CURL *curl = NULL;
int failures = 0; int failures = 0;
bool rolltime; int rolltime;
curl = curl_easy_init(); curl = curl_easy_init();
if (unlikely(!curl)) { if (unlikely(!curl)) {
@ -4272,6 +4376,23 @@ static void *watchpool_thread(void __maybe_unused *userdata)
return NULL; return NULL;
} }
/* Work is sorted according to age, so discard the oldest work items, leaving
* only 1 staged work item per mining thread */
static void age_work(void)
{
int discarded = 0;
while (requests_staged() > mining_threads * 4 / 3 + opt_queue) {
struct work *work = hash_pop(NULL);
if (unlikely(!work))
break;
discard_work(work);
discarded++;
}
if (discarded)
applog(LOG_DEBUG, "Aged %d work items", discarded);
}
/* Makes sure the hashmeter keeps going even if mining threads stall, updates /* Makes sure the hashmeter keeps going even if mining threads stall, updates
* the screen at regular intervals, and restarts threads if they appear to have * the screen at regular intervals, and restarts threads if they appear to have
@ -4294,6 +4415,8 @@ static void *watchdog_thread(void __maybe_unused *userdata)
if (requests_queued() < opt_queue) if (requests_queued() < opt_queue)
queue_request(NULL, false); queue_request(NULL, false);
age_work();
hashmeter(-1, &zero_tv, 0); hashmeter(-1, &zero_tv, 0);
#ifdef HAVE_CURSES #ifdef HAVE_CURSES
@ -4581,13 +4704,10 @@ char *curses_input(const char *query)
} }
#endif #endif
int add_pool_details(bool live, char *url, char *user, char *pass) void add_pool_details(bool live, char *url, char *user, char *pass)
{ {
struct pool *pool; struct pool *pool;
if (total_pools == MAX_POOLS)
return ADD_POOL_MAXIMUM;
pool = add_pool(); pool = add_pool();
pool->rpc_url = url; pool->rpc_url = url;
@ -4603,8 +4723,6 @@ int add_pool_details(bool live, char *url, char *user, char *pass)
pool->enabled = POOL_ENABLED; pool->enabled = POOL_ENABLED;
if (live && !pool_active(pool, false)) if (live && !pool_active(pool, false))
pool->idle = true; pool->idle = true;
return ADD_POOL_OK;
} }
#ifdef HAVE_CURSES #ifdef HAVE_CURSES
@ -4614,10 +4732,6 @@ static bool input_pool(bool live)
bool ret = false; bool ret = false;
immedok(logwin, true); immedok(logwin, true);
if (total_pools == MAX_POOLS) {
wlogprint("Reached maximum number of pools.\n");
goto out;
}
wlogprint("Input server details.\n"); wlogprint("Input server details.\n");
url = curses_input("URL"); url = curses_input("URL");
@ -4645,7 +4759,8 @@ static bool input_pool(bool live)
if (!pass) if (!pass)
goto out; goto out;
ret = (add_pool_details(live, url, user, pass) == ADD_POOL_OK); add_pool_details(live, url, user, pass);
ret = true;
out: out:
immedok(logwin, false); immedok(logwin, false);
@ -4815,6 +4930,7 @@ bool add_cgpu(struct cgpu_info*cgpu)
cgpu->device_id = d->lastid = 0; cgpu->device_id = d->lastid = 0;
HASH_ADD_STR(devids, name, d); HASH_ADD_STR(devids, name, d);
} }
devices = realloc(devices, sizeof(struct cgpu_info *) * (total_devices + 2));
devices[total_devices++] = cgpu; devices[total_devices++] = cgpu;
return true; return true;
} }
@ -4904,8 +5020,6 @@ int main(int argc, char *argv[])
gpus[i].dynamic = true; gpus[i].dynamic = true;
#endif #endif
memset(devices, 0, sizeof(devices));
/* parse command line */ /* parse command line */
opt_register_table(opt_config_table, opt_register_table(opt_config_table,
"Options for both config file and command line"); "Options for both config file and command line");

2
driver-cpu.c

@ -731,8 +731,6 @@ static void cpu_detect()
if (num_processors < 1) if (num_processors < 1)
return; return;
if (total_devices + opt_n_threads > MAX_DEVICES)
opt_n_threads = MAX_DEVICES - total_devices;
cpus = calloc(opt_n_threads, sizeof(struct cgpu_info)); cpus = calloc(opt_n_threads, sizeof(struct cgpu_info));
if (unlikely(!cpus)) if (unlikely(!cpus))
quit(1, "Failed to calloc cpus"); quit(1, "Failed to calloc cpus");

6
driver-icarus.c

@ -179,7 +179,7 @@ struct ICARUS_INFO {
}; };
// One for each possible device // One for each possible device
static struct ICARUS_INFO *icarus_info[MAX_DEVICES]; static struct ICARUS_INFO **icarus_info;
struct device_api icarus_api; struct device_api icarus_api;
@ -421,15 +421,15 @@ static bool icarus_detect_one(const char *devpath)
icarus->device_path = strdup(devpath); icarus->device_path = strdup(devpath);
icarus->threads = 1; icarus->threads = 1;
add_cgpu(icarus); add_cgpu(icarus);
icarus_info = realloc(icarus_info, sizeof(struct ICARUS_INFO *) * (total_devices + 1));
applog(LOG_INFO, "Found Icarus at %s, mark as %d", applog(LOG_INFO, "Found Icarus at %s, mark as %d",
devpath, icarus->device_id); devpath, icarus->device_id);
if (icarus_info[icarus->device_id] == NULL) { // Since we are adding a new device on the end it needs to always be allocated
icarus_info[icarus->device_id] = (struct ICARUS_INFO *)malloc(sizeof(struct ICARUS_INFO)); icarus_info[icarus->device_id] = (struct ICARUS_INFO *)malloc(sizeof(struct ICARUS_INFO));
if (unlikely(!(icarus_info[icarus->device_id]))) if (unlikely(!(icarus_info[icarus->device_id])))
quit(1, "Failed to malloc ICARUS_INFO"); quit(1, "Failed to malloc ICARUS_INFO");
}
info = icarus_info[icarus->device_id]; info = icarus_info[icarus->device_id];

37
driver-opencl.c

@ -538,15 +538,11 @@ struct cgpu_info *cpus;
void pause_dynamic_threads(int gpu) void pause_dynamic_threads(int gpu)
{ {
struct cgpu_info *cgpu = &gpus[gpu]; struct cgpu_info *cgpu = &gpus[gpu];
int i, thread_no = 0; int i;
for (i = 0; i < mining_threads; i++) { for (i = 1; i < cgpu->threads; i++) {
struct thr_info *thr = &thr_info[i]; struct thr_info *thr = &thr_info[i];
if (thr->cgpu != cgpu)
continue;
if (!thread_no++)
continue;
if (!thr->pause && cgpu->dynamic) { if (!thr->pause && cgpu->dynamic) {
applog(LOG_WARNING, "Disabling extra threads due to dynamic mode."); applog(LOG_WARNING, "Disabling extra threads due to dynamic mode.");
applog(LOG_WARNING, "Tune dynamic intensity with --gpu-dyninterval"); applog(LOG_WARNING, "Tune dynamic intensity with --gpu-dyninterval");
@ -1130,9 +1126,6 @@ static void opencl_detect()
nDevs = 0; nDevs = 0;
} }
if (MAX_DEVICES - total_devices < nDevs)
nDevs = MAX_DEVICES - total_devices;
if (!nDevs) if (!nDevs)
return; return;
@ -1354,34 +1347,32 @@ static uint64_t opencl_scanhash(struct thr_info *thr, struct work *work,
_clState *clState = clStates[thr_id]; _clState *clState = clStates[thr_id];
const cl_kernel *kernel = &clState->kernel; const cl_kernel *kernel = &clState->kernel;
double gpu_ms_average = 7;
cl_int status; cl_int status;
size_t globalThreads[1]; size_t globalThreads[1];
size_t localThreads[1] = { clState->wsize }; size_t localThreads[1] = { clState->wsize };
unsigned int threads; unsigned int threads;
unsigned int hashes; unsigned int hashes;
gettimeofday(&gpu->tv_gpustart, NULL);
struct timeval tv_gpustart, tv_gpuend, diff;
suseconds_t gpu_us;
gettimeofday(&tv_gpustart, NULL);
timeval_subtract(&diff, &tv_gpustart, &tv_gpuend);
/* This finish flushes the readbuffer set with CL_FALSE later */ /* This finish flushes the readbuffer set with CL_FALSE later */
clFinish(clState->commandQueue); clFinish(clState->commandQueue);
gettimeofday(&tv_gpuend, NULL); gettimeofday(&gpu->tv_gpuend, NULL);
timeval_subtract(&diff, &tv_gpuend, &tv_gpustart);
gpu_us = diff.tv_sec * 1000000 + diff.tv_usec;
decay_time(&gpu_ms_average, gpu_us / 1000);
if (gpu->dynamic) { if (gpu->dynamic) {
struct timeval diff;
suseconds_t gpu_ms;
timersub(&gpu->tv_gpuend, &gpu->tv_gpustart, &diff);
gpu_ms = diff.tv_sec * 1000 + diff.tv_usec / 1000;
gpu->gpu_ms_average = (gpu->gpu_ms_average + gpu_ms * 0.63) / 1.63;
/* Try to not let the GPU be out for longer than 6ms, but /* Try to not let the GPU be out for longer than 6ms, but
* increase intensity when the system is idle, unless * increase intensity when the system is idle, unless
* dynamic is disabled. */ * dynamic is disabled. */
if (gpu_ms_average > opt_dynamic_interval) { if (gpu->gpu_ms_average > opt_dynamic_interval) {
if (gpu->intensity > MIN_INTENSITY) if (gpu->intensity > MIN_INTENSITY)
--gpu->intensity; --gpu->intensity;
} else if (gpu_ms_average < ((opt_dynamic_interval / 2) ? : 1)) { } else if (gpu->gpu_ms_average < ((opt_dynamic_interval / 2) ? : 1)) {
if (gpu->intensity < MAX_INTENSITY) if (gpu->intensity < MAX_INTENSITY)
++gpu->intensity; ++gpu->intensity;
} }

2
driver-ztex.c

@ -66,8 +66,6 @@ static void ztex_detect(void)
applog(LOG_WARNING, "Found %d ztex board(s)", cnt); applog(LOG_WARNING, "Found %d ztex board(s)", cnt);
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
if (total_devices == MAX_DEVICES)
break;
ztex = calloc(1, sizeof(struct cgpu_info)); ztex = calloc(1, sizeof(struct cgpu_info));
ztex->api = &ztex_api; ztex->api = &ztex_api;
ztex->device_ztex = ztex_devices[i]->dev; ztex->device_ztex = ztex_devices[i]->dev;

50
fpgautils.c

@ -40,9 +40,6 @@
char char
serial_autodetect_udev(detectone_func_t detectone, const char*prodname) serial_autodetect_udev(detectone_func_t detectone, const char*prodname)
{ {
if (total_devices == MAX_DEVICES)
return 0;
struct udev *udev = udev_new(); struct udev *udev = udev_new();
struct udev_enumerate *enumerate = udev_enumerate_new(udev); struct udev_enumerate *enumerate = udev_enumerate_new(udev);
struct udev_list_entry *list_entry; struct udev_list_entry *list_entry;
@ -64,9 +61,6 @@ serial_autodetect_udev(detectone_func_t detectone, const char*prodname)
++found; ++found;
udev_device_unref(device); udev_device_unref(device);
if (total_devices == MAX_DEVICES)
break;
} }
udev_enumerate_unref(enumerate); udev_enumerate_unref(enumerate);
udev_unref(udev); udev_unref(udev);
@ -85,9 +79,6 @@ char
serial_autodetect_devserial(detectone_func_t detectone, const char*prodname) serial_autodetect_devserial(detectone_func_t detectone, const char*prodname)
{ {
#ifndef WIN32 #ifndef WIN32
if (total_devices == MAX_DEVICES)
return 0;
DIR *D; DIR *D;
struct dirent *de; struct dirent *de;
const char udevdir[] = "/dev/serial/by-id"; const char udevdir[] = "/dev/serial/by-id";
@ -104,11 +95,8 @@ serial_autodetect_devserial(detectone_func_t detectone, const char*prodname)
if (!strstr(de->d_name, prodname)) if (!strstr(de->d_name, prodname))
continue; continue;
strcpy(devfile, de->d_name); strcpy(devfile, de->d_name);
if (detectone(devpath)) { if (detectone(devpath))
++found; ++found;
if (total_devices == MAX_DEVICES)
break;
}
} }
closedir(D); closedir(D);
@ -121,9 +109,6 @@ serial_autodetect_devserial(detectone_func_t detectone, const char*prodname)
char char
_serial_detect(const char*dname, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto) _serial_detect(const char*dname, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto)
{ {
if (total_devices == MAX_DEVICES)
return 0;
struct string_elist *iter, *tmp; struct string_elist *iter, *tmp;
const char*s, *p; const char*s, *p;
bool inhibitauto = false; bool inhibitauto = false;
@ -148,12 +133,10 @@ _serial_detect(const char*dname, detectone_func_t detectone, autoscan_func_t aut
string_elist_del(iter); string_elist_del(iter);
inhibitauto = true; inhibitauto = true;
++found; ++found;
if (total_devices == MAX_DEVICES)
break;
} }
} }
if ((forceauto || !inhibitauto) && autoscan && total_devices < MAX_DEVICES) if ((forceauto || !inhibitauto) && autoscan)
found += autoscan(); found += autoscan();
return found; return found;
@ -198,28 +181,33 @@ serial_open(const char*devpath, unsigned long baud, signed short timeout, bool p
if (unlikely(fdDev == -1)) if (unlikely(fdDev == -1))
return -1; return -1;
struct termios pattr; struct termios my_termios;
tcgetattr(fdDev, &pattr);
pattr.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); tcgetattr(fdDev, &my_termios);
pattr.c_oflag &= ~OPOST;
pattr.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
pattr.c_cflag &= ~(CSIZE | PARENB);
pattr.c_cflag |= CS8;
switch (baud) { switch (baud) {
case 0: break; case 0: break;
case 115200: pattr.c_cflag = B115200; break; case 115200: my_termios.c_cflag = B115200; break;
default: default:
applog(LOG_WARNING, "Unrecognized baud rate: %lu", baud); applog(LOG_WARNING, "Unrecognized baud rate: %lu", baud);
} }
pattr.c_cflag |= CREAD | CLOCAL;
my_termios.c_cflag |= CS8;
my_termios.c_cflag |= CREAD;
my_termios.c_cflag |= CLOCAL;
my_termios.c_cflag &= ~(CSIZE | PARENB);
my_termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK |
ISTRIP | INLCR | IGNCR | ICRNL | IXON);
my_termios.c_oflag &= ~OPOST;
my_termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
if (timeout >= 0) { if (timeout >= 0) {
pattr.c_cc[VTIME] = (cc_t)timeout; my_termios.c_cc[VTIME] = (cc_t)timeout;
pattr.c_cc[VMIN] = 0; my_termios.c_cc[VMIN] = 0;
} }
tcsetattr(fdDev, TCSANOW, &pattr); tcsetattr(fdDev, TCSANOW, &my_termios);
if (purge) if (purge)
tcflush(fdDev, TCIOFLUSH); tcflush(fdDev, TCIOFLUSH);
return fdDev; return fdDev;

20
miner.h

@ -300,6 +300,7 @@ struct cgminer_pool_stats {
struct timeval getwork_wait; struct timeval getwork_wait;
struct timeval getwork_wait_max; struct timeval getwork_wait_max;
struct timeval getwork_wait_min; struct timeval getwork_wait_min;
double getwork_wait_rolling;
}; };
struct cgpu_info { struct cgpu_info {
@ -347,6 +348,10 @@ struct cgpu_info {
cl_uint vwidth; cl_uint vwidth;
size_t work_size; size_t work_size;
enum cl_kernels kernel; enum cl_kernels kernel;
struct timeval tv_gpustart;;
struct timeval tv_gpuend;
double gpu_ms_average;
#endif #endif
float temp; float temp;
@ -537,7 +542,7 @@ extern pthread_rwlock_t netacc_lock;
extern const uint32_t sha256_init_state[]; extern const uint32_t sha256_init_state[];
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
const char *rpc_req, bool, bool, bool *, const char *rpc_req, bool, bool, int *,
struct pool *pool, bool); struct pool *pool, bool);
extern char *bin2hex(const unsigned char *p, size_t len); extern char *bin2hex(const unsigned char *p, size_t len);
extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len); extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
@ -580,14 +585,9 @@ extern void api(int thr_id);
extern struct pool *current_pool(void); extern struct pool *current_pool(void);
extern int active_pools(void); extern int active_pools(void);
extern int add_pool_details(bool live, char *url, char *user, char *pass); extern void add_pool_details(bool live, char *url, char *user, char *pass);
#define ADD_POOL_MAXIMUM 1
#define ADD_POOL_OK 0
#define MAX_GPUDEVICES 16 #define MAX_GPUDEVICES 16
#define MAX_DEVICES 64
#define MAX_POOLS (32)
#define MIN_INTENSITY -10 #define MIN_INTENSITY -10
#define _MIN_INTENSITY_STR "-10" #define _MIN_INTENSITY_STR "-10"
@ -608,9 +608,9 @@ extern double total_secs;
extern int mining_threads; extern int mining_threads;
extern struct cgpu_info *cpus; extern struct cgpu_info *cpus;
extern int total_devices; extern int total_devices;
extern struct cgpu_info *devices[]; extern struct cgpu_info **devices;
extern int total_pools; extern int total_pools;
extern struct pool *pools[MAX_POOLS]; extern struct pool **pools;
extern const char *algo_names[]; extern const char *algo_names[];
extern enum sha256_algos opt_algo; extern enum sha256_algos opt_algo;
extern struct strategies strategies[]; extern struct strategies strategies[];
@ -739,7 +739,7 @@ struct work {
bool mined; bool mined;
bool clone; bool clone;
bool cloned; bool cloned;
bool rolltime; int rolltime;
bool longpoll; bool longpoll;
bool stale; bool stale;
bool mandatory; bool mandatory;

111
miner.php

@ -3,6 +3,7 @@ session_start();
# #
global $miner, $port, $readonly, $notify, $rigs, $socktimeoutsec; global $miner, $port, $readonly, $notify, $rigs, $socktimeoutsec;
global $checklastshare, $hidefields; global $checklastshare, $hidefields;
global $ignorerefresh, $changerefresh, $autorefresh;
# #
# Don't touch these 2 - see $rigs below # Don't touch these 2 - see $rigs below
$miner = null; $miner = null;
@ -50,6 +51,14 @@ $socktimeoutsec = 10;
#$hidefields = array('POOL.URL' => 1, 'POOL.User' => 1); #$hidefields = array('POOL.URL' => 1, 'POOL.User' => 1);
$hidefields = array(); $hidefields = array();
# #
# Auto-refresh of the page (in seconds)
# $ignorerefresh = true/false always ignore refresh parameters
# $changerefresh = true/false show buttons to change the value
# $autorefresh = default value, 0 means dont auto-refresh
$ignorerefresh = false;
$changerefresh = true;
$autorefresh = 0;
#
$here = $_SERVER['PHP_SELF']; $here = $_SERVER['PHP_SELF'];
# #
global $tablebegin, $tableend, $warnfont, $warnoff, $dfmt; global $tablebegin, $tableend, $warnfont, $warnoff, $dfmt;
@ -60,6 +69,11 @@ $warnfont = '<font color=red><b>';
$warnoff = '</b></font>'; $warnoff = '</b></font>';
$dfmt = 'H:i:s j-M-Y \U\T\CP'; $dfmt = 'H:i:s j-M-Y \U\T\CP';
# #
global $miner_font_family, $miner_font_size;
#
$miner_font_family = 'verdana,arial,sans';
$miner_font_size = '13pt';
#
# This below allows you to put your own settings into a seperate file # This below allows you to put your own settings into a seperate file
# so you don't need to update miner.php with your preferred settings # so you don't need to update miner.php with your preferred settings
# every time a new version is released # every time a new version is released
@ -76,9 +90,24 @@ $showndate = false;
global $rigerror; global $rigerror;
$rigerror = array(); $rigerror = array();
# #
function htmlhead($checkapi) function htmlhead($checkapi, $rig)
{ {
global $miner_font_family, $miner_font_size;
global $error, $readonly, $here; global $error, $readonly, $here;
global $ignorerefresh, $autorefresh;
$paramrig = '';
if ($rig != null && $rig != '')
$paramrig = "&rig=$rig";
if ($ignorerefresh == true || $autorefresh == 0)
$refreshmeta = '';
else
{
$url = "$here?ref=$autorefresh$paramrig";
$refreshmeta = "\n<meta http-equiv='refresh' content='$autorefresh;url=$url'>";
}
if ($readonly === false && $checkapi === true) if ($readonly === false && $checkapi === true)
{ {
$access = api('privileged'); $access = api('privileged');
@ -87,28 +116,31 @@ function htmlhead($checkapi)
|| $access['STATUS']['STATUS'] != 'S') || $access['STATUS']['STATUS'] != 'S')
$readonly = true; $readonly = true;
} }
?> $miner_font = "font-family:$miner_font_family; font-size:$miner_font_size;";
<html><head><title>Mine</title>
echo "<html><head>$refreshmeta
<title>Mine</title>
<style type='text/css'> <style type='text/css'>
td { color:blue; font-family:verdana,arial,sans; font-size:13pt; } td { color:blue; $miner_font }
td.h { color:blue; font-family:verdana,arial,sans; font-size:13pt; background:#d0ffff } td.h { color:blue; $miner_font background:#d0ffff }
td.err { color:black; font-family:verdana,arial,sans; font-size:13pt; background:#ff3050 } td.err { color:black; $miner_font background:#ff3050 }
td.warn { color:black; font-family:verdana,arial,sans; font-size:13pt; background:#ffb050 } td.warn { color:black; $miner_font background:#ffb050 }
td.sta { color:green; font-family:verdana,arial,sans; font-size:13pt; } td.sta { color:green; $miner_font }
td.tot { color:blue; font-family:verdana,arial,sans; font-size:13pt; background:#fff8f2 } td.tot { color:blue; $miner_font background:#fff8f2 }
td.lst { color:blue; font-family:verdana,arial,sans; font-size:13pt; background:#ffffdd } td.lst { color:blue; $miner_font background:#ffffdd }
</style> </style>
</head><body bgcolor=#ecffff> </head><body bgcolor=#ecffff>
<script type='text/javascript'> <script type='text/javascript'>
function pr(a,m){if(m!=null){if(!confirm(m+'?'))return}window.location="<?php echo $here ?>"+a} function pr(a,m){if(m!=null){if(!confirm(m+'?'))return}window.location='$here?ref=$autorefresh'+a}\n";
<?php
if ($ignorerefresh == false)
echo "function prr(a){if(a){v=document.getElementById('refval').value}else{v=0}window.location='$here?ref='+v+'$paramrig'}\n";
if ($readonly === false && $checkapi === true) if ($readonly === false && $checkapi === true)
{ {
?> echo "function prc(a,m){pr('&arg='+a,m)}
function prc(a,m){pr('?arg='+a,m)}
function prs(a,r){var c=a.substr(3);var z=c.split('|',2);var m=z[0].substr(0,1).toUpperCase()+z[0].substr(1)+' GPU '+z[1];prc(a+'&rig='+r,m)} function prs(a,r){var c=a.substr(3);var z=c.split('|',2);var m=z[0].substr(0,1).toUpperCase()+z[0].substr(1)+' GPU '+z[1];prc(a+'&rig='+r,m)}
function prs2(a,n,r){var v=document.getElementById('gi'+n).value;var c=a.substr(3);var z=c.split('|',2);var m='Set GPU '+z[1]+' '+z[0].substr(0,1).toUpperCase()+z[0].substr(1)+' to '+v;prc(a+','+v+'&rig='+r,m)} function prs2(a,n,r){var v=document.getElementById('gi'+n).value;var c=a.substr(3);var z=c.split('|',2);var m='Set GPU '+z[1]+' '+z[0].substr(0,1).toUpperCase()+z[0].substr(1)+' to '+v;prc(a+','+v+'&rig='+r,m)}\n";
<?php
} }
?> ?>
</script> </script>
@ -778,7 +810,7 @@ function doforeach($cmd, $des, $sum, $head, $datetime)
foreach ($dthead as $name => $x) foreach ($dthead as $name => $x)
{ {
if ($item == 'STATUS' && $name == '') if ($item == 'STATUS' && $name == '')
echo "<td align=right><input type=button value='Rig $rig' onclick='pr(\"?rig=$rig\",null)'></td>"; echo "<td align=right><input type=button value='Rig $rig' onclick='pr(\"&rig=$rig\",null)'></td>";
else else
{ {
if (isset($row[$name])) if (isset($row[$name]))
@ -861,7 +893,7 @@ function doforeach($cmd, $des, $sum, $head, $datetime)
if ($rig === 'total') if ($rig === 'total')
echo "<td align=right class=tot>Total:</td>"; echo "<td align=right class=tot>Total:</td>";
else else
echo "<td align=right><input type=button value='Rig $rig' onclick='pr(\"?rig=$rig\",null)'></td>"; echo "<td align=right><input type=button value='Rig $rig' onclick='pr(\"&rig=$rig\",null)'></td>";
} }
else else
{ {
@ -884,27 +916,42 @@ function doforeach($cmd, $des, $sum, $head, $datetime)
} }
} }
# #
function refreshbuttons()
{
global $readonly;
global $ignorerefresh, $changerefresh, $autorefresh;
if ($ignorerefresh == false && $changerefresh == true)
{
echo '&nbsp;&nbsp;&nbsp;&nbsp;';
echo "<input type=button value='Refresh:' onclick='prr(true)'>";
echo "<input type=text name='refval' id='refval' size=2 value='$autorefresh'>";
echo "<input type=button value='Off' onclick='prr(false)'>";
}
}
#
function doOne($rig, $preprocess) function doOne($rig, $preprocess)
{ {
global $error, $readonly, $notify; global $error, $readonly, $notify, $rigs;
global $rigs;
htmlhead(true); htmlhead(true, $rig);
$error = null; $error = null;
echo "<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td>"; echo "<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td>";
echo "<input type=button value='Refresh' onclick='pr(\"?rig=$rig\",null)'></td>"; echo "<input type=button value='Refresh' onclick='pr(\"&rig=$rig\",null)'></td>";
if (count($rigs) > 1) if (count($rigs) > 1)
echo "<td><input type=button value='Summary' onclick='pr(\"\",null)'></td>"; echo "<td><input type=button value='Summary' onclick='pr(\"\",null)'></td>";
echo "<td width=100%>&nbsp;</td><td>"; echo "<td width=100%>&nbsp;</td><td nowrap>";
if ($readonly === false) if ($readonly === false)
{ {
$msg = 'Quit CGMiner'; $rg = '';
if (count($rigs) > 1) if (count($rigs) > 1)
$msg .= " Rig $rig"; $rg = " Rig $rig";
echo "<input type=button value='Quit' onclick='prc(\"quit&rig=$rig\",\"$msg\")'>"; echo "<input type=button value='Restart' onclick='prc(\"restart&rig=$rig\",\"Restart CGMiner$rg\")'>";
echo "&nbsp;<input type=button value='Quit' onclick='prc(\"quit&rig=$rig\",\"Quit CGMiner$rg\")'>";
} }
refreshbuttons();
echo "</td></tr></table></td></tr>"; echo "</td></tr></table></td></tr>";
if ($preprocess != null) if ($preprocess != null)
@ -930,6 +977,14 @@ function display()
global $tablebegin, $tableend; global $tablebegin, $tableend;
global $miner, $port; global $miner, $port;
global $error, $readonly, $notify, $rigs; global $error, $readonly, $notify, $rigs;
global $ignorerefresh, $autorefresh;
if ($ignorerefresh == false)
{
$ref = trim(getparam('ref', true));
if ($ref != null && $ref != '')
$autorefresh = intval($ref);
}
$rig = trim(getparam('rig', true)); $rig = trim(getparam('rig', true));
@ -998,10 +1053,12 @@ function display()
return; return;
} }
htmlhead(false); htmlhead(false, null);
echo "<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td>"; echo "<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td>";
echo "<input type=button value='Refresh' onclick='pr(\"\",null)'>"; echo "<input type=button value='Refresh' onclick='pr(\"\",null)'>";
echo "<td width=100%>&nbsp;</td><td nowrap>";
refreshbuttons();
echo "</td></tr></table></td></tr>"; echo "</td></tr></table></td></tr>";
if ($preprocess != null) if ($preprocess != null)

17
util.c

@ -56,7 +56,7 @@ struct upload_buffer {
struct header_info { struct header_info {
char *lp_path; char *lp_path;
bool has_rolltime; int rolltime;
char *reason; char *reason;
}; };
@ -160,8 +160,13 @@ static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data)
if (!strncasecmp("N", val, 1)) { if (!strncasecmp("N", val, 1)) {
applog(LOG_DEBUG, "X-Roll-Ntime: N found"); applog(LOG_DEBUG, "X-Roll-Ntime: N found");
} else { } else {
applog(LOG_DEBUG, "X-Roll-Ntime found"); /* Check to see if expire= is supported and if not, set
hi->has_rolltime = true; * the rolltime to the default scantime */
if (strlen(val) > 7 && !strncasecmp("expire=", val, 7))
sscanf(val + 7, "%d", &hi->rolltime);
else
hi->rolltime = opt_scantime;
applog(LOG_DEBUG, "X-Roll-Ntime expiry set to %d", hi->rolltime);
} }
} }
@ -248,7 +253,7 @@ static void set_nettime(void)
json_t *json_rpc_call(CURL *curl, const char *url, json_t *json_rpc_call(CURL *curl, const char *url,
const char *userpass, const char *rpc_req, const char *userpass, const char *rpc_req,
bool probe, bool longpoll, bool *rolltime, bool probe, bool longpoll, int *rolltime,
struct pool *pool, bool share) struct pool *pool, bool share)
{ {
json_t *val, *err_val, *res_val; json_t *val, *err_val, *res_val;
@ -260,7 +265,7 @@ json_t *json_rpc_call(CURL *curl, const char *url,
char len_hdr[64], user_agent_hdr[128]; char len_hdr[64], user_agent_hdr[128];
char curl_err_str[CURL_ERROR_SIZE]; char curl_err_str[CURL_ERROR_SIZE];
long timeout = longpoll ? (60 * 60) : 60; long timeout = longpoll ? (60 * 60) : 60;
struct header_info hi = {NULL, false, NULL}; struct header_info hi = {NULL, 0, NULL};
bool probing = false; bool probing = false;
memset(&err, 0, sizeof(err)); memset(&err, 0, sizeof(err));
@ -375,7 +380,7 @@ json_t *json_rpc_call(CURL *curl, const char *url,
hi.lp_path = NULL; hi.lp_path = NULL;
} }
*rolltime = hi.has_rolltime; *rolltime = hi.rolltime;
val = JSON_LOADS(all_data.buf, &err); val = JSON_LOADS(all_data.buf, &err);
if (!val) { if (!val) {

Loading…
Cancel
Save