diff --git a/NEWS b/NEWS index c9a9d3a0..4edc096c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,84 @@ +Version 2.4.4 - July 1, 2012 + +- Fix builds on non gnu platforms. +- api.c ensure old mode is always available when not using --api-groups + quit() +on param errors +- Implement rudimentary X-Mining-Hashrate support. +- Detect large swings in temperature when below the target temperature range and +change fan by amounts dependant on the value of tdiff. +- Adjust the fanspeed by the magnitude of the temperature difference when in the +optimal range. +- Revert "Restarting cgminer from within after ADL has been corrupted only leads +to a crash. Display a warning only and disable fanspeed monitoring." +- api.c fix json already closed +- implement and document API option --api-groups +- Put upper bounds to under 2 hours that work can be rolled into the future for +bitcoind will deem it invalid beyond that. +- define API option --api-groups +- api.c allow unwell devices to be enabled so they can be cured +- miner.php - fix/enable autorefresh for custom pages +- miner.php allow custom summary pages - new 'Mobile' summary +- Work around pools that advertise very low expire= time inappropriately as this +leads to many false positives for stale shares detected. +- Only show ztex board count if any exist. +- There is no need for work to be a union in struct workio_cmd +- fpgautils.c include a debug message for all unknown open errors +- Don't keep rolling work right up to the expire= cut off. Use 2/3 of the time +between the scantime and the expiry as cutoff for reusing work. +- Log a specific error when serial opens fail due to lack of user permissions +- Increase GPU timing resolution to microsecond and add sanity check to ensure +times are positive. +- Opencl code may start executing before the clfinish order is given to it so +get the start timing used for dynamic intensity from before the kernel is +queued. +- fpgautils.c - set BAUD rate according to termio spec +- fpgautils.c - linux ordering back to the correct way +- miner.php remove unneeded '.'s +- miner.php add auto refresh options +- miner.php add 'restart' next to 'quit' +- miner.php make fontname/size configurable with myminer.php +- Make the pools array a dynamically allocated array to allow unlimited pools to +be added. +- Make the devices array a dynamically allocated array of pointers to allow +unlimited devices. +- Dynamic intensity for GPUs should be calculated on a per device basis. Clean +up the code to only calculate it if required as well. +- Use a queueing bool set under control_lock to prevent multiple calls to +queue_request racing. +- Use the work clone flag to determine if we should subtract it from the total +queued variable and provide a subtract queued function to prevent looping over +locked code. +- Don't decrement staged extras count from longpoll work. +- Count longpoll's contribution to the queue. +- Increase queued count before pushing message. +- Test we have enough work queued for pools with and without rolltime +capability. +- As work is sorted by age, we can discard the oldest work at regular intervals +to keep only 1 of the newest work items per mining thread. +- Roll work again after duplicating it to prevent duplicates on return to the +clone function. +- Abstract out work cloning and clone $mining_threads copies whenever a rollable +work item is found and return a clone instead. +- api.c display Pool Av in json +- Take into account average getwork delay as a marker of pool communications +when considering work stale. +- Work out a rolling average getwork delay stored in pool_stats. +- Getwork delay in stats should include retries for each getwork call. +- Walk through the thread list instead of searching for them when disabling +threads for dynamic mode. +- Extend nrolltime to support the expiry= parameter. Do this by turning the +rolltime bool into an integer set to the expiry time. If the pool supports +rolltime but not expiry= then set the expiry time to the standard scantime. +- When disabling fanspeed monitoring on adl failure, remove any twin GPU +association. This could have been leading to hangs on machines with dual GPU +cards when ADL failed. +- modminer: Don't delay 2nd+ FPGAs during work restart +- Disable OpenCL code when not available. +- Fix openwrt crashing on regeneratehash() by making check_solve a noop. +- FPGA - allow device detect override without an open failure +- Fix sign warning. + + Version 2.4.3 - June 14, 2012 - can_roll and should_roll should have no bearing on the cycle period within the diff --git a/cgminer.c b/cgminer.c index 861332a5..0654a1da 100644 --- a/cgminer.c +++ b/cgminer.c @@ -445,6 +445,7 @@ struct pool *current_pool(void) char *set_int_range(const char *arg, int *i, int min, int max) { char *err = opt_set_intval(arg, i); + if (err) return err; @@ -594,7 +595,7 @@ static char *set_userpass(const char *arg) static char *enable_debug(bool *flag) { *flag = true; - /* Turn out verbose output, too. */ + /* Turn on verbose output, too. */ opt_log_output = true; return NULL; } @@ -609,8 +610,8 @@ static char *set_schedtime(const char *arg, struct schedtime *st) return NULL; } -static char* -set_sharelog(char *arg) { +static char* set_sharelog(char *arg) +{ char *r = ""; long int i = strtol(arg, &r, 10); @@ -662,11 +663,11 @@ static void load_temp_cutoffs() devices[device]->cutofftemp = val; } - } - else { - for (i = device; i < total_devices; ++i) + } else { + for (i = device; i < total_devices; ++i) { if (!devices[i]->cutofftemp) devices[i]->cutofftemp = opt_cutofftemp; + } return; } if (device <= 1) { @@ -1025,6 +1026,7 @@ static char *parse_config(json_t *config, bool fileconf) name = strdup(opt->names); for (p = strtok(name, "|"); p; p = strtok(NULL, "|")) { char *err = NULL; + /* Ignore short options. */ if (p[1] != '-') continue; @@ -1117,8 +1119,7 @@ static void load_default_config(void) if (getenv("HOME") && *getenv("HOME")) { strcpy(cnfbuf, getenv("HOME")); strcat(cnfbuf, "/"); - } - else + } else strcpy(cnfbuf, ""); strcat(cnfbuf, ".cgminer/"); #else @@ -3364,8 +3365,9 @@ static void hashmeter(int thr_id, struct timeval *diff, if (want_per_device_stats) { struct timeval now; struct timeval elapsed; + gettimeofday(&now, NULL); - timeval_subtract(&elapsed, &now, &thr->cgpu->last_message_tv); + timersub(&now, &thr->cgpu->last_message_tv, &elapsed); if (opt_log_interval <= elapsed.tv_sec) { struct cgpu_info *cgpu = thr->cgpu; char logline[255]; @@ -3385,7 +3387,7 @@ static void hashmeter(int thr_id, struct timeval *diff, /* Totals are updated by all threads so can race without locking */ mutex_lock(&hash_lock); gettimeofday(&temp_tv_end, NULL); - timeval_subtract(&total_diff, &temp_tv_end, &total_tv_end); + timersub(&temp_tv_end, &total_tv_end, &total_diff); total_mhashes_done += local_mhashes; local_mhashes_done += local_mhashes; @@ -3399,7 +3401,7 @@ static void hashmeter(int thr_id, struct timeval *diff, decay_time(&rolling, local_mhashes_done / local_secs); global_hashrate = roundl(rolling) * 1000000; - timeval_subtract(&total_diff, &total_tv_end, &total_tv_start); + timersub(&total_tv_end, &total_tv_start, &total_diff); total_secs = (double)total_diff.tv_sec + ((double)total_diff.tv_usec / 1000000.0); @@ -3953,7 +3955,7 @@ void *miner_thread(void *userdata) /* Try to cycle approximately 5 times before each log update */ const long cycle = opt_log_interval / 5 ? : 1; struct timeval tv_start, tv_end, tv_workstart, tv_lastupdate; - struct timeval diff, sdiff, wdiff; + struct timeval diff, sdiff, wdiff = {0, 0}; uint32_t max_nonce = api->can_limit_work ? api->can_limit_work(mythr) : 0xffffffff; unsigned long long hashes_done = 0; unsigned long long hashes; @@ -4070,7 +4072,7 @@ void *miner_thread(void *userdata) cgpu->max_hashes = hashes; gettimeofday(&tv_end, NULL); - timeval_subtract(&diff, &tv_end, &tv_start); + timersub(&tv_end, &tv_start, &diff); sdiff.tv_sec += diff.tv_sec; sdiff.tv_usec += diff.tv_usec; if (sdiff.tv_usec > 1000000) { @@ -4078,7 +4080,7 @@ void *miner_thread(void *userdata) sdiff.tv_usec -= 1000000; } - timeval_subtract(&wdiff, &tv_end, &tv_workstart); + timersub(&tv_end, &tv_workstart, &wdiff); if (!requested) { if (wdiff.tv_sec > request_interval || work->blk.nonce > request_nonce) { thread_reportout(mythr); @@ -4114,7 +4116,7 @@ void *miner_thread(void *userdata) max_nonce = max_nonce * 0x400 / (((cycle * 1000000) + sdiff.tv_usec) / (cycle * 1000000 / 0x400)); } - timeval_subtract(&diff, &tv_end, &tv_lastupdate); + timersub(&tv_end, &tv_lastupdate, &diff); if (diff.tv_sec >= opt_log_interval) { hashmeter(thr_id, &diff, hashes_done); hashes_done = 0; @@ -4601,7 +4603,7 @@ static void print_summary(void) int hours, mins, secs, i; double utility, efficiency = 0.0; - timeval_subtract(&diff, &total_tv_end, &total_tv_start); + timersub(&total_tv_end, &total_tv_start, &diff); hours = diff.tv_sec / 3600; mins = (diff.tv_sec % 3600) / 60; secs = diff.tv_sec % 60; @@ -4812,71 +4814,72 @@ out: #endif #if defined(unix) - static void fork_monitor() - { - // Make a pipe: [readFD, writeFD] - int pfd[2]; - int r = pipe(pfd); - if (r<0) { - perror("pipe - failed to create pipe for --monitor"); - exit(1); - } +static void fork_monitor() +{ + // Make a pipe: [readFD, writeFD] + int pfd[2]; + int r = pipe(pfd); - // Make stderr write end of pipe - fflush(stderr); - r = dup2(pfd[1], 2); - if (r<0) { - perror("dup2 - failed to alias stderr to write end of pipe for --monitor"); - exit(1); - } - r = close(pfd[1]); - if (r<0) { - perror("close - failed to close write end of pipe for --monitor"); - exit(1); - } + if (r < 0) { + perror("pipe - failed to create pipe for --monitor"); + exit(1); + } - // Don't allow a dying monitor to kill the main process - sighandler_t sr0 = signal(SIGPIPE, SIG_IGN); - sighandler_t sr1 = signal(SIGPIPE, SIG_IGN); - if (SIG_ERR==sr0 || SIG_ERR==sr1) { - perror("signal - failed to edit signal mask for --monitor"); + // Make stderr write end of pipe + fflush(stderr); + r = dup2(pfd[1], 2); + if (r < 0) { + perror("dup2 - failed to alias stderr to write end of pipe for --monitor"); + exit(1); + } + r = close(pfd[1]); + if (r < 0) { + perror("close - failed to close write end of pipe for --monitor"); + exit(1); + } + + // Don't allow a dying monitor to kill the main process + sighandler_t sr0 = signal(SIGPIPE, SIG_IGN); + sighandler_t sr1 = signal(SIGPIPE, SIG_IGN); + if (SIG_ERR == sr0 || SIG_ERR == sr1) { + perror("signal - failed to edit signal mask for --monitor"); + exit(1); + } + + // Fork a child process + forkpid = fork(); + if (forkpid < 0) { + perror("fork - failed to fork child process for --monitor"); + exit(1); + } + + // Child: launch monitor command + if (0 == forkpid) { + // Make stdin read end of pipe + r = dup2(pfd[0], 0); + if (r < 0) { + perror("dup2 - in child, failed to alias read end of pipe to stdin for --monitor"); exit(1); } - - // Fork a child process - forkpid = fork(); - if (forkpid<0) { - perror("fork - failed to fork child process for --monitor"); + close(pfd[0]); + if (r < 0) { + perror("close - in child, failed to close read end of pipe for --monitor"); exit(1); } - // Child: launch monitor command - if (0==forkpid) { - // Make stdin read end of pipe - r = dup2(pfd[0], 0); - if (r<0) { - perror("dup2 - in child, failed to alias read end of pipe to stdin for --monitor"); - exit(1); - } - close(pfd[0]); - if (r<0) { - perror("close - in child, failed to close read end of pipe for --monitor"); - exit(1); - } - - // Launch user specified command - execl("/bin/bash", "/bin/bash", "-c", opt_stderr_cmd, (char*)NULL); - perror("execl - in child failed to exec user specified command for --monitor"); - exit(1); - } + // Launch user specified command + execl("/bin/bash", "/bin/bash", "-c", opt_stderr_cmd, (char*)NULL); + perror("execl - in child failed to exec user specified command for --monitor"); + exit(1); + } - // Parent: clean up unused fds and bail - r = close(pfd[0]); - if (r<0) { - perror("close - failed to close read end of pipe for --monitor"); - exit(1); - } + // Parent: clean up unused fds and bail + r = close(pfd[0]); + if (r < 0) { + perror("close - failed to close read end of pipe for --monitor"); + exit(1); } +} #endif // defined(unix) #ifdef HAVE_CURSES @@ -4958,8 +4961,7 @@ bool add_cgpu(struct cgpu_info*cgpu) HASH_FIND_STR(devids, cgpu->api->name, d); if (d) cgpu->device_id = ++d->lastid; - else - { + else { d = malloc(sizeof(*d)); memcpy(d->name, cgpu->api->name, sizeof(d->name)); cgpu->device_id = d->lastid = 0; @@ -5118,14 +5120,16 @@ int main(int argc, char *argv[]) opt_log_output = true; #ifdef WANT_CPUMINE - if (0<=opt_bench_algo) { + if (0 <= opt_bench_algo) { double rate = bench_algo_stage3(opt_bench_algo); - if (!skip_to_bench) { + + if (!skip_to_bench) printf("%.5f (%s)\n", rate, algo_names[opt_bench_algo]); - } else { + else { // Write result to shared memory for parent - #if defined(WIN32) +#if defined(WIN32) char unique_name[64]; + if (GetEnvironmentVariable("CGMINER_SHARED_MEM", unique_name, 32)) { HANDLE map_handle = CreateFileMapping( INVALID_HANDLE_VALUE, // use paging file @@ -5135,7 +5139,7 @@ int main(int argc, char *argv[]) 4096, // size: low 32-bits unique_name // name of map object ); - if (NULL!=map_handle) { + if (NULL != map_handle) { void *shared_mem = MapViewOfFile( map_handle, // object to map view of FILE_MAP_WRITE, // read/write access @@ -5143,13 +5147,13 @@ int main(int argc, char *argv[]) 0, // low offset: beginning 0 // default: map entire file ); - if (NULL!=shared_mem) + if (NULL != shared_mem) CopyMemory(shared_mem, &rate, sizeof(rate)); (void)UnmapViewOfFile(shared_mem); } (void)CloseHandle(map_handle); } - #endif +#endif } exit(0); } diff --git a/driver-modminer.c b/driver-modminer.c index 2f8ee111..5b00aace 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -466,7 +466,7 @@ modminer_process_results(struct thr_info*thr) struct timeval tv_workend, elapsed; gettimeofday(&tv_workend, NULL); - timeval_subtract(&elapsed, &tv_workend, &state->tv_workstart); + timersub(&tv_workend, &state->tv_workstart, &elapsed); uint64_t hashes = (uint64_t)state->clock * (((uint64_t)elapsed.tv_sec * 1000000) + elapsed.tv_usec); if (hashes > 0xffffffff) diff --git a/miner.h b/miner.h index 57dd6367..8d9ef2f3 100644 --- a/miner.h +++ b/miner.h @@ -561,9 +561,6 @@ typedef bool (*sha256_func)(int thr_id, const unsigned char *pmidstate, uint32_t *last_nonce, uint32_t nonce); -extern int -timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y); - extern bool fulltest(const unsigned char *hash, const unsigned char *target); extern int opt_scantime; diff --git a/util.c b/util.c index ffc6a70a..b17eceae 100644 --- a/util.c +++ b/util.c @@ -147,9 +147,9 @@ static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data) memcpy(val, rem, remlen); /* store value, trim trailing ws */ val[remlen] = 0; - while ((*val) && (isspace(val[strlen(val) - 1]))) { + while ((*val) && (isspace(val[strlen(val) - 1]))) val[strlen(val) - 1] = 0; - } + if (!*val) /* skip blank value */ goto out; @@ -157,9 +157,9 @@ static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data) applog(LOG_DEBUG, "HTTP hdr(%s): %s", key, val); if (!strcasecmp("X-Roll-Ntime", key)) { - if (!strncasecmp("N", val, 1)) { + if (!strncasecmp("N", val, 1)) applog(LOG_DEBUG, "X-Roll-Ntime: N found"); - } else { + else { /* Check to see if expire= is supported and if not, set * the rolltime to the default scantime */ if (strlen(val) > 7 && !strncasecmp("expire=", val, 7)) @@ -256,10 +256,10 @@ json_t *json_rpc_call(CURL *curl, const char *url, bool probe, bool longpoll, int *rolltime, struct pool *pool, bool share) { - char len_hdr[64], user_agent_hdr[128], *ghashrate; long timeout = longpoll ? (60 * 60) : 60; struct data_buffer all_data = {NULL, 0}; struct header_info hi = {NULL, 0, NULL}; + char len_hdr[64], user_agent_hdr[128]; char curl_err_str[CURL_ERROR_SIZE]; struct curl_slist *headers = NULL; struct upload_buffer upload_data; @@ -327,9 +327,10 @@ json_t *json_rpc_call(CURL *curl, const char *url, "X-Mining-Extensions: longpoll midstate rollntime submitold"); if (likely(global_hashrate)) { - asprintf(&ghashrate, "X-Mining-Hashrate: %llu", global_hashrate); + char ghashrate[255]; + + sprintf(ghashrate, "X-Mining-Hashrate: %llu", global_hashrate); headers = curl_slist_append(headers, ghashrate); - free(ghashrate); } headers = curl_slist_append(headers, len_hdr); @@ -379,9 +380,8 @@ json_t *json_rpc_call(CURL *curl, const char *url, if (pool->hdr_path != NULL) free(pool->hdr_path); pool->hdr_path = hi.lp_path; - } else { + } else pool->hdr_path = NULL; - } } else if (hi.lp_path) { free(hi.lp_path); hi.lp_path = NULL; @@ -401,6 +401,7 @@ json_t *json_rpc_call(CURL *curl, const char *url, if (opt_protocol) { char *s = json_dumps(val, JSON_INDENT(3)); + applog(LOG_DEBUG, "JSON protocol response:\n%s", s); free(s); } @@ -450,8 +451,8 @@ err_out: char *bin2hex(const unsigned char *p, size_t len) { - unsigned int i; char *s = malloc((len * 2) + 1); + unsigned int i; if (!s) return NULL; @@ -492,43 +493,14 @@ bool hex2bin(unsigned char *p, const char *hexstr, size_t len) return (len == 0 && *hexstr == 0) ? true : false; } -/* Subtract the `struct timeval' values X and Y, - storing the result in RESULT. - Return 1 if the difference is negative, otherwise 0. */ - -int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) -{ - /* Perform the carry for the later subtraction by updating Y. */ - if (x->tv_usec < y->tv_usec) { - int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; - - y->tv_usec -= 1000000 * nsec; - y->tv_sec += nsec; - } - if (x->tv_usec - y->tv_usec > 1000000) { - int nsec = (x->tv_usec - y->tv_usec) / 1000000; - - y->tv_usec += 1000000 * nsec; - y->tv_sec -= nsec; - } - - /* Compute the time remaining to wait. - * `tv_usec' is certainly positive. */ - result->tv_sec = x->tv_sec - y->tv_sec; - result->tv_usec = x->tv_usec - y->tv_usec; - - /* Return 1 if result is negative. */ - return x->tv_sec < y->tv_sec; -} - bool fulltest(const unsigned char *hash, const unsigned char *target) { unsigned char hash_swap[32], target_swap[32]; uint32_t *hash32 = (uint32_t *) hash_swap; uint32_t *target32 = (uint32_t *) target_swap; - int i; - bool rc = true; char *hash_str, *target_str; + bool rc = true; + int i; swap256(hash_swap, hash); swap256(target_swap, target); @@ -681,10 +653,7 @@ out: int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (void *), void *arg) { - int ret; - - ret = pthread_create(&thr->pth, attr, start, arg); - return ret; + return pthread_create(&thr->pth, attr, start, arg); } void thr_info_freeze(struct thr_info *thr)