From 568b0fed896a25938e4e211cce7a925e437ed812 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 1 Sep 2012 18:21:08 +1000 Subject: [PATCH 01/50] API allow full debug settings control --- API-README | 28 +++++++++++++++++--- api.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++--- cgminer.c | 4 +-- logging.h | 2 ++ 4 files changed, 103 insertions(+), 9 deletions(-) diff --git a/API-README b/API-README index ff48a3c5..46209764 100644 --- a/API-README +++ b/API-README @@ -287,6 +287,20 @@ The list of requests - a (*) means it requires privileged access - and replies a Current Block Hash=XXXX..., <- blank if none LP=true/false| <- LP is in use on at least 1 pool + debug|setting (*) + DEBUG Debug settings + The optional commands for 'setting' are the same as + the screen curses debug settings. + Only the first character is checked (case insensitive): + Silent, Quiet, Verbose, Debug, RPCProto, PerDevice, Normal + The output fields are (as above): + Silent=true/false, + Quiet=true/false, + Verbose=true/false, + Debug=true/false, + RPCProto=true/false, + PerDevice=true/false| + When you enable, disable or restart a GPU or PGA, you will also get Thread messages in the cgminer status window @@ -306,8 +320,9 @@ windows Obviously, the JSON format is simply just the names as given before the '=' with the values after the '=' -If you enable cgminer debug (-D or --debug) you will also get messages showing -details of the requests received and the replies +If you enable cgminer debug (-D or --debug) or, when cgminer debug is off, +turn on debug with the API command 'debug|debug' you will also get messages +showing some details of the requests received and the replies There are included 4 program examples for accessing the API: @@ -339,13 +354,18 @@ miner.php - an example web page to access the API Feature Changelog for external applications using the API: +API V1.19 + +Added API commands: + 'debug' + +---------- + API V1.18 Modified API commands: 'stats' - add 'Work Had Roll Time', 'Work Can Roll', 'Work Had Expire', 'Work Roll Time' to the pool stats - -Modified API commands: 'config' - include 'ScanTime' ---------- diff --git a/api.c b/api.c index ca1b9429..8c1aafc6 100644 --- a/api.c +++ b/api.c @@ -166,7 +166,7 @@ static const char SEPARATOR = '|'; #define SEPSTR "|" static const char GPUSEP = ','; -static const char *APIVERSION = "1.18"; +static const char *APIVERSION = "1.19"; static const char *DEAD = "Dead"; static const char *SICK = "Sick"; static const char *NOSTART = "NoStart"; @@ -258,6 +258,7 @@ static const char *OSINFO = #define _MINESTATS "STATS" #define _CHECK "CHECK" #define _MINECOIN "COIN" +#define _DEBUGSET "DEBUG" static const char ISJSON = '{'; #define JSON0 "{" @@ -295,6 +296,7 @@ static const char ISJSON = '{'; #define JSON_MINESTATS JSON1 _MINESTATS JSON2 #define JSON_CHECK JSON1 _CHECK JSON2 #define JSON_MINECOIN JSON1 _MINECOIN JSON2 +#define JSON_DEBUGSET JSON1 _DEBUGSET JSON2 #define JSON_END JSON4 JSON5 static const char *JSON_COMMAND = "command"; @@ -390,6 +392,7 @@ static const char *JSON_PARAMETER = "parameter"; #define MSG_INVBOOL 76 #define MSG_FOO 77 #define MSG_MINECOIN 78 +#define MSG_DEBUGSET 79 enum code_severity { SEVERITY_ERR, @@ -543,6 +546,7 @@ struct CODES { { SEVERITY_ERR, MSG_INVBOOL, PARAM_NONE, "Invalid parameter should be true or false" }, { SEVERITY_SUCC, MSG_FOO, PARAM_BOOL, "Failover-Only set to %s" }, { SEVERITY_SUCC, MSG_MINECOIN,PARAM_NONE, "CGMiner coin" }, + { SEVERITY_SUCC, MSG_DEBUGSET,PARAM_STR, "Debug settings" }, { SEVERITY_FAIL, 0, 0, NULL } }; @@ -2772,7 +2776,7 @@ static void minecoin(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo #endif root = api_add_const(root, "Hash Method", SHA256STR, false); - mutex_lock(&ch_lock); + mutex_lock(&ch_lock); if (current_fullhash && *current_fullhash) { root = api_add_timeval(root, "Current Block Time", &block_timeval, true); root = api_add_string(root, "Current Block Hash", current_fullhash, true); @@ -2781,7 +2785,7 @@ static void minecoin(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo root = api_add_timeval(root, "Current Block Time", &t, true); root = api_add_const(root, "Current Block Hash", BLANK, false); } - mutex_unlock(&ch_lock); + mutex_unlock(&ch_lock); root = api_add_bool(root, "LP", &have_longpoll, false); @@ -2791,6 +2795,73 @@ static void minecoin(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo strcat(io_buffer, buf); } +static void debugstate(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) +{ + struct api_data *root = NULL; + char buf[TMPBUFSIZ]; + + if (param == NULL) + param = (char *)BLANK; + else + *param = tolower(*param); + + switch(*param) { + case 's': + opt_realquiet = true; + break; + case 'q': + opt_quiet ^= true; + break; + case 'v': + opt_log_output ^= true; + if (opt_log_output) + opt_quiet = false; + break; + case 'd': + opt_debug ^= true; + opt_log_output = opt_debug; + if (opt_debug) + opt_quiet = false; + break; + case 'r': + opt_protocol ^= true; + if (opt_protocol) + opt_quiet = false; + break; + case 'p': + want_per_device_stats ^= true; + opt_log_output = want_per_device_stats; + break; + case 'n': + opt_log_output = false; + opt_debug = false; + opt_quiet = false; + opt_protocol = false; + want_per_device_stats = false; + break; + default: + // anything else just reports the settings + break; + } + + sprintf(io_buffer, isjson + ? "%s," JSON_DEBUGSET + : "%s" _DEBUGSET ",", + message(MSG_DEBUGSET, 0, NULL, isjson)); + + root = api_add_bool(root, "Silent", &opt_realquiet, false); + root = api_add_bool(root, "Quiet", &opt_quiet, false); + root = api_add_bool(root, "Verbose", &opt_log_output, false); + root = api_add_bool(root, "Debug", &opt_debug, false); + root = api_add_bool(root, "RPCProto", &opt_protocol, false); + root = api_add_bool(root, "PerDevice", &want_per_device_stats, false); + + root = print_data(root, buf, isjson); + if (isjson) + strcat(buf, JSON_CLOSE); + strcat(io_buffer, buf); +} + static void checkcommand(__maybe_unused SOCKETTYPE c, char *param, bool isjson, char group); struct CMDS { @@ -2843,6 +2914,7 @@ struct CMDS { { "check", checkcommand, false }, { "failover-only", failoveronly, true }, { "coin", minecoin, false }, + { "debug", debugstate, true }, { NULL, NULL, false } }; diff --git a/cgminer.c b/cgminer.c index c9114b28..3c3c619a 100644 --- a/cgminer.c +++ b/cgminer.c @@ -86,10 +86,10 @@ static char packagename[255]; bool opt_protocol; static bool opt_benchmark; bool have_longpoll; -static bool want_per_device_stats; +bool want_per_device_stats; bool use_syslog; bool opt_quiet; -static bool opt_realquiet; +bool opt_realquiet; bool opt_loginput; const int opt_cutofftemp = 95; int opt_log_interval = 5; diff --git a/logging.h b/logging.h index 18f3a744..52f98731 100644 --- a/logging.h +++ b/logging.h @@ -20,6 +20,8 @@ enum { /* original / legacy debug flags */ extern bool opt_debug; extern bool opt_log_output; +extern bool opt_realquiet; +extern bool want_per_device_stats; /* global log_level, messages with lower or equal prio are logged */ extern int opt_log_level; From 2bf08bb4f8bb491bf184f7ac1840cbe60e119a9a Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 1 Sep 2012 21:01:51 +1000 Subject: [PATCH 02/50] API-README more debug parameter information --- API-README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/API-README b/API-README index 46209764..c6b15464 100644 --- a/API-README +++ b/API-README @@ -290,7 +290,8 @@ The list of requests - a (*) means it requires privileged access - and replies a debug|setting (*) DEBUG Debug settings The optional commands for 'setting' are the same as - the screen curses debug settings. + the screen curses debug settings + You can only specify one setting Only the first character is checked (case insensitive): Silent, Quiet, Verbose, Debug, RPCProto, PerDevice, Normal The output fields are (as above): From 4023872b76be05e98118d7efe6f052db431238a7 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 1 Sep 2012 23:51:51 +1000 Subject: [PATCH 03/50] count device diff1 shares --- cgminer.c | 1 + miner.h | 1 + 2 files changed, 2 insertions(+) diff --git a/cgminer.c b/cgminer.c index c9114b28..54e9282d 100644 --- a/cgminer.c +++ b/cgminer.c @@ -4186,6 +4186,7 @@ bool test_nonce(struct work *work, uint32_t nonce) bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) { total_diff1++; + thr->cgpu->diff1++; work->pool->diff1++; /* Do one last check before attempting to submit the work */ diff --git a/miner.h b/miner.h index a234ecd3..f35ae965 100644 --- a/miner.h +++ b/miner.h @@ -396,6 +396,7 @@ struct cgpu_info { int gpu_powertune; float gpu_vddc; #endif + int diff1; int last_share_pool; time_t last_share_pool_time; From 381478e65cc271f5bc63a798aeab0109f897bd50 Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 2 Sep 2012 08:05:50 +1000 Subject: [PATCH 04/50] api.c Correct diff1 field name --- api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.c b/api.c index 8c1aafc6..affe13c4 100644 --- a/api.c +++ b/api.c @@ -1793,7 +1793,7 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, root = api_add_uint(root, "Remote Failures", &(pool->remotefail_occasions), false); root = api_add_escape(root, "User", pool->rpc_user, false); root = api_add_time(root, "Last Share Time", &(pool->last_share_time), false); - root = api_add_int(root, "Diff1 Shares", &(pool->diff1), false); + root = api_add_int(root, "Diff1 Work", &(pool->diff1), false); if (isjson && (i > 0)) strcat(io_buffer, COMMA); From e5347ed9714afa68b8f185603bdf2465b086bdee Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 3 Sep 2012 00:16:10 +1000 Subject: [PATCH 05/50] API-README update --- API-README | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/API-README b/API-README index c6b15464..1c2846aa 100644 --- a/API-README +++ b/API-README @@ -360,9 +360,12 @@ API V1.19 Added API commands: 'debug' +Modified API commands: + Change pool field name 'Diff1 Shares' to 'Diff1 Work' + ---------- -API V1.18 +API V1.18 (cgminer v2.7.4) Modified API commands: 'stats' - add 'Work Had Roll Time', 'Work Can Roll', 'Work Had Expire', From 93555e271a134dcf7af90befc8499acaf9569089 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 4 Sep 2012 01:23:32 +1000 Subject: [PATCH 06/50] API add device diff1 work --- API-README | 3 +++ api.c | 3 +++ miner.php | 8 ++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/API-README b/API-README index 1c2846aa..cc8ee9e5 100644 --- a/API-README +++ b/API-README @@ -362,6 +362,9 @@ Added API commands: Modified API commands: Change pool field name 'Diff1 Shares' to 'Diff1 Work' + 'devs' - add 'Diff1 Work' to all devices + 'gpu|N' - add 'Diff1 Work' + 'pga|N' - add 'Diff1 Work' ---------- diff --git a/api.c b/api.c index affe13c4..b4ec40f7 100644 --- a/api.c +++ b/api.c @@ -1345,6 +1345,7 @@ static void gpustatus(int gpu, bool isjson) root = api_add_int(root, "Last Share Pool", &last_share_pool, false); root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false); root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false); + root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false); root = print_data(root, buf, isjson); strcat(io_buffer, buf); @@ -1428,6 +1429,7 @@ static void pgastatus(int pga, bool isjson) root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false); root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false); root = api_add_freq(root, "Frequency", &frequency, false); + root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false); root = print_data(root, buf, isjson); strcat(io_buffer, buf); @@ -1460,6 +1462,7 @@ static void cpustatus(int cpu, bool isjson) root = api_add_int(root, "Last Share Pool", &last_share_pool, false); root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false); root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false); + root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false); root = print_data(root, buf, isjson); strcat(io_buffer, buf); diff --git a/miner.php b/miner.php index 9c6f6949..8202cb64 100644 --- a/miner.php +++ b/miner.php @@ -755,8 +755,12 @@ function fmt($section, $name, $value, $when, $alldata) case 'SUMMARY.Discarded': case 'POOL.Discarded': case 'total.Discarded': - case 'POOL.Diff1 Shares': - case 'total.Diff1 Shares': + case 'GPU.Diff1 Work': + case 'PGA.Diff1 Work': + case 'POOL.Diff1 Work': + case 'total.Diff1 Work': + case 'POOL.Diff1 Shares': // old name + case 'total.Diff1 Shares': // old name $parts = explode('.', $value, 2); if (count($parts) == 1) $dec = ''; From bd151ef36d47426d2436feab38cd4ed61905d435 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 4 Sep 2012 01:27:53 +1000 Subject: [PATCH 07/50] miner.php correct to new Diff1 Work field names --- miner.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miner.php b/miner.php index 8202cb64..07a5fb57 100644 --- a/miner.php +++ b/miner.php @@ -849,7 +849,7 @@ $singlerigsum = array( 'Hardware Errors' => 1, 'Utility' => 1, 'Total MH' => 1), 'pools' => array('Getworks' => 1, 'Accepted' => 1, 'Rejected' => 1, 'Discarded' => 1, 'Stale' => 1, 'Get Failures' => 1, 'Remote Failures' => 1, - 'Diff1 Shares' => 1), + 'Diff1 Work' => 1), 'notify' => array('*' => 1)); # function showtotal($total, $when, $oldvalues) @@ -2056,7 +2056,7 @@ function display() newtable(); doforeach('version', 'rig summary', array(), array(), true); - $sum = array('MHS av', 'Getworks', 'Found Blocks', 'Accepted', 'Rejected', 'Discarded', 'Stale', 'Utility', 'Local Work', 'Total MH', 'Work Utility', 'Diff1 Shares'); + $sum = array('MHS av', 'Getworks', 'Found Blocks', 'Accepted', 'Rejected', 'Discarded', 'Stale', 'Utility', 'Local Work', 'Total MH', 'Work Utility', 'Diff1 Work'); doforeach('summary', 'summary information', $sum, array(), false); endtable(); otherrow('

'); From 71e2f23f4771669547039672cabdcba80bcbb21d Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 4 Sep 2012 02:10:22 +1000 Subject: [PATCH 08/50] BFL: missing device id in log message --- driver-bitforce.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index 93587218..b8e7bc7c 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -385,7 +385,7 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) /* Use the temperature monitor as a kind of watchdog for when * our responses are out of sync and flush the buffer to * hopefully recover */ - applog(LOG_WARNING, "BFL%i: Garbled response probably throttling, clearing buffer"); + applog(LOG_WARNING, "BFL%i: Garbled response probably throttling, clearing buffer", bitforce->device_id); /* Count throttling episodes as hardware errors */ bitforce->hw_errors++; bitforce_clear_buffer(bitforce); From 7a2407f15c2bd2fefbec39fca726e7b1b3dc3348 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 4 Sep 2012 02:26:17 +1000 Subject: [PATCH 09/50] BFL add throttle count to internal stats + API --- API-README | 1 + api.c | 1 + driver-bitforce.c | 5 ++++- miner.h | 3 +++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/API-README b/API-README index cc8ee9e5..4f812c14 100644 --- a/API-README +++ b/API-README @@ -365,6 +365,7 @@ Modified API commands: 'devs' - add 'Diff1 Work' to all devices 'gpu|N' - add 'Diff1 Work' 'pga|N' - add 'Diff1 Work' + 'notify' - add '*Dev Throttle' (for BFL Singles) ---------- diff --git a/api.c b/api.c index b4ec40f7..a8123810 100644 --- a/api.c +++ b/api.c @@ -2561,6 +2561,7 @@ void notifystatus(int device, struct cgpu_info *cgpu, bool isjson, __maybe_unuse root = api_add_int(root, "*Dev Over Heat", &(cgpu->dev_over_heat_count), false); root = api_add_int(root, "*Dev Thermal Cutoff", &(cgpu->dev_thermal_cutoff_count), false); root = api_add_int(root, "*Dev Comms Error", &(cgpu->dev_comms_error_count), false); + root = api_add_int(root, "*Dev Throttle", &(cgpu->dev_throttle_count), false); if (isjson && (device > 0)) strcat(io_buffer, COMMA); diff --git a/driver-bitforce.c b/driver-bitforce.c index b8e7bc7c..64cc51ac 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -386,10 +386,13 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) * our responses are out of sync and flush the buffer to * hopefully recover */ applog(LOG_WARNING, "BFL%i: Garbled response probably throttling, clearing buffer", bitforce->device_id); + bitforce->device_last_not_well = time(NULL); + bitforce->device_not_well_reason = REASON_DEV_THROTTLE; + bitforce->dev_throttle_count++; /* Count throttling episodes as hardware errors */ bitforce->hw_errors++; bitforce_clear_buffer(bitforce); - return false;; + return false; } return true; diff --git a/miner.h b/miner.h index f35ae965..7234cf6c 100644 --- a/miner.h +++ b/miner.h @@ -276,6 +276,7 @@ enum dev_reason { REASON_DEV_OVER_HEAT, REASON_DEV_THERMAL_CUTOFF, REASON_DEV_COMMS_ERROR, + REASON_DEV_THROTTLE, }; #define REASON_NONE "None" @@ -288,6 +289,7 @@ enum dev_reason { #define REASON_DEV_OVER_HEAT_STR "Device over heated" #define REASON_DEV_THERMAL_CUTOFF_STR "Device reached thermal cutoff" #define REASON_DEV_COMMS_ERROR_STR "Device comms error" +#define REASON_DEV_THROTTLE_STR "Device throttle" #define REASON_UNKNOWN_STR "Unknown reason - code bug" #define MIN_SEC_UNSET 99999999 @@ -412,6 +414,7 @@ struct cgpu_info { int dev_over_heat_count; // It's a warning but worth knowing int dev_thermal_cutoff_count; int dev_comms_error_count; + int dev_throttle_count; struct cgminer_stats cgminer_stats; }; From 9487ba05cdbed2f9135ab030e91b2a06cc4cbbfb Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 4 Sep 2012 12:52:11 +1000 Subject: [PATCH 10/50] API/BFL identify a device - currently only BFL to flash the led --- API-README | 17 +++++++++++++++ api.c | 45 ++++++++++++++++++++++++++++++++++++++++ driver-bitforce.c | 53 +++++++++++++++++++++++++++++++++++++++++++++-- miner.h | 2 ++ 4 files changed, 115 insertions(+), 2 deletions(-) diff --git a/API-README b/API-README index 4f812c14..8a686fcd 100644 --- a/API-README +++ b/API-README @@ -259,6 +259,22 @@ The list of requests - a (*) means it requires privileged access - and replies a stating the results of the disable request This is only available if PGA mining is enabled + pgaidentify|N (*) + none There is no reply section just the STATUS section + stating the results of the identify request + This is only available if PGA mining is enabled + and currently only BFL singles support this command + On a BFL single it will flash the led on the front + of the device for appoximately 4s + All other non BFL PGA devices will return an error + status message stating that they dont support it + This adds a 4s delay to the BFL share being processed + so you may get a message stating that procssing took + longer than 7000ms if the request was sent towards + the end of the timing of any work being worked on + e.g.: BFL0: took 8438ms - longer than 7000ms + You should ignore this + devdetails DEVDETAILS Each device with a list of their static details This lists all devices including those not supported by the 'devs' command @@ -359,6 +375,7 @@ API V1.19 Added API commands: 'debug' + 'pgaidentify|N' Modified API commands: Change pool field name 'Diff1 Shares' to 'Diff1 Work' diff --git a/api.c b/api.c index a8123810..839ea660 100644 --- a/api.c +++ b/api.c @@ -393,6 +393,8 @@ static const char *JSON_PARAMETER = "parameter"; #define MSG_FOO 77 #define MSG_MINECOIN 78 #define MSG_DEBUGSET 79 +#define MSG_PGAIDENT 80 +#define MSG_PGANOID 81 enum code_severity { SEVERITY_ERR, @@ -547,6 +549,10 @@ struct CODES { { SEVERITY_SUCC, MSG_FOO, PARAM_BOOL, "Failover-Only set to %s" }, { SEVERITY_SUCC, MSG_MINECOIN,PARAM_NONE, "CGMiner coin" }, { SEVERITY_SUCC, MSG_DEBUGSET,PARAM_STR, "Debug settings" }, +#ifdef HAVE_AN_FPGA + { SEVERITY_SUCC, MSG_PGAIDENT,PARAM_PGA, "Identify command sent to PGA%d" }, + { SEVERITY_ERR, MSG_PGANOID, PARAM_PGA, "PGA%d does not support identify" }, +#endif { SEVERITY_FAIL, 0, 0, NULL } }; @@ -1700,6 +1706,44 @@ static void pgadisable(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __ strcpy(io_buffer, message(MSG_PGADIS, id, NULL, isjson)); } + +static void pgaidentify(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) +{ + int numpga = numpgas(); + int id; + + if (numpga == 0) { + strcpy(io_buffer, message(MSG_PGANON, 0, NULL, isjson)); + return; + } + + if (param == NULL || *param == '\0') { + strcpy(io_buffer, message(MSG_MISID, 0, NULL, isjson)); + return; + } + + id = atoi(param); + if (id < 0 || id >= numpga) { + strcpy(io_buffer, message(MSG_INVPGA, id, NULL, isjson)); + return; + } + + int dev = pgadevice(id); + if (dev < 0) { // Should never happen + strcpy(io_buffer, message(MSG_INVPGA, id, NULL, isjson)); + return; + } + + struct cgpu_info *cgpu = devices[dev]; + struct device_api *api = cgpu->api; + + if (!api->identify_device) + strcpy(io_buffer, message(MSG_PGANOID, id, NULL, isjson)); + else { + api->identify_device(cgpu); + strcpy(io_buffer, message(MSG_PGAIDENT, id, NULL, isjson)); + } +} #endif #ifdef WANT_CPUMINE @@ -2888,6 +2932,7 @@ struct CMDS { { "pga", pgadev, false }, { "pgaenable", pgaenable, true }, { "pgadisable", pgadisable, true }, + { "pgaidentify", pgaidentify, true }, #endif #ifdef WANT_CPUMINE { "cpu", cpudev, false }, diff --git a/driver-bitforce.c b/driver-bitforce.c index 64cc51ac..c1107fea 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -99,6 +99,7 @@ static bool bitforce_detect_one(const char *devpath) } BFwrite(fdDev, "ZGX", 3); + pdevbuf[0] = '\0'; BFgets(pdevbuf, sizeof(pdevbuf), fdDev); if (unlikely(!pdevbuf[0])) { applog(LOG_ERR, "BFL: Error reading/timeout (ZGX)"); @@ -309,6 +310,7 @@ void bitforce_init(struct cgpu_info *bitforce) do { BFwrite(fdDev, "ZGX", 3); + pdevbuf[0] = '\0'; BFgets(pdevbuf, sizeof(pdevbuf), fdDev); if (unlikely(!pdevbuf[0])) { @@ -338,6 +340,37 @@ void bitforce_init(struct cgpu_info *bitforce) mutex_unlock(&bitforce->device_mutex); } +static void bitforce_flash_led(struct cgpu_info *bitforce) +{ + int fdDev = bitforce->device_fd; + + if (!fdDev) + return; + + /* Do not try to flash the led if we're polling for a result to + * minimise the chance of interleaved results */ + if (bitforce->polling) + return; + + /* It is not critical flashing the led so don't get stuck if we + * can't grab the mutex here */ + if (mutex_trylock(&bitforce->device_mutex)) + return; + + BFwrite(fdDev, "ZMX", 3); + + /* Once we've tried - don't do it until told to again */ + bitforce->flash_led = false; + + /* However, this stops anything else getting a reply + * So best to delay any other access to the BFL */ + sleep(4); + + mutex_unlock(&bitforce->device_mutex); + + return; // nothing is returned by the BFL +} + static bool bitforce_get_temp(struct cgpu_info *bitforce) { int fdDev = bitforce->device_fd; @@ -348,16 +381,23 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) return false; /* Do not try to get the temperature if we're polling for a result to - * minimise the change of interleaved results */ + * minimise the chance of interleaved results */ if (bitforce->polling) return true; - /* It is not critical getting temperature so don't get stuck if we + // Flash instead of Temp - doing both can be too slow + if (bitforce->flash_led) { + bitforce_flash_led(bitforce); + return true; + } + + /* It is not critical getting temperature so don't get stuck if we * can't grab the mutex here */ if (mutex_trylock(&bitforce->device_mutex)) return false; BFwrite(fdDev, "ZLX", 3); + pdevbuf[0] = '\0'; BFgets(pdevbuf, sizeof(pdevbuf), fdDev); mutex_unlock(&bitforce->device_mutex); @@ -414,6 +454,7 @@ re_send: BFwrite(fdDev, "ZPX", 3); else BFwrite(fdDev, "ZDX", 3); + pdevbuf[0] = '\0'; BFgets(pdevbuf, sizeof(pdevbuf), fdDev); if (!pdevbuf[0] || !strncasecmp(pdevbuf, "B", 1)) { mutex_unlock(&bitforce->device_mutex); @@ -453,6 +494,7 @@ re_send: BFwrite(fdDev, ob, 68); } + pdevbuf[0] = '\0'; BFgets(pdevbuf, sizeof(pdevbuf), fdDev); mutex_unlock(&bitforce->device_mutex); @@ -496,6 +538,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) mutex_lock(&bitforce->device_mutex); BFwrite(fdDev, "ZFX", 3); + pdevbuf[0] = '\0'; BFgets(pdevbuf, sizeof(pdevbuf), fdDev); mutex_unlock(&bitforce->device_mutex); @@ -640,6 +683,11 @@ static bool bitforce_get_stats(struct cgpu_info *bitforce) return bitforce_get_temp(bitforce); } +static void bitforce_identify(struct cgpu_info *bitforce) +{ + bitforce->flash_led = true; +} + static bool bitforce_thread_init(struct thr_info *thr) { struct cgpu_info *bitforce = thr->cgpu; @@ -676,6 +724,7 @@ struct device_api bitforce_api = { .reinit_device = bitforce_init, .get_statline_before = get_bitforce_statline_before, .get_stats = bitforce_get_stats, + .identify_device = bitforce_identify, .thread_prepare = bitforce_thread_prepare, .thread_init = bitforce_thread_init, .scanhash = bitforce_scanhash, diff --git a/miner.h b/miner.h index 7234cf6c..6ac8d934 100644 --- a/miner.h +++ b/miner.h @@ -239,6 +239,7 @@ struct device_api { void (*get_statline)(char*, struct cgpu_info*); struct api_data *(*get_api_stats)(struct cgpu_info*); bool (*get_stats)(struct cgpu_info*); + void (*identify_device)(struct cgpu_info*); // e.g. to flash a led // Thread-specific functions bool (*thread_prepare)(struct thr_info*); @@ -337,6 +338,7 @@ struct cgpu_info { uint32_t nonces; bool nonce_range; bool polling; + bool flash_led; #endif pthread_mutex_t device_mutex; From 9950cff5aef644b8787f8ff5ff2fb8a89e8df404 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 4 Sep 2012 12:57:22 +1000 Subject: [PATCH 11/50] API pgaidentify - unsupported message should be a warning --- API-README | 2 +- api.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/API-README b/API-README index 8a686fcd..bd2811c9 100644 --- a/API-README +++ b/API-README @@ -266,7 +266,7 @@ The list of requests - a (*) means it requires privileged access - and replies a and currently only BFL singles support this command On a BFL single it will flash the led on the front of the device for appoximately 4s - All other non BFL PGA devices will return an error + All other non BFL PGA devices will return a warning status message stating that they dont support it This adds a 4s delay to the BFL share being processed so you may get a message stating that procssing took diff --git a/api.c b/api.c index 839ea660..4aefcf01 100644 --- a/api.c +++ b/api.c @@ -551,7 +551,7 @@ struct CODES { { SEVERITY_SUCC, MSG_DEBUGSET,PARAM_STR, "Debug settings" }, #ifdef HAVE_AN_FPGA { SEVERITY_SUCC, MSG_PGAIDENT,PARAM_PGA, "Identify command sent to PGA%d" }, - { SEVERITY_ERR, MSG_PGANOID, PARAM_PGA, "PGA%d does not support identify" }, + { SEVERITY_WARN, MSG_PGANOID, PARAM_PGA, "PGA%d does not support identify" }, #endif { SEVERITY_FAIL, 0, 0, NULL } }; From 307d8da034f79e714572df886ae9c8d37ab765ca Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 4 Sep 2012 15:57:11 +1000 Subject: [PATCH 12/50] HW: error counter auto for all devices - ztex code not fixed --- cgminer.c | 24 +++++++++++++++++------- driver-modminer.c | 11 +++++------ findnonce.c | 16 ++++++++++++++-- miner.h | 1 - 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/cgminer.c b/cgminer.c index d124dc76..69976f33 100644 --- a/cgminer.c +++ b/cgminer.c @@ -4141,7 +4141,7 @@ err_out: return false; } -bool hashtest(const struct work *work) +static bool hashtest(struct thr_info *thr, const struct work *work) { uint32_t *data32 = (uint32_t *)(work->data); unsigned char swap[128]; @@ -4162,11 +4162,22 @@ bool hashtest(const struct work *work) memcpy((void*)work->hash, hash2, 32); - return fulltest(work->hash, work->target); + if (hash2_32[7] != 0) { + applog(LOG_WARNING, "%s%d: invalid nonce - HW error", + thr->cgpu->api->name, thr->cgpu->device_id); + hw_errors++; + thr->cgpu->hw_errors++; + return true; + } + + bool test = fulltest(work->hash, work->target); + if (!test) + applog(LOG_INFO, "Share below target"); + return test; } -bool test_nonce(struct work *work, uint32_t nonce) +static bool test_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) { if (opt_scrypt) { uint32_t *work_nonce = (uint32_t *)(work->data + 64 + 12); @@ -4180,7 +4191,7 @@ bool test_nonce(struct work *work, uint32_t nonce) work->data[64 + 12 + 2] = (nonce >> 16) & 0xff; work->data[64 + 12 + 3] = (nonce >> 24) & 0xff; - return hashtest(work); + return hashtest(thr, work); } bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) @@ -4191,10 +4202,9 @@ bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) /* Do one last check before attempting to submit the work */ /* Side effect: sets work->data for us */ - if (!test_nonce(work, nonce)) { - applog(LOG_INFO, "Share below target"); + if (!test_nonce(thr, work, nonce)) return true; - } + return submit_work_sync(thr, work); } diff --git a/driver-modminer.c b/driver-modminer.c index 040100db..750f9ec5 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -405,6 +405,7 @@ modminer_process_results(struct thr_info*thr) uint32_t nonce; long iter; bool bad; + int curr_hw_errors; cmd[0] = '\x0a'; cmd[1] = fpgaid; @@ -441,12 +442,10 @@ modminer_process_results(struct thr_info*thr) mutex_unlock(&modminer->device_mutex); if (memcmp(&nonce, "\xff\xff\xff\xff", 4)) { state->no_nonce_counter = 0; - bad = !test_nonce(work, nonce); - if (!bad) - submit_nonce(thr, work, nonce); - else { - ++hw_errors; - if (++modminer->hw_errors * 100 > 1000 + state->good_share_counter) + curr_hw_errors = modminer->hw_errors; + submit_nonce(thr, work, nonce); + if (modminer->hw_errors > curr_hw_errors) { + if (modminer->hw_errors * 100 > 1000 + state->good_share_counter) // Only reduce clocks if hardware errors are more than ~1% of results modminer_reduce_clock(thr, true); } diff --git a/findnonce.c b/findnonce.c index d557f17a..788835d9 100644 --- a/findnonce.c +++ b/findnonce.c @@ -131,6 +131,8 @@ void precalc_hash(dev_blk_ctx *blk, uint32_t *state, uint32_t *data) blk->sevenA = blk->ctx_h + SHA256_K[7]; } +#if 0 // not used any more + #define P(t) (W[(t)&0xF] = W[(t-16)&0xF] + (rotate(W[(t-15)&0xF], 25) ^ rotate(W[(t-15)&0xF], 14) ^ (W[(t-15)&0xF] >> 3)) + W[(t-7)&0xF] + (rotate(W[(t-2)&0xF], 15) ^ rotate(W[(t-2)&0xF], 13) ^ (W[(t-2)&0xF] >> 10))) #define IR(u) \ @@ -167,6 +169,8 @@ void precalc_hash(dev_blk_ctx *blk, uint32_t *state, uint32_t *data) R(E, F, G, H, A, B, C, D, P(u+4), SHA256_K[u+4]); \ R(D, E, F, G, H, A, B, C, P(u+5), SHA256_K[u+5]) +#endif + struct pc_data { struct thr_info *thr; struct work *work; @@ -175,6 +179,8 @@ struct pc_data { int found; }; +#if 0 // not used any more + static void send_sha_nonce(struct pc_data *pcd, cl_uint nonce) { dev_blk_ctx *blk = &pcd->work->blk; @@ -222,6 +228,8 @@ static void send_sha_nonce(struct pc_data *pcd, cl_uint nonce) } } +#endif + static void send_scrypt_nonce(struct pc_data *pcd, uint32_t nonce) { struct thr_info *thr = pcd->thr; @@ -238,6 +246,8 @@ static void send_scrypt_nonce(struct pc_data *pcd, uint32_t nonce) static void *postcalc_hash(void *userdata) { struct pc_data *pcd = (struct pc_data *)userdata; + struct thr_info *thr = pcd->thr; + struct work *work = pcd->work; unsigned int entry = 0; pthread_detach(pthread_self()); @@ -248,8 +258,10 @@ static void *postcalc_hash(void *userdata) applog(LOG_DEBUG, "OCL NONCE %u found in slot %d", nonce, entry); if (opt_scrypt) send_scrypt_nonce(pcd, nonce); - else - send_sha_nonce(pcd, nonce); + else { + if (unlikely(submit_nonce(thr, work, nonce) == false)) + applog(LOG_ERR, "Failed to submit work, exiting"); + } } free(pcd); diff --git a/miner.h b/miner.h index 6ac8d934..4771176f 100644 --- a/miner.h +++ b/miner.h @@ -844,7 +844,6 @@ struct modminer_fpga_state { #endif extern void get_datestamp(char *, struct timeval *); -extern bool test_nonce(struct work *work, uint32_t nonce); bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce); extern void tailsprintf(char *f, const char *fmt, ...); extern void wlogprint(const char *f, ...); From 9f9c688f72e003f21ecb86f703210580a07bbe11 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 11 Sep 2012 14:29:08 +1000 Subject: [PATCH 13/50] README - FPGA device FAQ --- README | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/README b/README index 11caccc2..c0c3afa4 100644 --- a/README +++ b/README @@ -843,10 +843,27 @@ They are Field-Programmable Gate Arrays that have been programmed to do Bitcoin mining. Since the acronym needs to be only 3 characters, the "Field-" part has been skipped. -Q: How do I get my BFL device to auto-recognise? -A: The only thing that needs to be done is to load the driver for them, which -on linux would require: -sudo modprobe ftdi_sio vendor=0x0403 product=0x6014 +Q: How do I get my BFL/Icarus/Lancelot/Cairnsmore device to auto-recognise? +A: On linux, if the /dev/ttyUSB* devices don't automatically appear, the only +thing that needs to be done is to load the driver for them: +BFL: sudo modprobe ftdi_sio vendor=0x0403 product=0x6014 +Icarus: sudo modprobe pl2303 vendor=0x067b product=0x230 +Lancelot: sudo modprobe ftdi_sio vendor=0x0403 product=0x6001 +Cairnsmore: sudo modprobe ftdi_sio product=0x8350 vendor=0x0403 +On windows you must install the pl2303 or ftdi driver requird for the device +pl2303: http://prolificusa.com/pl-2303hx-drivers/ +ftdi: http://www.ftdichip.com/Drivers/VCP.htm + +Q: On linux I can see the /dev/ttyUSB* devices for my ICA/BFL/MMQ FPGA, but +cgminer can't mine on them +A: Make sure you have the required priviledges to access the /dev/ttyUSB* devices: + sudo ls -las /dev/ttyUSB* +will give output like: + 0 crw-rw---- 1 root dialout 188, 0 2012-09-11 13:49 /dev/ttyUSB0 +This means your account must have the group 'dialout' or root priviledges +To permanently give your account the 'dialout' group: + sudo usermod -G dialout `whoami` +Then logout and back in again --- From 6b2deb0afabaee5e1552bb493ca3e805544fe997 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 11 Sep 2012 16:27:39 +1000 Subject: [PATCH 14/50] README spelling/etc --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index c0c3afa4..1438008a 100644 --- a/README +++ b/README @@ -816,7 +816,7 @@ driver version and ATI stream version. Q: cgminer reports no devices or only one device on startup on Linux although I have multiple devices and drivers+SDK installed properly? -A: Try 'export DISPLAY=:0" before running cgminer. +A: Try "export DISPLAY=:0" before running cgminer. Q: My network gets slower and slower and then dies for a minute? A; Try the --net-delay option. @@ -850,7 +850,7 @@ BFL: sudo modprobe ftdi_sio vendor=0x0403 product=0x6014 Icarus: sudo modprobe pl2303 vendor=0x067b product=0x230 Lancelot: sudo modprobe ftdi_sio vendor=0x0403 product=0x6001 Cairnsmore: sudo modprobe ftdi_sio product=0x8350 vendor=0x0403 -On windows you must install the pl2303 or ftdi driver requird for the device +On windows you must install the pl2303 or ftdi driver required for the device pl2303: http://prolificusa.com/pl-2303hx-drivers/ ftdi: http://www.ftdichip.com/Drivers/VCP.htm From cef9731fbcd2138888575f6d06df0f84d7156f57 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 12 Sep 2012 07:44:00 +1000 Subject: [PATCH 15/50] CURL support for individual proxy per pool and all proxy types --- README | 24 +++++++++++++++++++- api.c | 7 ++++++ cgminer.c | 6 +++++ miner.h | 4 ++++ util.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 106 insertions(+), 2 deletions(-) diff --git a/README b/README index 1438008a..e2a005fe 100644 --- a/README +++ b/README @@ -168,7 +168,7 @@ Options for both config file and command line: --scrypt Use the scrypt algorithm for mining (litecoin only) --sharelog Append share log to file --shares Quit after mining N shares (default: unlimited) ---socks-proxy Set socks4 proxy (host:port) +--socks-proxy Set socks4 proxy (host:port) for all pools without a proxy specified --syslog Use system log for output messages (default: standard error) --temp-cutoff Temperature where a device will be automatically disabled, one value or comma separated list (default: 95) --text-only|-T Disable ncurses formatted screen output @@ -295,6 +295,28 @@ Add overclocking settings, GPU and fan control with different engine settings fo cgminer -o http://pool:port -u username -p password -I 9 --auto-fan --auto-gpu --gpu-engine 750-950,945,700-930,960 --gpu-memclock 300 +Single pool with a standard http proxy, regular desktop: + +cgminer -o http:proxy:port|http://pool:port -u username -p password + +Single pool with a socks5 proxy, regular desktop: + +cgminer -o socks5:proxy:port|http://pool:port -u username -p password + +The list of proxy types are: + http: standard http 1.1 proxy + http0: http 1.0 proxy + socks4: socks4 proxy + socks5: socks5 proxy + socks4a: socks4a proxy + socks5h: socks5 proxy using a hostname + +If you compile cgminer with a version of CURL before 7.19.4 then some of the above will +not be available. All are available since CURL version 7.19.4 + +If you specify the --socks-proxy option to cgminer, it will only be applied to all pools +that don't specify their own proxy setting like above + READ WARNINGS AND DOCUMENTATION BELOW ABOUT OVERCLOCKING On Linux you virtually always need to export your display settings before diff --git a/api.c b/api.c index 4aefcf01..e3185188 100644 --- a/api.c +++ b/api.c @@ -1841,6 +1841,13 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, root = api_add_escape(root, "User", pool->rpc_user, false); root = api_add_time(root, "Last Share Time", &(pool->last_share_time), false); root = api_add_int(root, "Diff1 Work", &(pool->diff1), false); + if (pool->rpc_proxy) { + root = api_add_const(root, "Proxy Type", proxytype(pool->rpc_proxytype), false); + root = api_add_escape(root, "Proxy", pool->rpc_proxy, false); + } else { + root = api_add_const(root, "Proxy Type", BLANK, false); + root = api_add_const(root, "Proxy", BLANK, false); + } if (isjson && (i > 0)) strcat(io_buffer, COMMA); diff --git a/cgminer.c b/cgminer.c index 69976f33..e1a37a17 100644 --- a/cgminer.c +++ b/cgminer.c @@ -419,6 +419,8 @@ static struct pool *add_pool(void) /* Make sure the pool doesn't think we've been idle since time 0 */ pool->tv_idle.tv_sec = ~0UL; + pool->rpc_proxy = NULL; + return pool; } @@ -547,6 +549,8 @@ static char *set_url(char *arg) add_pool(); pool = pools[total_urls - 1]; + arg = get_proxy(arg, pool); + opt_set_charp(arg, &pool->rpc_url); if (strncmp(arg, "http://", 7) && strncmp(arg, "https://", 8)) { @@ -4999,6 +5003,8 @@ void add_pool_details(bool live, char *url, char *user, char *pass) pool = add_pool(); + url = get_proxy(url, pool); + pool->rpc_url = url; pool->rpc_user = user; pool->rpc_pass = pass; diff --git a/miner.h b/miner.h index 4771176f..3167fabd 100644 --- a/miner.h +++ b/miner.h @@ -592,6 +592,8 @@ extern const uint32_t sha256_init_state[]; extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, const char *rpc_req, bool, bool, int *, struct pool *pool, bool); +extern const char *proxytype(curl_proxytype proxytype); +extern char *get_proxy(char *url, struct pool *pool); extern char *bin2hex(const unsigned char *p, size_t len); extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len); @@ -770,6 +772,8 @@ struct pool { char *rpc_url; char *rpc_userpass; char *rpc_user, *rpc_pass; + curl_proxytype rpc_proxytype; + char *rpc_proxy; pthread_mutex_t pool_lock; diff --git a/util.c b/util.c index 724ffa9d..27866531 100644 --- a/util.c +++ b/util.c @@ -305,7 +305,10 @@ json_t *json_rpc_call(CURL *curl, const char *url, curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, resp_hdr_cb); curl_easy_setopt(curl, CURLOPT_HEADERDATA, &hi); curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY); - if (opt_socks_proxy) { + if (pool->rpc_proxy) { + curl_easy_setopt(curl, CURLOPT_PROXY, pool->rpc_proxy); + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, pool->rpc_proxytype); + } else if (opt_socks_proxy) { curl_easy_setopt(curl, CURLOPT_PROXY, opt_socks_proxy); curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); } @@ -460,6 +463,68 @@ err_out: return NULL; } +#if (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 10) || (LIBCURL_VERSION_MAJOR > 7) +static struct { + const char *name; + curl_proxytype proxytype; +} proxynames[] = { + { "http:", CURLPROXY_HTTP }, +#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR > 19) || (LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH >= 4) + { "http0:", CURLPROXY_HTTP_1_0 }, +#endif +#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR > 15) || (LIBCURL_VERSION_MINOR == 15 && LIBCURL_VERSION_PATCH >= 2) + { "socks4:", CURLPROXY_SOCKS4 }, +#endif + { "socks5:", CURLPROXY_SOCKS5 }, +#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR >= 18) + { "socks4a:", CURLPROXY_SOCKS4A }, + { "socks5h:", CURLPROXY_SOCKS5_HOSTNAME }, +#endif +}; +#endif + +const char *proxytype(curl_proxytype proxytype) +{ + int i; + + for (i = 0; proxynames[i].name; i++) + if (proxynames[i].proxytype == proxytype) + return proxynames[i].name; + + return "invalid"; +} + +char *get_proxy(char *url, struct pool *pool) +{ + pool->rpc_proxy = NULL; + +#if (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 10) || (LIBCURL_VERSION_MAJOR > 7) + char *split; + int plen, len, i; + + for (i = 0; proxynames[i].name; i++) { + plen = strlen(proxynames[i].name); + if (strncmp(url, proxynames[i].name, plen) == 0) { + if (!(split = strchr(url, '|'))) + return url; + + *split = '\0'; + len = split - url; + pool->rpc_proxy = malloc(1 + len - plen); + if (!(pool->rpc_proxy)) + quit(1, "Failed to malloc rpc_proxy"); + + strcpy(pool->rpc_proxy, url); + pool->rpc_proxytype = proxynames[i].proxytype; + url = split + 1; + break; + } + } +#endif + return url; +} + + char *bin2hex(const unsigned char *p, size_t len) { char *s = malloc((len * 2) + 1); From e043f5a5aa8b7e7c54a7fc64efbdb770365a4517 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 12 Sep 2012 08:32:00 +1000 Subject: [PATCH 16/50] bug: remove proxy: from the front of the proxy used --- util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.c b/util.c index 27866531..59743fdd 100644 --- a/util.c +++ b/util.c @@ -514,7 +514,7 @@ char *get_proxy(char *url, struct pool *pool) if (!(pool->rpc_proxy)) quit(1, "Failed to malloc rpc_proxy"); - strcpy(pool->rpc_proxy, url); + strcpy(pool->rpc_proxy, url + plen); pool->rpc_proxytype = proxynames[i].proxytype; url = split + 1; break; From 68046631d5670af20d027fb6a15d090146cdbd1b Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 12 Sep 2012 08:46:53 +1000 Subject: [PATCH 17/50] README URL proxy must use quote so show in the example --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index e2a005fe..4baa0d27 100644 --- a/README +++ b/README @@ -297,11 +297,11 @@ cgminer -o http://pool:port -u username -p password -I 9 --auto-fan --auto-gpu - Single pool with a standard http proxy, regular desktop: -cgminer -o http:proxy:port|http://pool:port -u username -p password +cgminer -o "http:proxy:port|http://pool:port" -u username -p password Single pool with a socks5 proxy, regular desktop: -cgminer -o socks5:proxy:port|http://pool:port -u username -p password +cgminer -o "socks5:proxy:port|http://pool:port" -u username -p password The list of proxy types are: http: standard http 1.1 proxy From 6c2515752fca6ff96362924fe87701601983835d Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 12 Sep 2012 19:05:50 +1000 Subject: [PATCH 18/50] API-README update for pools proxy info --- API-README | 1 + 1 file changed, 1 insertion(+) diff --git a/API-README b/API-README index bd2811c9..2d72d811 100644 --- a/API-README +++ b/API-README @@ -383,6 +383,7 @@ Modified API commands: 'gpu|N' - add 'Diff1 Work' 'pga|N' - add 'Diff1 Work' 'notify' - add '*Dev Throttle' (for BFL Singles) + 'pools' - add 'Proxy Type', 'Proxy' ---------- From 0ac350547ef00bc4f3121cbab47cee47fc0bda60 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 12 Sep 2012 19:32:37 +1000 Subject: [PATCH 19/50] --default-config - allow command line to define the default configuration file for loading and saving --- cgminer.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/cgminer.c b/cgminer.c index e1a37a17..8adc8825 100644 --- a/cgminer.c +++ b/cgminer.c @@ -226,6 +226,7 @@ static struct block *blocks = NULL; char *opt_socks_proxy = NULL; static const char def_conf[] = "cgminer.conf"; +static char *default_config; static bool config_loaded; static int include_count; #define JSON_INCLUDE_CONF "include" @@ -1175,21 +1176,21 @@ static char *load_config(const char *arg, void __maybe_unused *unused) return parse_config(config, true); } +static char *set_default_config(const char *arg) +{ + opt_set_charp(arg, &default_config); + + return NULL; +} + +void default_save_file(char *filename); + static void load_default_config(void) { cnfbuf = malloc(PATH_MAX); -#if defined(unix) - if (getenv("HOME") && *getenv("HOME")) { - strcpy(cnfbuf, getenv("HOME")); - strcat(cnfbuf, "/"); - } else - strcpy(cnfbuf, ""); - strcat(cnfbuf, ".cgminer/"); -#else - strcpy(cnfbuf, ""); -#endif - strcat(cnfbuf, def_conf); + default_save_file(cnfbuf); + if (!access(cnfbuf, R_OK)) load_config(cnfbuf, NULL); else { @@ -1237,6 +1238,10 @@ static struct opt_table opt_cmdline_table[] = { load_config, NULL, NULL, "Load a JSON-format configuration file\n" "See example.conf for an example configuration."), + OPT_WITH_ARG("--default-config", + set_default_config, NULL, NULL, + "Specify the filename of the default config file\n" + "Loaded at start and used when saving without a name."), OPT_WITHOUT_ARG("--help|-h", opt_verusage_and_exit, NULL, "Print this message"), @@ -3484,6 +3489,11 @@ retry: void default_save_file(char *filename) { + if (default_config && *default_config) { + strcpy(filename, default_config); + return; + } + #if defined(unix) if (getenv("HOME") && *getenv("HOME")) { strcpy(filename, getenv("HOME")); From fced503ed6c771e1089a3680536a63015add5fb2 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 12 Sep 2012 19:45:49 +1000 Subject: [PATCH 20/50] save individual pool proxy settings to config --- cgminer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index 8adc8825..b0197983 100644 --- a/cgminer.c +++ b/cgminer.c @@ -3098,7 +3098,11 @@ void write_config(FILE *fcfg) /* Write pool values */ fputs("{\n\"pools\" : [", fcfg); for(i = 0; i < total_pools; i++) { - fprintf(fcfg, "%s\n\t{\n\t\t\"url\" : \"%s\",", i > 0 ? "," : "", json_escape(pools[i]->rpc_url)); + fprintf(fcfg, "%s\n\t{\n\t\t\"url\" : \"%s%s%s%s\",", i > 0 ? "," : "", + pools[i]->rpc_proxy ? json_escape((char *)proxytype(pools[i]->rpc_proxytype)) : "", + pools[i]->rpc_proxy ? json_escape(pools[i]->rpc_proxy) : "", + pools[i]->rpc_proxy ? "|" : "", + json_escape(pools[i]->rpc_url)); fprintf(fcfg, "\n\t\t\"user\" : \"%s\",", json_escape(pools[i]->rpc_user)); fprintf(fcfg, "\n\t\t\"pass\" : \"%s\"\n\t}", json_escape(pools[i]->rpc_pass)); } From e649aa39061abbc9bfd8c9172333b7ccacfad292 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 12 Sep 2012 20:10:00 +1000 Subject: [PATCH 21/50] HW: dont submit bad shares --- cgminer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index b0197983..f42e0e0e 100644 --- a/cgminer.c +++ b/cgminer.c @@ -4185,7 +4185,7 @@ static bool hashtest(struct thr_info *thr, const struct work *work) thr->cgpu->api->name, thr->cgpu->device_id); hw_errors++; thr->cgpu->hw_errors++; - return true; + return false; } bool test = fulltest(work->hash, work->target); From 99f0607fb2b028b8df96228bb9705d9a70e57166 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 12 Sep 2012 23:26:43 +1000 Subject: [PATCH 22/50] API add display of and setting queue,scantime,expiry --- API-README | 14 +++++++++++++- api.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cgminer.c | 2 +- miner.h | 2 ++ 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/API-README b/API-README index 2d72d811..4ac86b9f 100644 --- a/API-README +++ b/API-README @@ -124,7 +124,10 @@ The list of requests - a (*) means it requires privileged access - and replies a Log Interval=N, <- log interval (--log N) Device Code=GPU ICA , <- spaced list of compiled devices OS=Linux/Apple/..., <- operating System - Failover-Only=true/false | <- failover-only setting + Failover-Only=true/false, <- failover-only setting + ScanTime=N, <- --scan-time setting + Queue=N, <- --queue setting + Expiry=N| <- --expiry setting summary SUMMARY The status summary of the miner e.g. Elapsed=NNN,Found Blocks=N,Getworks=N,...| @@ -318,6 +321,13 @@ The list of requests - a (*) means it requires privileged access - and replies a RPCProto=true/false, PerDevice=true/false| + setconfig|name,N (*) + none There is no reply section just the STATUS section + stating the results of setting 'name' to N + The valid values for name are currently: + queue, scantime, expiry + N is an integer in the range 0 to 9999 + When you enable, disable or restart a GPU or PGA, you will also get Thread messages in the cgminer status window @@ -376,6 +386,7 @@ API V1.19 Added API commands: 'debug' 'pgaidentify|N' + 'setconfig|name,N' Modified API commands: Change pool field name 'Diff1 Shares' to 'Diff1 Work' @@ -384,6 +395,7 @@ Modified API commands: 'pga|N' - add 'Diff1 Work' 'notify' - add '*Dev Throttle' (for BFL Singles) 'pools' - add 'Proxy Type', 'Proxy' + 'config' - add 'Queue', 'Expiry' ---------- diff --git a/api.c b/api.c index e3185188..2e61aba6 100644 --- a/api.c +++ b/api.c @@ -259,6 +259,7 @@ static const char *OSINFO = #define _CHECK "CHECK" #define _MINECOIN "COIN" #define _DEBUGSET "DEBUG" +#define _SETCONFIG "SETCONFIG" static const char ISJSON = '{'; #define JSON0 "{" @@ -297,6 +298,7 @@ static const char ISJSON = '{'; #define JSON_CHECK JSON1 _CHECK JSON2 #define JSON_MINECOIN JSON1 _MINECOIN JSON2 #define JSON_DEBUGSET JSON1 _DEBUGSET JSON2 +#define JSON_SETCONFIG JSON1 _SETCONFIG JSON2 #define JSON_END JSON4 JSON5 static const char *JSON_COMMAND = "command"; @@ -395,6 +397,11 @@ static const char *JSON_PARAMETER = "parameter"; #define MSG_DEBUGSET 79 #define MSG_PGAIDENT 80 #define MSG_PGANOID 81 +#define MSG_SETCONFIG 82 +#define MSG_UNKCON 83 +#define MSG_INVNUM 84 +#define MSG_CONPAR 85 +#define MSG_CONVAL 86 enum code_severity { SEVERITY_ERR, @@ -423,6 +430,7 @@ enum code_parameters { PARAM_STR, PARAM_BOTH, PARAM_BOOL, + PARAM_SET, PARAM_NONE }; @@ -553,6 +561,11 @@ struct CODES { { SEVERITY_SUCC, MSG_PGAIDENT,PARAM_PGA, "Identify command sent to PGA%d" }, { SEVERITY_WARN, MSG_PGANOID, PARAM_PGA, "PGA%d does not support identify" }, #endif + { SEVERITY_SUCC, MSG_SETCONFIG,PARAM_SET, "Set config '%s' to %d" }, + { SEVERITY_ERR, MSG_UNKCON, PARAM_STR, "Unknown config '%s'" }, + { SEVERITY_ERR, MSG_INVNUM, PARAM_BOTH, "Invalid number (%d) for '%s' range is 0-9999" }, + { SEVERITY_ERR, MSG_CONPAR, PARAM_NONE, "Missing config parameters 'name\\,N'" }, + { SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s\\,N'" }, { SEVERITY_FAIL, 0, 0, NULL } }; @@ -1165,6 +1178,9 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) case PARAM_BOOL: sprintf(buf, codes[i].description, paramid ? TRUESTR : FALSESTR); break; + case PARAM_SET: + sprintf(buf, codes[i].description, param2, paramid); + break; case PARAM_NONE: default: strcpy(buf, codes[i].description); @@ -1267,6 +1283,8 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, root = api_add_const(root, "OS", OSINFO, false); root = api_add_bool(root, "Failover-Only", &opt_fail_only, false); root = api_add_int(root, "ScanTime", &opt_scantime, false); + root = api_add_int(root, "Queue", &opt_queue, false); + root = api_add_int(root, "Expiry", &opt_expiry, false); root = print_data(root, buf, isjson); if (isjson) @@ -2917,6 +2935,43 @@ static void debugstate(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __ strcat(io_buffer, buf); } +static void setconfig(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) +{ + char *comma; + int value; + + if (param == NULL || *param == '\0') { + strcpy(io_buffer, message(MSG_CONPAR, 0, NULL, isjson)); + return; + } + + comma = strchr(param, ','); + if (!comma) { + strcpy(io_buffer, message(MSG_CONVAL, 0, param, isjson)); + return; + } + + *(comma++) = '\0'; + value = atoi(comma); + if (value < 0 || value > 9999) { + strcpy(io_buffer, message(MSG_INVNUM, value, param, isjson)); + return; + } + + if (strcasecmp(param, "queue") == 0) + opt_queue = value; + else if (strcasecmp(param, "scantime") == 0) + opt_scantime = value; + else if (strcasecmp(param, "expiry") == 0) + opt_expiry = value; + else { + strcpy(io_buffer, message(MSG_UNKCON, 0, param, isjson)); + return; + } + + strcpy(io_buffer, message(MSG_SETCONFIG, value, param, isjson)); +} + static void checkcommand(__maybe_unused SOCKETTYPE c, char *param, bool isjson, char group); struct CMDS { @@ -2971,6 +3026,7 @@ struct CMDS { { "failover-only", failoveronly, true }, { "coin", minecoin, false }, { "debug", debugstate, true }, + { "setconfig", setconfig, true }, { NULL, NULL, false } }; diff --git a/cgminer.c b/cgminer.c index f42e0e0e..9e9ef642 100644 --- a/cgminer.c +++ b/cgminer.c @@ -93,7 +93,7 @@ bool opt_realquiet; bool opt_loginput; const int opt_cutofftemp = 95; int opt_log_interval = 5; -static int opt_queue = 1; +int opt_queue = 1; int opt_scantime = 60; int opt_expiry = 120; int opt_bench_algo = -1; diff --git a/miner.h b/miner.h index 3167fabd..924bc852 100644 --- a/miner.h +++ b/miner.h @@ -607,7 +607,9 @@ typedef bool (*sha256_func)(struct thr_info*, const unsigned char *pmidstate, extern bool fulltest(const unsigned char *hash, const unsigned char *target); +extern int opt_queue; extern int opt_scantime; +extern int opt_expiry; extern pthread_mutex_t console_lock; extern pthread_mutex_t ch_lock; From fd2fa260c788cf2bca2449d41dfb3f78ec624612 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 12 Sep 2012 23:27:48 +1000 Subject: [PATCH 23/50] api.c add missing escape for comma in MSG_PGAUNW --- api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.c b/api.c index 2e61aba6..51f9d3b8 100644 --- a/api.c +++ b/api.c @@ -496,7 +496,7 @@ struct CODES { { SEVERITY_INFO, MSG_PGALRDIS,PARAM_PGA, "PGA %d already disabled" }, { SEVERITY_INFO, MSG_PGAENA, PARAM_PGA, "PGA %d sent enable message" }, { SEVERITY_INFO, MSG_PGADIS, PARAM_PGA, "PGA %d set disable flag" }, - { SEVERITY_ERR, MSG_PGAUNW, PARAM_PGA, "PGA %d is not flagged WELL, cannot enable" }, + { SEVERITY_ERR, MSG_PGAUNW, PARAM_PGA, "PGA %d is not flagged WELL\\, cannot enable" }, #endif #ifdef WANT_CPUMINE { SEVERITY_ERR, MSG_CPUNON, PARAM_NONE, "No CPUs" }, From ade940bcbad27c7c5dfe6cc8b76995f50cdd7611 Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 13 Sep 2012 09:44:58 +1000 Subject: [PATCH 24/50] api.c all STATUS messages automatically escaped --- api.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api.c b/api.c index 51f9d3b8..67f0d78b 100644 --- a/api.c +++ b/api.c @@ -496,7 +496,7 @@ struct CODES { { SEVERITY_INFO, MSG_PGALRDIS,PARAM_PGA, "PGA %d already disabled" }, { SEVERITY_INFO, MSG_PGAENA, PARAM_PGA, "PGA %d sent enable message" }, { SEVERITY_INFO, MSG_PGADIS, PARAM_PGA, "PGA %d set disable flag" }, - { SEVERITY_ERR, MSG_PGAUNW, PARAM_PGA, "PGA %d is not flagged WELL\\, cannot enable" }, + { SEVERITY_ERR, MSG_PGAUNW, PARAM_PGA, "PGA %d is not flagged WELL, cannot enable" }, #endif #ifdef WANT_CPUMINE { SEVERITY_ERR, MSG_CPUNON, PARAM_NONE, "No CPUs" }, @@ -564,8 +564,8 @@ struct CODES { { SEVERITY_SUCC, MSG_SETCONFIG,PARAM_SET, "Set config '%s' to %d" }, { SEVERITY_ERR, MSG_UNKCON, PARAM_STR, "Unknown config '%s'" }, { SEVERITY_ERR, MSG_INVNUM, PARAM_BOTH, "Invalid number (%d) for '%s' range is 0-9999" }, - { SEVERITY_ERR, MSG_CONPAR, PARAM_NONE, "Missing config parameters 'name\\,N'" }, - { SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s\\,N'" }, + { SEVERITY_ERR, MSG_CONPAR, PARAM_NONE, "Missing config parameters 'name,N'" }, + { SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s,N'" }, { SEVERITY_FAIL, 0, 0, NULL } }; @@ -1189,8 +1189,8 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) root = api_add_string(root, _STATUS, severity, false); root = api_add_time(root, "When", &when, false); root = api_add_int(root, "Code", &messageid, false); - root = api_add_string(root, "Msg", buf, false); - root = api_add_string(root, "Description", opt_api_description, false); + root = api_add_escape(root, "Msg", buf, false); + root = api_add_escape(root, "Description", opt_api_description, false); root = print_data(root, ptr, isjson); if (isjson) @@ -1204,8 +1204,8 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) int id = -1; root = api_add_int(root, "Code", &id, false); sprintf(buf, "%d", messageid); - root = api_add_string(root, "Msg", buf, false); - root = api_add_string(root, "Description", opt_api_description, false); + root = api_add_escape(root, "Msg", buf, false); + root = api_add_escape(root, "Description", opt_api_description, false); root = print_data(root, ptr, isjson); if (isjson) From db0269a238de060c6675a473783226c06b9e133d Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 13 Sep 2012 12:40:27 +1000 Subject: [PATCH 25/50] miner.php by default don't display IP/Port numbers in error messages --- API-README | 8 ++++++++ miner.php | 47 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/API-README b/API-README index 4ac86b9f..0e661700 100644 --- a/API-README +++ b/API-README @@ -924,6 +924,14 @@ e.g. $rigs = array('127.0.0.1:4028','myrig.com:4028:Sugoi'); --------- +Default: + $rigipsecurity = true; + +Set $rigipsecurity to false to show the IP/Port of the rig +in the socket error messages and also show the full socket message + +--------- + Default: $rigtotals = true; $forcerigtotals = false; diff --git a/miner.php b/miner.php index 07a5fb57..7ead4e9b 100644 --- a/miner.php +++ b/miner.php @@ -2,7 +2,7 @@ session_start(); # global $title, $miner, $port, $readonly, $notify, $rigs; -global $rigtotals, $forcerigtotals; +global $rgisecurity, $rigtotals, $forcerigtotals; global $socksndtimeoutsec, $sockrcvtimeoutsec; global $checklastshare, $poolinputs, $hidefields; global $ignorerefresh, $changerefresh, $autorefresh; @@ -40,6 +40,10 @@ $poolinputs = false; # format: 'IP:Port' or 'Host:Port' or 'Host:Port:Name' $rigs = array('127.0.0.1:4028'); # +# Set $rigipsecurity to false to show the IP/Port of the rig +# in the socket error messages and also show the full socket message +$rigipsecurity = true; +# # Set $rigtotals to true to display totals on the single rig page # 'false' means no totals (and ignores $forcerigtotals) # You can force it to always show rig totals when there is only @@ -226,7 +230,7 @@ function htmlhead($checkapi, $rig, $pg = null) if ($readonly === false && $checkapi === true) { $error = null; - $access = api('privileged'); + $access = api($rig, 'privileged'); if ($error != null || !isset($access['STATUS']['STATUS']) || $access['STATUS']['STATUS'] != 'S') @@ -275,8 +279,9 @@ global $haderror, $error; $haderror = false; $error = null; # -function getsock($addr, $port) +function getsock($rig, $addr, $port) { + global $rigipsecurity; global $haderror, $error, $socksndtimeoutsec, $sockrcvtimeoutsec; $error = null; @@ -285,9 +290,15 @@ function getsock($addr, $port) if ($socket === false || $socket === null) { $haderror = true; - $error = socket_strerror(socket_last_error()); - $msg = "socket create(TCP) failed"; - $error = "ERR: $msg '$error'\n"; + if ($rigipsecurity === false) + { + $error = socket_strerror(socket_last_error()); + $msg = "socket create(TCP) failed"; + $error = "ERR: $msg '$error'\n"; + } + else + $error = "ERR: socket create(TCP) failed\n"; + return null; } @@ -301,9 +312,15 @@ function getsock($addr, $port) if ($res === false) { $haderror = true; - $error = socket_strerror(socket_last_error()); - $msg = "socket connect($addr,$port) failed"; - $error = "ERR: $msg '$error'\n"; + if ($rigipsecurity === false) + { + $error = socket_strerror(socket_last_error()); + $msg = "socket connect($addr,$port) failed"; + $error = "ERR: $msg '$error'\n"; + } + else + $error = "ERR: socket connect($rig) failed\n"; + socket_close($socket); return null; } @@ -365,12 +382,12 @@ function revert($str) return str_replace(array("\1", "\2", "\3", "\4"), array("|", "\\", "=", ","), $str); } # -function api($cmd) +function api($rig, $cmd) { global $haderror, $error; global $miner, $port, $hidefields; - $socket = getsock($miner, $port); + $socket = getsock($rig, $miner, $port); if ($socket != null) { socket_write($socket, $cmd, strlen($cmd)); @@ -1071,7 +1088,7 @@ function processgpus($rig) global $error; global $warnfont, $warnoff; - $gpus = api('gpucount'); + $gpus = api($rig, 'gpucount'); if ($error != null) otherrow("Error getting GPU count: $warnfont$error$warnoff"); @@ -1140,7 +1157,7 @@ function process($cmds, $rig) $count = count($cmds); foreach ($cmds as $cmd => $des) { - $process = api($cmd); + $process = api($rig, $cmd); if ($error != null) { @@ -1255,7 +1272,7 @@ function doforeach($cmd, $des, $sum, $head, $datetime) else $name = $num; - $ans = api($cmd); + $ans = api($name, $cmd); if ($error != null) { @@ -1767,7 +1784,7 @@ function processcustompage($pagename, $sections, $sum, $namemap) foreach ($cmds as $cmd => $one) { - $process = api($cmd); + $process = api($name, $cmd); if ($error != null) { From 7293a8a9ac09b74b38267d8e1f19ae609d005b81 Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 13 Sep 2012 21:50:18 +1000 Subject: [PATCH 26/50] miner.php oops - mistype --- miner.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miner.php b/miner.php index 7ead4e9b..268e05bf 100644 --- a/miner.php +++ b/miner.php @@ -2,7 +2,7 @@ session_start(); # global $title, $miner, $port, $readonly, $notify, $rigs; -global $rgisecurity, $rigtotals, $forcerigtotals; +global $rigipsecurity, $rigtotals, $forcerigtotals; global $socksndtimeoutsec, $sockrcvtimeoutsec; global $checklastshare, $poolinputs, $hidefields; global $ignorerefresh, $changerefresh, $autorefresh; From fe7a967d5680d9ff113b60cb306655acb2642298 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 15 Sep 2012 00:39:54 +1000 Subject: [PATCH 27/50] Icarus - ignore hardware errors in timing mode --- driver-icarus.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/driver-icarus.c b/driver-icarus.c index f1cf9d17..33b875d7 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -639,7 +639,8 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, struct timeval tv_start, tv_finish, elapsed; struct timeval tv_history_start, tv_history_finish; double Ti, Xi; - int i; + int curr_hw_errors, i; + bool was_hw_error; struct ICARUS_HISTORY *history0, *history; int count; @@ -712,7 +713,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, nonce = swab32(nonce); #endif + curr_hw_errors = icarus->hw_errors; submit_nonce(thr, work, nonce); + was_hw_error = (curr_hw_errors > icarus->hw_errors); hash_count = (nonce & info->nonce_mask); hash_count++; @@ -726,8 +729,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, icarus->device_id, nonce, hash_count, elapsed.tv_sec, elapsed.tv_usec); } - // ignore possible end condition values + // ignore possible end condition values ... and hw errors if (info->do_icarus_timing + && !was_hw_error && ((nonce & info->nonce_mask) > END_CONDITION) && ((nonce & info->nonce_mask) < (info->nonce_mask & ~END_CONDITION))) { gettimeofday(&tv_history_start, NULL); From bd3c98aaafd2c819e9b11a46eebcea85f38deb49 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 15 Sep 2012 14:04:57 +1000 Subject: [PATCH 28/50] Optional WorkTime details with each Accepted/Rejected work item --- API-README | 6 ++++-- README | 16 +++++++++++++++ api.c | 5 +++++ cgminer.c | 59 ++++++++++++++++++++++++++++++++++++++++++++---------- miner.h | 9 +++++++++ util.c | 6 ++++++ 6 files changed, 88 insertions(+), 13 deletions(-) diff --git a/API-README b/API-README index 0e661700..1fa904da 100644 --- a/API-README +++ b/API-README @@ -312,14 +312,16 @@ The list of requests - a (*) means it requires privileged access - and replies a the screen curses debug settings You can only specify one setting Only the first character is checked (case insensitive): - Silent, Quiet, Verbose, Debug, RPCProto, PerDevice, Normal + Silent, Quiet, Verbose, Debug, RPCProto, PerDevice, + WorkTime, Normal The output fields are (as above): Silent=true/false, Quiet=true/false, Verbose=true/false, Debug=true/false, RPCProto=true/false, - PerDevice=true/false| + PerDevice=true/false, + WorkTime=true/false| setconfig|name,N (*) none There is no reply section just the STATUS section diff --git a/README b/README index 4baa0d27..7f6f95d7 100644 --- a/README +++ b/README @@ -473,6 +473,22 @@ it will log to a file called logfile.txt and otherwise work the same. There is also the -m option on linux which will spawn a command of your choice and pipe the output directly to that command. +The WorkTime details 'debug' option adds details on the end of each line +displayed for Accepted or Rejected work done. An example would be: + + <-00000223.95214f4c O G:0.524 (97.672) W:4.910 (0.000) S:0.577 R:13:49:55 + +The first 2 hex codes are the previous block hash, the rest are reported in +seconds unless stated otherwise: +The previous hash is followed by 'C' or 'O' if the work was cloned or original, +G:n.nnn is how long the original getwork to the pool took, (m.mmm) is how long +from the original getwork complete until work started, W:n.nnn is how long the +work took to process until it was ready to submit, (m.mmm) is how long from +ready to submit to actually doing the submit, this is usually 0.000 unless +there was a problem with the first attempt at submitting the work, S:n.nnn +is how long it took to submit the work and await the reply, R:hh:mm:ss is the +actual time the work submit reply was received - so you can count back from +that to work out each absolute time If you start cgminer with the --sharelog option, you can get detailed information for each share found. The argument to the option may be "-" for diff --git a/api.c b/api.c index 67f0d78b..ddd938ae 100644 --- a/api.c +++ b/api.c @@ -2911,6 +2911,10 @@ static void debugstate(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __ opt_quiet = false; opt_protocol = false; want_per_device_stats = false; + opt_worktime = false; + break; + case 'w': + opt_worktime ^= true; break; default: // anything else just reports the settings @@ -2928,6 +2932,7 @@ static void debugstate(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __ root = api_add_bool(root, "Debug", &opt_debug, false); root = api_add_bool(root, "RPCProto", &opt_protocol, false); root = api_add_bool(root, "PerDevice", &want_per_device_stats, false); + root = api_add_bool(root, "WorkTime", &opt_worktime, false); root = print_data(root, buf, isjson); if (isjson) diff --git a/cgminer.c b/cgminer.c index 9e9ef642..791875ff 100644 --- a/cgminer.c +++ b/cgminer.c @@ -142,6 +142,7 @@ bool opt_delaynet; bool opt_disable_pool = true; char *opt_icarus_options = NULL; char *opt_icarus_timing = NULL; +bool opt_worktime; char *opt_kernel_path; char *cgminer_path; @@ -1063,6 +1064,9 @@ static struct opt_table opt_config_table[] = { OPT_WITH_ARG("--userpass|-O", set_userpass, NULL, NULL, "Username:Password pair for bitcoin JSON-RPC server"), + OPT_WITHOUT_ARG("--worktime", + opt_set_bool, &opt_worktime, + "Display extra work time debug information"), OPT_WITH_ARG("--pools", opt_set_bool, NULL, NULL, opt_hidden), OPT_ENDTABLE @@ -1765,6 +1769,7 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub int rolltime; uint32_t *hash32; char hashshow[64+1] = ""; + char worktime[200] = ""; #ifdef __BIG_ENDIAN__ int swapcounter = 0; @@ -1789,8 +1794,10 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub applog(LOG_DEBUG, "DBG: sending %s submit RPC call: %s", pool->rpc_url, sd); + gettimeofday((struct timeval *)&(work->tv_submit), NULL); /* issue JSON-RPC request */ val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, s, false, false, &rolltime, pool, true); + gettimeofday((struct timeval *)&(work->tv_submit_reply), NULL); if (unlikely(!val)) { applog(LOG_INFO, "submit_upstream_work json_rpc_call failed"); if (!pool_tset(pool, &pool->submit_fail)) { @@ -1812,6 +1819,27 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub sprintf(hashshow, "%08lx.%08lx%s", (unsigned long)(hash32[6]), (unsigned long)(hash32[5]), work->block? " BLOCK!" : ""); } + + if (opt_worktime) { + double getwork_time = tdiff((struct timeval *)&(work->tv_getwork_reply), + (struct timeval *)&(work->tv_getwork)); + double getwork_to_work = tdiff((struct timeval *)&(work->tv_work_start), + (struct timeval *)&(work->tv_getwork_reply)); + double work_time = tdiff((struct timeval *)&(work->tv_work_finish), + (struct timeval *)&(work->tv_work_start)); + double work_to_submit = tdiff((struct timeval *)&(work->tv_submit), + (struct timeval *)&(work->tv_work_finish)); + double submit_time = tdiff((struct timeval *)&(work->tv_submit_reply), + (struct timeval *)&(work->tv_submit)); + struct tm *tm = localtime(&(work->tv_submit_reply.tv_sec)); + sprintf(worktime, " <-%08lx.%08lx %c G:%1.3f (%1.3f) W:%1.3f (%1.3f) S:%1.3f R:%02d:%02d:%02d", + (unsigned long)swab32(*(uint32_t *)&(work->data[28])), + (unsigned long)swab32(*(uint32_t *)&(work->data[24])), + work->clone ? 'C' : 'O', + getwork_time, getwork_to_work, work_time, + work_to_submit, submit_time, + tm->tm_hour, tm->tm_min, tm->tm_sec); + } } /* Theoretically threads could race when modifying accepted and @@ -1828,11 +1856,11 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub applog(LOG_DEBUG, "PROOF OF WORK RESULT: true (yay!!!)"); if (!QUIET) { if (total_pools > 1) - applog(LOG_NOTICE, "Accepted %s %s %d pool %d %s", - hashshow, cgpu->api->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : ""); + applog(LOG_NOTICE, "Accepted %s %s %d pool %d %s%s", + hashshow, cgpu->api->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "", worktime); else - applog(LOG_NOTICE, "Accepted %s %s %d %s", - hashshow, cgpu->api->name, cgpu->device_id, resubmit ? "(resubmit)" : ""); + applog(LOG_NOTICE, "Accepted %s %s %d %s%s", + hashshow, cgpu->api->name, cgpu->device_id, resubmit ? "(resubmit)" : "", worktime); } sharelog("accept", work); if (opt_shares && total_accepted >= opt_shares) { @@ -1881,8 +1909,8 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub } else strcpy(reason, ""); - applog(LOG_NOTICE, "Rejected %s %s %d %s%s %s", - hashshow, cgpu->api->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : ""); + applog(LOG_NOTICE, "Rejected %s %s %d %s%s %s%s", + hashshow, cgpu->api->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "", worktime); sharelog(disposition, work); } @@ -2000,7 +2028,7 @@ static bool get_upstream_work(struct work *work, CURL *curl) { struct pool *pool = work->pool; struct cgminer_pool_stats *pool_stats = &(pool->cgminer_pool_stats); - struct timeval tv_start, tv_end, tv_elapsed; + struct timeval tv_elapsed; json_t *val = NULL; bool rc = false; char *url; @@ -2009,7 +2037,7 @@ static bool get_upstream_work(struct work *work, CURL *curl) url = pool->rpc_url; - gettimeofday(&tv_start, NULL); + gettimeofday(&(work->tv_getwork), NULL); val = json_rpc_call(curl, url, pool->rpc_userpass, rpc_req, false, false, &work->rolltime, pool, false); @@ -2022,8 +2050,8 @@ static bool get_upstream_work(struct work *work, CURL *curl) } else applog(LOG_DEBUG, "Failed json_rpc_call in get_upstream_work"); - gettimeofday(&tv_end, NULL); - timersub(&tv_end, &tv_start, &tv_elapsed); + gettimeofday(&(work->tv_getwork_reply), NULL); + timersub(&(work->tv_getwork_reply), &(work->tv_getwork), &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; @@ -3425,12 +3453,13 @@ static void display_options(void) clear_logwin(); retry: wlogprint("[N]ormal [C]lear [S]ilent mode (disable all output)\n"); - wlogprint("[D]ebug:%s\n[P]er-device:%s\n[Q]uiet:%s\n[V]erbose:%s\n[R]PC debug:%s\n[L]og interval:%d\n", + wlogprint("[D]ebug:%s\n[P]er-device:%s\n[Q]uiet:%s\n[V]erbose:%s\n[R]PC debug:%s\n[W]orkTime details:%s\n[L]og interval:%d\n", opt_debug ? "on" : "off", want_per_device_stats? "on" : "off", opt_quiet ? "on" : "off", opt_log_output ? "on" : "off", opt_protocol ? "on" : "off", + opt_worktime ? "on" : "off", opt_log_interval); wlogprint("Select an option or any other key to return\n"); input = getch(); @@ -3483,6 +3512,10 @@ retry: goto retry; } else if (!strncasecmp(&input, "s", 1)) { opt_realquiet = true; + } else if (!strncasecmp(&input, "w", 1)) { + opt_worktime ^= true; + wlogprint("WorkTime details %s\n", opt_worktime ? "enabled" : "disabled"); + goto retry; } else clear_logwin(); @@ -4214,6 +4247,8 @@ static bool test_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) { + gettimeofday(&(work->tv_work_finish), NULL); + total_diff1++; thr->cgpu->diff1++; work->pool->diff1++; @@ -4338,6 +4373,8 @@ void *miner_thread(void *userdata) } pool_stats->getwork_calls++; + gettimeofday(&(work->tv_work_start), NULL); + thread_reportin(mythr); hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce); thread_reportin(mythr); diff --git a/miner.h b/miner.h index 924bc852..13f15412 100644 --- a/miner.h +++ b/miner.h @@ -456,6 +456,7 @@ extern void thr_info_cancel(struct thr_info *thr); extern void thr_info_freeze(struct thr_info *thr); extern void nmsleep(unsigned int msecs); extern double us_tdiff(struct timeval *end, struct timeval *start); +extern double tdiff(struct timeval *end, struct timeval *start); struct string_elist { char *string; @@ -582,6 +583,7 @@ extern bool opt_delaynet; extern bool opt_restart; extern char *opt_icarus_options; extern char *opt_icarus_timing; +extern bool opt_worktime; #ifdef USE_BITFORCE extern bool opt_bfl_noncerange; #endif @@ -829,6 +831,13 @@ struct work { UT_hash_handle hh; time_t share_found_time; + + struct timeval tv_getwork; + struct timeval tv_getwork_reply; + struct timeval tv_work_start; + struct timeval tv_work_finish; + struct timeval tv_submit; + struct timeval tv_submit_reply; }; #ifdef USE_MODMINER diff --git a/util.c b/util.c index 59743fdd..b3a5a1ba 100644 --- a/util.c +++ b/util.c @@ -787,3 +787,9 @@ double us_tdiff(struct timeval *end, struct timeval *start) { return end->tv_sec * 1000000 + end->tv_usec - start->tv_sec * 1000000 - start->tv_usec; } + +/* Returns the seconds difference between end and start times as a double */ +double tdiff(struct timeval *end, struct timeval *start) +{ + return end->tv_sec - start->tv_sec + (end->tv_usec - start->tv_usec) / 1000000.0; +} From 796f3906c183e29a76b9028d3f1358ccc583344b Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 16 Sep 2012 07:57:43 +1000 Subject: [PATCH 29/50] WorkTime - multiple nonce per work and identify the work source --- README | 23 +++++++++------- cgminer.c | 77 ++++++++++++++++++++++++++++++++++++++-------------- driver-cpu.c | 4 +-- miner.h | 19 +++++++------ 4 files changed, 82 insertions(+), 41 deletions(-) diff --git a/README b/README index 7f6f95d7..fd29dc8c 100644 --- a/README +++ b/README @@ -476,19 +476,22 @@ and pipe the output directly to that command. The WorkTime details 'debug' option adds details on the end of each line displayed for Accepted or Rejected work done. An example would be: - <-00000223.95214f4c O G:0.524 (97.672) W:4.910 (0.000) S:0.577 R:13:49:55 + <-00000059.ed4834a3 M:X G:17:02:38:0.405 C:1.855 (2.995) W:3.440 (0.000) S:0.461 R:17:02:47 The first 2 hex codes are the previous block hash, the rest are reported in seconds unless stated otherwise: -The previous hash is followed by 'C' or 'O' if the work was cloned or original, -G:n.nnn is how long the original getwork to the pool took, (m.mmm) is how long -from the original getwork complete until work started, W:n.nnn is how long the -work took to process until it was ready to submit, (m.mmm) is how long from -ready to submit to actually doing the submit, this is usually 0.000 unless -there was a problem with the first attempt at submitting the work, S:n.nnn -is how long it took to submit the work and await the reply, R:hh:mm:ss is the -actual time the work submit reply was received - so you can count back from -that to work out each absolute time +The previous hash is followed by the getwork mode used M:X where X is one of +P:Pool, T:Test Pool, L:LP or B:Benchmark, +then G:hh:mm:ss:n.nnn, which is when the getwork or LP was sent to the pool and +the n.nnn is how long it took to reply, +followed by 'O' on it's own if it is an original getwork, or 'C:n.nnn' if it was +a clone with n.nnn stating how long after the work was recieved that it was cloned, +(m.mmm) is how long from when the original work was received until work started, +W:n.nnn is how long the work took to process until it was ready to submit, +(m.mmm) is how long from ready to submit to actually doing the submit, this is +usually 0.000 unless there was a problem with submitting the work, +S:n.nnn is how long it took to submit the completed work and await the reply, +R:hh:mm:ss is the actual time the work submit reply was received If you start cgminer with the --sharelog option, you can get detailed information for each share found. The argument to the option may be "-" for diff --git a/cgminer.c b/cgminer.c index 791875ff..2b1a2101 100644 --- a/cgminer.c +++ b/cgminer.c @@ -359,7 +359,7 @@ static void sharelog(const char*disposition, const struct work*work) thr_id = work->thr_id; cgpu = thr_info[thr_id].cgpu; pool = work->pool; - t = (unsigned long int)work->share_found_time; + t = (unsigned long int)(work->tv_work_found.tv_sec); target = bin2hex(work->target, sizeof(work->target)); if (unlikely(!target)) { applog(LOG_ERR, "sharelog target OOM"); @@ -1768,6 +1768,7 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub struct pool *pool = work->pool; int rolltime; uint32_t *hash32; + struct timeval tv_submit, tv_submit_reply; char hashshow[64+1] = ""; char worktime[200] = ""; @@ -1794,10 +1795,10 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub applog(LOG_DEBUG, "DBG: sending %s submit RPC call: %s", pool->rpc_url, sd); - gettimeofday((struct timeval *)&(work->tv_submit), NULL); + gettimeofday(&tv_submit, NULL); /* issue JSON-RPC request */ val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, s, false, false, &rolltime, pool, true); - gettimeofday((struct timeval *)&(work->tv_submit_reply), NULL); + gettimeofday(&tv_submit_reply, NULL); if (unlikely(!val)) { applog(LOG_INFO, "submit_upstream_work json_rpc_call failed"); if (!pool_tset(pool, &pool->submit_fail)) { @@ -1821,24 +1822,39 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub } if (opt_worktime) { + char workclone[20]; + struct tm *tm, tm_getwork, tm_submit_reply; double getwork_time = tdiff((struct timeval *)&(work->tv_getwork_reply), (struct timeval *)&(work->tv_getwork)); double getwork_to_work = tdiff((struct timeval *)&(work->tv_work_start), (struct timeval *)&(work->tv_getwork_reply)); - double work_time = tdiff((struct timeval *)&(work->tv_work_finish), + double work_time = tdiff((struct timeval *)&(work->tv_work_found), (struct timeval *)&(work->tv_work_start)); - double work_to_submit = tdiff((struct timeval *)&(work->tv_submit), - (struct timeval *)&(work->tv_work_finish)); - double submit_time = tdiff((struct timeval *)&(work->tv_submit_reply), - (struct timeval *)&(work->tv_submit)); - struct tm *tm = localtime(&(work->tv_submit_reply.tv_sec)); - sprintf(worktime, " <-%08lx.%08lx %c G:%1.3f (%1.3f) W:%1.3f (%1.3f) S:%1.3f R:%02d:%02d:%02d", + double work_to_submit = tdiff(&tv_submit, + (struct timeval *)&(work->tv_work_found)); + double submit_time = tdiff(&tv_submit_reply, &tv_submit); + + tm = localtime(&(work->tv_getwork.tv_sec)); + memcpy(&tm_getwork, tm, sizeof(struct tm)); + tm = localtime(&(tv_submit_reply.tv_sec)); + memcpy(&tm_submit_reply, tm, sizeof(struct tm)); + + if (work->clone) { + sprintf(workclone, "C:%1.3f", + tdiff((struct timeval *)&(work->tv_cloned), + (struct timeval *)&(work->tv_getwork_reply))); + } + else + strcpy(workclone, "O"); + + sprintf(worktime, " <-%08lx.%08lx M:%c G:%02d:%02d:%02d:%1.3f %s (%1.3f) W:%1.3f (%1.3f) S:%1.3f R:%02d:%02d:%02d", (unsigned long)swab32(*(uint32_t *)&(work->data[28])), (unsigned long)swab32(*(uint32_t *)&(work->data[24])), - work->clone ? 'C' : 'O', - getwork_time, getwork_to_work, work_time, - work_to_submit, submit_time, - tm->tm_hour, tm->tm_min, tm->tm_sec); + work->getwork_mode, tm_getwork.tm_hour, tm_getwork.tm_min, + tm_getwork.tm_sec, getwork_time, workclone, + getwork_to_work, work_time, work_to_submit, submit_time, + tm_submit_reply.tm_hour, tm_submit_reply.tm_min, + tm_submit_reply.tm_sec); } } @@ -2022,6 +2038,9 @@ static void get_benchmark_work(struct work *work) memcpy(work, &bench_block, min_size); work->mandatory = true; work->pool = pools[0]; + gettimeofday(&(work->tv_getwork), NULL); + memcpy(&(work->tv_getwork_reply), &(work->tv_getwork), sizeof(struct timeval)); + work->getwork_mode = GETWORK_MODE_BENCHMARK; } static bool get_upstream_work(struct work *work, CURL *curl) @@ -2068,6 +2087,7 @@ static bool get_upstream_work(struct work *work, CURL *curl) work->pool = pool; work->longpoll = false; + work->getwork_mode = GETWORK_MODE_POOL; total_getworks++; pool->getwork_requested++; @@ -2376,6 +2396,7 @@ static struct work *make_clone(struct work *work) memcpy(work_clone, work, sizeof(struct work)); work_clone->clone = true; + gettimeofday((struct timeval *)&(work_clone->tv_cloned), NULL); work_clone->longpoll = false; work_clone->mandatory = false; /* Make cloned work appear slightly older to bias towards keeping the @@ -3845,6 +3866,7 @@ static void *longpoll_thread(void *userdata); static bool pool_active(struct pool *pool, bool pinging) { + struct timeval tv_getwork, tv_getwork_reply; bool ret = false; json_t *val; CURL *curl; @@ -3857,8 +3879,10 @@ static bool pool_active(struct pool *pool, bool pinging) } applog(LOG_INFO, "Testing pool %s", pool->rpc_url); + gettimeofday(&tv_getwork, NULL); val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, rpc_req, true, false, &rolltime, pool, false); + gettimeofday(&tv_getwork_reply, NULL); if (val) { struct work *work = make_work(); @@ -3870,6 +3894,9 @@ static bool pool_active(struct pool *pool, bool pinging) pool->pool_no, pool->rpc_url); work->pool = pool; work->rolltime = rolltime; + memcpy(&(work->tv_getwork), &tv_getwork, sizeof(struct timeval)); + memcpy(&(work->tv_getwork_reply), &tv_getwork_reply, sizeof(struct timeval)); + work->getwork_mode = GETWORK_MODE_TESTPOOL; applog(LOG_DEBUG, "Pushing pooltest work to base pool"); tq_push(thr_info[stage_thr_id].q, work); @@ -4161,7 +4188,7 @@ out: work->mined = true; } -bool submit_work_sync(struct thr_info *thr, const struct work *work_in) +bool submit_work_sync(struct thr_info *thr, const struct work *work_in, struct timeval *tv_work_found) { struct workio_cmd *wc; @@ -4176,7 +4203,8 @@ bool submit_work_sync(struct thr_info *thr, const struct work *work_in) wc->cmd = WC_SUBMIT_WORK; wc->thr = thr; memcpy(wc->work, work_in, sizeof(*work_in)); - wc->work->share_found_time = time(NULL); + if (tv_work_found) + memcpy(&(wc->work->tv_work_found), tv_work_found, sizeof(struct timeval)); applog(LOG_DEBUG, "Pushing submit work to work thread"); @@ -4247,7 +4275,8 @@ static bool test_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) { - gettimeofday(&(work->tv_work_finish), NULL); + struct timeval tv_work_found; + gettimeofday(&tv_work_found, NULL); total_diff1++; thr->cgpu->diff1++; @@ -4258,7 +4287,7 @@ bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) if (!test_nonce(thr, work, nonce)) return true; - return submit_work_sync(thr, work); + return submit_work_sync(thr, work, &tv_work_found); } static inline bool abandon_work(struct work *work, struct timeval *wdiff, uint64_t hashes) @@ -4471,7 +4500,7 @@ enum { }; /* Stage another work item from the work returned in a longpoll */ -static void convert_to_work(json_t *val, int rolltime, struct pool *pool) +static void convert_to_work(json_t *val, int rolltime, struct pool *pool, struct timeval *tv_lp, struct timeval *tv_lp_reply) { struct work *work; bool rc; @@ -4487,6 +4516,9 @@ static void convert_to_work(json_t *val, int rolltime, struct pool *pool) work->pool = pool; work->rolltime = rolltime; work->longpoll = true; + memcpy(&(work->tv_getwork), tv_lp, sizeof(struct timeval)); + memcpy(&(work->tv_getwork_reply), tv_lp_reply, sizeof(struct timeval)); + work->getwork_mode = GETWORK_MODE_LP; if (pool->enabled == POOL_REJECTING) work->mandatory = true; @@ -4555,7 +4587,7 @@ static void *longpoll_thread(void *userdata) /* This *pool is the source of the actual longpoll, not the pool we've * tied it to */ struct pool *pool = NULL; - struct timeval start, end; + struct timeval start, reply, end; CURL *curl = NULL; int failures = 0; int rolltime; @@ -4600,13 +4632,16 @@ retry_pool: curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1); val = json_rpc_call(curl, pool->lp_url, pool->rpc_userpass, rpc_req, false, true, &rolltime, pool, false); + + gettimeofday(&reply, NULL); + if (likely(val)) { soval = json_object_get(json_object_get(val, "result"), "submitold"); if (soval) pool->submit_old = json_is_true(soval); else pool->submit_old = false; - convert_to_work(val, rolltime, pool); + convert_to_work(val, rolltime, pool, &start, &reply); failures = 0; json_decref(val); } else { diff --git a/driver-cpu.c b/driver-cpu.c index 8ffc7802..e3a74de6 100644 --- a/driver-cpu.c +++ b/driver-cpu.c @@ -75,7 +75,7 @@ static inline void affine_to_cpu(int id, int cpu) /* TODO: resolve externals */ -extern bool submit_work_sync(struct thr_info *thr, const struct work *work_in); +extern bool submit_work_sync(struct thr_info *thr, const struct work *work_in, struct timeval *tv); extern char *set_int_range(const char *arg, int *i, int min, int max); extern int dev_from_id(int thr_id); @@ -827,7 +827,7 @@ CPUSearch: /* if nonce found, submit work */ if (unlikely(rc)) { applog(LOG_DEBUG, "CPU %d found something?", dev_from_id(thr_id)); - if (unlikely(!submit_work_sync(thr, work))) { + if (unlikely(!submit_work_sync(thr, work, NULL))) { applog(LOG_ERR, "Failed to submit_work_sync in miner_thread %d", thr_id); } work->blk.nonce = last_nonce + 1; diff --git a/miner.h b/miner.h index 13f15412..74cc0019 100644 --- a/miner.h +++ b/miner.h @@ -798,6 +798,11 @@ struct pool { struct cgminer_pool_stats cgminer_pool_stats; }; +#define GETWORK_MODE_TESTPOOL 'T' +#define GETWORK_MODE_POOL 'P' +#define GETWORK_MODE_LP 'L' +#define GETWORK_MODE_BENCHMARK 'B' + struct work { unsigned char data[128]; unsigned char hash1[64]; @@ -830,14 +835,12 @@ struct work { int id; UT_hash_handle hh; - time_t share_found_time; - - struct timeval tv_getwork; - struct timeval tv_getwork_reply; - struct timeval tv_work_start; - struct timeval tv_work_finish; - struct timeval tv_submit; - struct timeval tv_submit_reply; + struct timeval tv_getwork; + struct timeval tv_getwork_reply; + struct timeval tv_cloned; + struct timeval tv_work_start; + struct timeval tv_work_found; + char getwork_mode; }; #ifdef USE_MODMINER From ad7aa2b382896abaf70ed5c0b6f92b314c1753d3 Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 16 Sep 2012 11:42:51 +1000 Subject: [PATCH 30/50] FPGA - allow long or short device names in detect code + style police --- README | 1 + driver-bitforce.c | 4 ++-- driver-icarus.c | 4 ++-- driver-modminer.c | 4 ++-- fpgautils.c | 53 +++++++++++++++++++++-------------------------- fpgautils.h | 26 +++++++++++------------ 6 files changed, 44 insertions(+), 48 deletions(-) diff --git a/README b/README index fd29dc8c..36de306f 100644 --- a/README +++ b/README @@ -239,6 +239,7 @@ The official supplied binaries are compiled with support for all FPGAs. To force the code to only attempt detection with a specific driver, prepend the argument with the driver name followed by a colon. For example, "icarus:/dev/ttyUSB0" or "bitforce:\\.\COM5" +or using the short name: "ica:/dev/ttyUSB0" or "bfl:\\.\COM5" For other FPGA details see the FPGA-README diff --git a/driver-bitforce.c b/driver-bitforce.c index c1107fea..ded9e923 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -45,8 +45,8 @@ enum { #endif /* WIN32 */ #include "compat.h" -#include "fpgautils.h" #include "miner.h" +#include "fpgautils.h" #define BITFORCE_SLEEP_MS 500 #define BITFORCE_TIMEOUT_S 7 @@ -230,7 +230,7 @@ static int bitforce_detect_auto(void) static void bitforce_detect(void) { - serial_detect_auto(bitforce_api.dname, bitforce_detect_one, bitforce_detect_auto); + serial_detect_auto(&bitforce_api, bitforce_detect_one, bitforce_detect_auto); } static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce) diff --git a/driver-icarus.c b/driver-icarus.c index 33b875d7..4214c31b 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -49,8 +49,8 @@ #endif #include "elist.h" -#include "fpgautils.h" #include "miner.h" +#include "fpgautils.h" // The serial I/O speed - Linux uses a define 'B115200' in bits/termios.h #define ICARUS_IO_SPEED 115200 @@ -598,7 +598,7 @@ static bool icarus_detect_one(const char *devpath) static void icarus_detect() { - serial_detect(icarus_api.dname, icarus_detect_one); + serial_detect(&icarus_api, icarus_detect_one); } static bool icarus_prepare(struct thr_info *thr) diff --git a/driver-modminer.c b/driver-modminer.c index 750f9ec5..d7359834 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -13,9 +13,9 @@ #include #include -#include "fpgautils.h" #include "logging.h" #include "miner.h" +#include "fpgautils.h" #define BITSTREAM_FILENAME "fpgaminer_top_fixed7_197MHz.ncd" #define BISTREAM_USER_ID "\2\4$B" @@ -103,7 +103,7 @@ modminer_detect_auto() static void modminer_detect() { - serial_detect_auto(modminer_api.dname, modminer_detect_one, modminer_detect_auto); + serial_detect_auto(&modminer_api, modminer_detect_one, modminer_detect_auto); } #define bailout(...) return _bailout(-1, modminer, __VA_ARGS__); diff --git a/fpgautils.c b/fpgautils.c index 287f277e..de9d93e7 100644 --- a/fpgautils.c +++ b/fpgautils.c @@ -33,13 +33,12 @@ #endif #include "elist.h" -#include "fpgautils.h" #include "logging.h" #include "miner.h" +#include "fpgautils.h" #ifdef HAVE_LIBUDEV -int -serial_autodetect_udev(detectone_func_t detectone, const char*prodname) +int serial_autodetect_udev(detectone_func_t detectone, const char*prodname) { struct udev *udev = udev_new(); struct udev_enumerate *enumerate = udev_enumerate_new(udev); @@ -69,15 +68,13 @@ serial_autodetect_udev(detectone_func_t detectone, const char*prodname) return found; } #else -int -serial_autodetect_udev(__maybe_unused detectone_func_t detectone, __maybe_unused const char*prodname) +int serial_autodetect_udev(__maybe_unused detectone_func_t detectone, __maybe_unused const char*prodname) { return 0; } #endif -int -serial_autodetect_devserial(detectone_func_t detectone, const char*prodname) +int serial_autodetect_devserial(detectone_func_t detectone, const char*prodname) { #ifndef WIN32 DIR *D; @@ -107,30 +104,32 @@ serial_autodetect_devserial(detectone_func_t detectone, const char*prodname) #endif } -int -_serial_detect(const char*dname, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto) +int _serial_detect(struct device_api *api, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto) { struct string_elist *iter, *tmp; - const char*s, *p; + const char *dev, *colon; bool inhibitauto = false; char found = 0; - size_t dnamel = strlen(dname); + size_t namel = strlen(api->name); + size_t dnamel = strlen(api->dname); list_for_each_entry_safe(iter, tmp, &scan_devices, list) { - s = iter->string; - if ((p = strchr(s, ':')) && p[1] != '\0') { - size_t plen = p - s; - if (plen != dnamel || strncasecmp(s, dname, plen)) + dev = iter->string; + if ((colon = strchr(dev, ':')) && colon[1] != '\0') { + size_t idlen = colon - dev; + + // allow either name:device or dname:device + if ((idlen != namel || strncasecmp(dev, api->name, idlen)) + && (idlen != dnamel || strncasecmp(dev, api->dname, idlen))) continue; - s = p + 1; + + dev = colon + 1; } - if (!strcmp(s, "auto")) + if (!strcmp(dev, "auto")) forceauto = true; - else - if (!strcmp(s, "noauto")) + else if (!strcmp(dev, "noauto")) inhibitauto = true; - else - if (detectone(s)) { + else if (detectone(dev)) { string_elist_del(iter); inhibitauto = true; ++found; @@ -311,8 +310,7 @@ void termios_debug(const char *devpath, struct termios *my_termios, const char * #endif #endif -int -serial_open(const char*devpath, unsigned long baud, signed short timeout, bool purge) +int serial_open(const char *devpath, unsigned long baud, signed short timeout, bool purge) { #ifdef WIN32 HANDLE hSerial = CreateFile(devpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); @@ -429,8 +427,7 @@ serial_open(const char*devpath, unsigned long baud, signed short timeout, bool p #endif } -ssize_t -_serial_read(int fd, char *buf, size_t bufsiz, char *eol) +ssize_t _serial_read(int fd, char *buf, size_t bufsiz, char *eol) { ssize_t len, tlen = 0; while (bufsiz) { @@ -446,8 +443,7 @@ _serial_read(int fd, char *buf, size_t bufsiz, char *eol) return tlen; } -static FILE* -_open_bitstream(const char*path, const char*subdir, const char*filename) +static FILE *_open_bitstream(const char *path, const char *subdir, const char *filename) { char fullpath[PATH_MAX]; strcpy(fullpath, path); @@ -471,8 +467,7 @@ _open_bitstream(const char*path, const char*subdir, const char*filename) _open_bitstream(path, NULL); \ } while(0) -FILE* -open_bitstream(const char*dname, const char*filename) +FILE *open_bitstream(const char *dname, const char *filename) { FILE *f; diff --git a/fpgautils.h b/fpgautils.h index 5b743bc5..5c8b6bfe 100644 --- a/fpgautils.h +++ b/fpgautils.h @@ -16,24 +16,24 @@ typedef bool(*detectone_func_t)(const char*); typedef int(*autoscan_func_t)(); -extern int _serial_detect(const char*dname, detectone_func_t, autoscan_func_t, bool force_autoscan); -#define serial_detect_fauto(dname, detectone, autoscan) \ - _serial_detect(dname, detectone, autoscan, true) -#define serial_detect_auto(dname, detectone, autoscan) \ - _serial_detect(dname, detectone, autoscan, false) -#define serial_detect(dname, detectone) \ - _serial_detect(dname, detectone, NULL, false) -extern int serial_autodetect_devserial(detectone_func_t, const char*prodname); -extern int serial_autodetect_udev (detectone_func_t, const char*prodname); +extern int _serial_detect(struct device_api *api, detectone_func_t, autoscan_func_t, bool force_autoscan); +#define serial_detect_fauto(api, detectone, autoscan) \ + _serial_detect(api, detectone, autoscan, true) +#define serial_detect_auto(api, detectone, autoscan) \ + _serial_detect(api, detectone, autoscan, false) +#define serial_detect(api, detectone) \ + _serial_detect(api, detectone, NULL, false) +extern int serial_autodetect_devserial(detectone_func_t, const char *prodname); +extern int serial_autodetect_udev(detectone_func_t, const char *prodname); -extern int serial_open(const char*devpath, unsigned long baud, signed short timeout, bool purge); -extern ssize_t _serial_read(int fd, char *buf, size_t buflen, char*eol); +extern int serial_open(const char *devpath, unsigned long baud, signed short timeout, bool purge); +extern ssize_t _serial_read(int fd, char *buf, size_t buflen, char *eol); #define serial_read(fd, buf, count) \ _serial_read(fd, (char*)(buf), count, NULL) #define serial_read_line(fd, buf, bufsiz, eol) \ - _serial_read(fd, buf, count, &eol) + _serial_read(fd, buf, bufsiz, &eol) #define serial_close(fd) close(fd) -extern FILE*open_bitstream(const char*dname, const char*filename); +extern FILE *open_bitstream(const char *dname, const char *filename); #endif From 8f4ccebf0d6334c14a26467759f67eeac120b553 Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 16 Sep 2012 11:47:54 +1000 Subject: [PATCH 31/50] remove MMQ unused variable warning --- driver-modminer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/driver-modminer.c b/driver-modminer.c index d7359834..d15f2d88 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -404,7 +404,6 @@ modminer_process_results(struct thr_info*thr) char cmd[2], temperature; uint32_t nonce; long iter; - bool bad; int curr_hw_errors; cmd[0] = '\x0a'; cmd[1] = fpgaid; From 923b9e0d86d54d5d36b8a5c53b1b45d6d89d13c1 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 18 Sep 2012 11:19:57 +1000 Subject: [PATCH 32/50] Calculate work difficulty for each getwork and display with WorkTime debug --- README | 3 ++- cgminer.c | 32 ++++++++++++++++++++++++++++++-- miner.h | 4 +++- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/README b/README index 36de306f..1591d66c 100644 --- a/README +++ b/README @@ -477,12 +477,13 @@ and pipe the output directly to that command. The WorkTime details 'debug' option adds details on the end of each line displayed for Accepted or Rejected work done. An example would be: - <-00000059.ed4834a3 M:X G:17:02:38:0.405 C:1.855 (2.995) W:3.440 (0.000) S:0.461 R:17:02:47 + <-00000059.ed4834a3 M:X D:1.0 G:17:02:38:0.405 C:1.855 (2.995) W:3.440 (0.000) S:0.461 R:17:02:47 The first 2 hex codes are the previous block hash, the rest are reported in seconds unless stated otherwise: The previous hash is followed by the getwork mode used M:X where X is one of P:Pool, T:Test Pool, L:LP or B:Benchmark, +then D:d.ddd is the difficulty required to get a share from the work, then G:hh:mm:ss:n.nnn, which is when the getwork or LP was sent to the pool and the n.nnn is how long it took to reply, followed by 'O' on it's own if it is an original getwork, or 'C:n.nnn' if it was diff --git a/cgminer.c b/cgminer.c index 2b1a2101..259a04dd 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1833,6 +1833,7 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub double work_to_submit = tdiff(&tv_submit, (struct timeval *)&(work->tv_work_found)); double submit_time = tdiff(&tv_submit_reply, &tv_submit); + int diffplaces = 3; tm = localtime(&(work->tv_getwork.tv_sec)); memcpy(&tm_getwork, tm, sizeof(struct tm)); @@ -1847,10 +1848,14 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub else strcpy(workclone, "O"); - sprintf(worktime, " <-%08lx.%08lx M:%c G:%02d:%02d:%02d:%1.3f %s (%1.3f) W:%1.3f (%1.3f) S:%1.3f R:%02d:%02d:%02d", + if (work->work_difficulty < 1) + diffplaces = 6; + + sprintf(worktime, " <-%08lx.%08lx M:%c D:%1.*f G:%02d:%02d:%02d:%1.3f %s (%1.3f) W:%1.3f (%1.3f) S:%1.3f R:%02d:%02d:%02d", (unsigned long)swab32(*(uint32_t *)&(work->data[28])), (unsigned long)swab32(*(uint32_t *)&(work->data[24])), - work->getwork_mode, tm_getwork.tm_hour, tm_getwork.tm_min, + work->getwork_mode, diffplaces, work->work_difficulty, + tm_getwork.tm_hour, tm_getwork.tm_min, tm_getwork.tm_sec, getwork_time, workclone, getwork_to_work, work_time, work_to_submit, submit_time, tm_submit_reply.tm_hour, tm_submit_reply.tm_min, @@ -2026,6 +2031,25 @@ static inline struct pool *select_pool(bool lagging) return pool; } +static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249216.0; + +/* + * Calculate the work share difficulty + */ +static void calc_diff(struct work *work) +{ + double targ; + int i; + + targ = 0; + for (i = 31; i >= 0; i--) { + targ *= 256; + targ += work->target[i]; + } + + work->work_difficulty = DIFFEXACTONE / (targ ? : DIFFEXACTONE); +} + static void get_benchmark_work(struct work *work) { // Use a random work block pulled from a pool @@ -2041,6 +2065,7 @@ static void get_benchmark_work(struct work *work) gettimeofday(&(work->tv_getwork), NULL); memcpy(&(work->tv_getwork_reply), &(work->tv_getwork), sizeof(struct timeval)); work->getwork_mode = GETWORK_MODE_BENCHMARK; + calc_diff(work); } static bool get_upstream_work(struct work *work, CURL *curl) @@ -2088,6 +2113,7 @@ static bool get_upstream_work(struct work *work, CURL *curl) work->pool = pool; work->longpoll = false; work->getwork_mode = GETWORK_MODE_POOL; + calc_diff(work); total_getworks++; pool->getwork_requested++; @@ -3897,6 +3923,7 @@ static bool pool_active(struct pool *pool, bool pinging) memcpy(&(work->tv_getwork), &tv_getwork, sizeof(struct timeval)); memcpy(&(work->tv_getwork_reply), &tv_getwork_reply, sizeof(struct timeval)); work->getwork_mode = GETWORK_MODE_TESTPOOL; + calc_diff(work); applog(LOG_DEBUG, "Pushing pooltest work to base pool"); tq_push(thr_info[stage_thr_id].q, work); @@ -4519,6 +4546,7 @@ static void convert_to_work(json_t *val, int rolltime, struct pool *pool, struct memcpy(&(work->tv_getwork), tv_lp, sizeof(struct timeval)); memcpy(&(work->tv_getwork_reply), tv_lp_reply, sizeof(struct timeval)); work->getwork_mode = GETWORK_MODE_LP; + calc_diff(work); if (pool->enabled == POOL_REJECTING) work->mandatory = true; diff --git a/miner.h b/miner.h index 74cc0019..f3e9303b 100644 --- a/miner.h +++ b/miner.h @@ -833,7 +833,9 @@ struct work { unsigned int work_block; int id; - UT_hash_handle hh; + UT_hash_handle hh; + + double work_difficulty; struct timeval tv_getwork; struct timeval tv_getwork_reply; From a2cc588c5143573a97a1757e889e74cb1387f118 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 18 Sep 2012 14:12:32 +1000 Subject: [PATCH 33/50] api.c remove compile warnings --- api.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api.c b/api.c index ddd938ae..01660af9 100644 --- a/api.c +++ b/api.c @@ -168,9 +168,11 @@ static const char GPUSEP = ','; static const char *APIVERSION = "1.19"; static const char *DEAD = "Dead"; +#if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA) static const char *SICK = "Sick"; static const char *NOSTART = "NoStart"; static const char *INIT = "Initialising"; +#endif static const char *DISABLED = "Disabled"; static const char *ALIVE = "Alive"; static const char *REJECTING = "Rejecting"; @@ -571,7 +573,9 @@ struct CODES { static int my_thr_id = 0; static bool bye; +#if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA) static bool ping = true; +#endif // Used to control quit restart access to shutdown variables static pthread_mutex_t quit_restart_lock; @@ -1292,6 +1296,7 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, strcat(io_buffer, buf); } +#if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA) static const char *status2str(enum alive status) { switch (status) { @@ -1309,6 +1314,7 @@ static const char *status2str(enum alive status) return UNKNOWN; } } +#endif #ifdef HAVE_OPENCL static void gpustatus(int gpu, bool isjson) From 7ede5a59bdb8a5973c1fc0fb1ee702a832e0ae5e Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 18 Sep 2012 14:30:46 +1000 Subject: [PATCH 34/50] WorkTime - display prevblock for scrypt --- cgminer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index 259a04dd..4ad666d9 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1852,8 +1852,8 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub diffplaces = 6; sprintf(worktime, " <-%08lx.%08lx M:%c D:%1.*f G:%02d:%02d:%02d:%1.3f %s (%1.3f) W:%1.3f (%1.3f) S:%1.3f R:%02d:%02d:%02d", - (unsigned long)swab32(*(uint32_t *)&(work->data[28])), - (unsigned long)swab32(*(uint32_t *)&(work->data[24])), + (unsigned long)swab32(*(uint32_t *)&(work->data[opt_scrypt ? 32 : 28])), + (unsigned long)swab32(*(uint32_t *)&(work->data[opt_scrypt ? 28 : 24])), work->getwork_mode, diffplaces, work->work_difficulty, tm_getwork.tm_hour, tm_getwork.tm_min, tm_getwork.tm_sec, getwork_time, workclone, From 89b6989fb31a72120985a2460e439a36bf545142 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 19 Sep 2012 00:54:55 +1000 Subject: [PATCH 35/50] Store and report Accepted,Rejected,Stale difficulty in the summary and API --- API-README | 12 +++++++----- api.c | 21 +++++++++++++++++++++ cgminer.c | 17 +++++++++++++++++ miner.h | 11 ++++++++++- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/API-README b/API-README index 1fa904da..ad89b1f8 100644 --- a/API-README +++ b/API-README @@ -387,16 +387,18 @@ API V1.19 Added API commands: 'debug' - 'pgaidentify|N' + 'pgaidentify|N' (only works for BFL Singles so far) 'setconfig|name,N' Modified API commands: Change pool field name 'Diff1 Shares' to 'Diff1 Work' - 'devs' - add 'Diff1 Work' to all devices - 'gpu|N' - add 'Diff1 Work' - 'pga|N' - add 'Diff1 Work' + 'devs' - add 'Diff1 Work', 'Difficulty Accepted', 'Difficulty Rejected' + to all devices + 'gpu|N' - add 'Diff1 Work', 'Difficulty Accepted', 'Difficulty Rejected' + 'pga|N' - add 'Diff1 Work', 'Difficulty Accepted', 'Difficulty Rejected' 'notify' - add '*Dev Throttle' (for BFL Singles) - 'pools' - add 'Proxy Type', 'Proxy' + 'pools' - add 'Proxy Type', 'Proxy', 'Difficulty Accepted', + 'Difficulty Rejected', 'Difficulty Stale' 'config' - add 'Queue', 'Expiry' ---------- diff --git a/api.c b/api.c index 01660af9..9b4e017e 100644 --- a/api.c +++ b/api.c @@ -776,6 +776,7 @@ static struct api_data *api_add_data_full(struct api_data *root, char *name, enu case API_UTILITY: case API_FREQ: case API_HS: + case API_DIFF: api_data->data = (void *)malloc(sizeof(double)); *((double *)(api_data->data)) = *((double *)data); break; @@ -902,6 +903,11 @@ struct api_data *api_add_hs(struct api_data *root, char *name, double *data, boo return api_add_data_full(root, name, API_HS, (void *)data, copy_data); } +struct api_data *api_add_diff(struct api_data *root, char *name, double *data, bool copy_data) +{ + return api_add_data_full(root, name, API_DIFF, (void *)data, copy_data); +} + static struct api_data *print_data(struct api_data *root, char *buf, bool isjson) { struct api_data *tmp; @@ -973,6 +979,9 @@ static struct api_data *print_data(struct api_data *root, char *buf, bool isjson case API_HS: sprintf(buf, "%.15f", *((double *)(root->data))); break; + case API_DIFF: + sprintf(buf, "%.8f", *((double *)(root->data))); + break; case API_BOOL: sprintf(buf, "%s", *((bool *)(root->data)) ? TRUESTR : FALSESTR); break; @@ -1376,6 +1385,8 @@ static void gpustatus(int gpu, bool isjson) root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false); root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false); root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false); + root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false); + root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false); root = print_data(root, buf, isjson); strcat(io_buffer, buf); @@ -1460,6 +1471,8 @@ static void pgastatus(int pga, bool isjson) root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false); root = api_add_freq(root, "Frequency", &frequency, false); root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false); + root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false); + root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false); root = print_data(root, buf, isjson); strcat(io_buffer, buf); @@ -1493,6 +1506,8 @@ static void cpustatus(int cpu, bool isjson) root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false); root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false); root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false); + root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false); + root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false); root = print_data(root, buf, isjson); strcat(io_buffer, buf); @@ -1872,6 +1887,9 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, root = api_add_const(root, "Proxy Type", BLANK, false); root = api_add_const(root, "Proxy", BLANK, false); } + root = api_add_diff(root, "Difficulty Accepted", &(pool->diff_accepted), false); + root = api_add_diff(root, "Difficulty Rejected", &(pool->diff_rejected), false); + root = api_add_diff(root, "Difficulty Stale", &(pool->diff_stale), false); if (isjson && (i > 0)) strcat(io_buffer, COMMA); @@ -1924,6 +1942,9 @@ static void summary(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, boo root = api_add_uint(root, "Network Blocks", &(new_blocks), false); root = api_add_mhtotal(root, "Total MH", &(total_mhashes_done), false); root = api_add_utility(root, "Work Utility", &(work_utility), false); + root = api_add_diff(root, "Difficulty Accepted", &(total_diff_accepted), false); + root = api_add_diff(root, "Difficulty Rejected", &(total_diff_rejected), false); + root = api_add_diff(root, "Difficulty Stale", &(total_diff_stale), false); root = print_data(root, buf, isjson); if (isjson) diff --git a/cgminer.c b/cgminer.c index 4ad666d9..cb61958e 100644 --- a/cgminer.c +++ b/cgminer.c @@ -187,6 +187,7 @@ pthread_mutex_t control_lock; int hw_errors; int total_accepted, total_rejected, total_diff1; int total_getworks, total_stale, total_discarded; +double total_diff_accepted, total_diff_rejected, total_diff_stale; static int total_queued, staged_rollable; unsigned int new_blocks; static unsigned int work_block; @@ -1870,6 +1871,9 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub cgpu->accepted++; total_accepted++; pool->accepted++; + cgpu->diff_accepted += work->work_difficulty; + total_diff_accepted += work->work_difficulty; + pool->diff_accepted += work->work_difficulty; pool->seq_rejects = 0; cgpu->last_share_pool = pool->pool_no; cgpu->last_share_pool_time = time(NULL); @@ -1903,6 +1907,9 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub cgpu->rejected++; total_rejected++; pool->rejected++; + cgpu->diff_rejected += work->work_difficulty; + total_diff_rejected += work->work_difficulty; + pool->diff_rejected += work->work_difficulty; pool->seq_rejects++; applog(LOG_DEBUG, "PROOF OF WORK RESULT: false (booooo)"); if (!QUIET) { @@ -2621,6 +2628,8 @@ static void *submit_work_thread(void *userdata) sharelog("discard", work); total_stale++; pool->stale_shares++; + total_diff_stale += work->work_difficulty; + pool->diff_stale += work->work_difficulty; goto out; } work->stale = true; @@ -2634,6 +2643,8 @@ static void *submit_work_thread(void *userdata) applog(LOG_NOTICE, "Share became stale while retrying submit, discarding"); total_stale++; pool->stale_shares++; + total_diff_stale += work->work_difficulty; + pool->diff_stale += work->work_difficulty; break; } @@ -3080,6 +3091,8 @@ static void display_pool_summary(struct pool *pool) wlog(" Share submissions: %d\n", pool->accepted + pool->rejected); wlog(" Accepted shares: %d\n", pool->accepted); wlog(" Rejected shares: %d\n", pool->rejected); + wlog(" Accepted difficulty shares: %1.f\n", pool->diff_accepted); + wlog(" Rejected difficulty shares: %1.f\n", pool->diff_rejected); if (pool->accepted || pool->rejected) wlog(" Reject ratio: %.1f%%\n", (double)(pool->rejected * 100) / (double)(pool->accepted + pool->rejected)); efficiency = pool->getwork_requested ? pool->accepted * 100.0 / pool->getwork_requested : 0.0; @@ -4996,6 +5009,8 @@ static void print_summary(void) applog(LOG_WARNING, "Share submissions: %d", total_accepted + total_rejected); applog(LOG_WARNING, "Accepted shares: %d", total_accepted); applog(LOG_WARNING, "Rejected shares: %d", total_rejected); + applog(LOG_WARNING, "Accepted difficulty shares: %1.f", total_diff_accepted); + applog(LOG_WARNING, "Rejected difficulty shares: %1.f", total_diff_rejected); if (total_accepted || total_rejected) applog(LOG_WARNING, "Reject ratio: %.1f%%", (double)(total_rejected * 100) / (double)(total_accepted + total_rejected)); applog(LOG_WARNING, "Hardware errors: %d", hw_errors); @@ -5021,6 +5036,8 @@ static void print_summary(void) applog(LOG_WARNING, " Share submissions: %d", pool->accepted + pool->rejected); applog(LOG_WARNING, " Accepted shares: %d", pool->accepted); applog(LOG_WARNING, " Rejected shares: %d", pool->rejected); + applog(LOG_WARNING, " Accepted difficulty shares: %1.f", pool->diff_accepted); + applog(LOG_WARNING, " Rejected difficulty shares: %1.f", pool->diff_rejected); if (pool->accepted || pool->rejected) applog(LOG_WARNING, " Reject ratio: %.1f%%", (double)(pool->rejected * 100) / (double)(pool->accepted + pool->rejected)); efficiency = pool->getwork_requested ? pool->accepted * 100.0 / pool->getwork_requested : 0.0; diff --git a/miner.h b/miner.h index f3e9303b..b94645e5 100644 --- a/miner.h +++ b/miner.h @@ -401,6 +401,8 @@ struct cgpu_info { float gpu_vddc; #endif int diff1; + double diff_accepted; + double diff_rejected; int last_share_pool; time_t last_share_pool_time; @@ -684,6 +686,7 @@ extern unsigned int new_blocks; extern unsigned int found_blocks; extern int total_accepted, total_rejected, total_diff1;; extern int total_getworks, total_stale, total_discarded; +extern double total_diff_accepted, total_diff_rejected, total_diff_stale; extern unsigned int local_work; extern unsigned int total_go, total_ro; extern const int opt_cutofftemp; @@ -748,6 +751,10 @@ struct pool { int solved; int diff1; + double diff_accepted; + double diff_rejected; + double diff_stale; + int queued; int staged; @@ -906,7 +913,8 @@ enum api_data_type { API_UTILITY, API_FREQ, API_VOLTS, - API_HS + API_HS, + API_DIFF }; struct api_data { @@ -937,5 +945,6 @@ extern struct api_data *api_add_utility(struct api_data *root, char *name, doubl extern struct api_data *api_add_freq(struct api_data *root, char *name, double *data, bool copy_data); extern struct api_data *api_add_volts(struct api_data *root, char *name, float *data, bool copy_data); extern struct api_data *api_add_hs(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_diff(struct api_data *root, char *name, double *data, bool copy_data); #endif /* __MINER_H__ */ From a6bf276f6b589d5de544baafb553bc34ce16907b Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 19 Sep 2012 01:14:43 +1000 Subject: [PATCH 36/50] API - Add last share difficulty for devices and pool --- API-README | 14 ++++++++------ api.c | 4 ++++ cgminer.c | 2 ++ miner.h | 2 ++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/API-README b/API-README index ad89b1f8..d0653d44 100644 --- a/API-README +++ b/API-README @@ -392,13 +392,15 @@ Added API commands: Modified API commands: Change pool field name 'Diff1 Shares' to 'Diff1 Work' - 'devs' - add 'Diff1 Work', 'Difficulty Accepted', 'Difficulty Rejected' - to all devices - 'gpu|N' - add 'Diff1 Work', 'Difficulty Accepted', 'Difficulty Rejected' - 'pga|N' - add 'Diff1 Work', 'Difficulty Accepted', 'Difficulty Rejected' + 'devs' - add 'Diff1 Work', 'Difficulty Accepted', 'Difficulty Rejected', + 'Last Share Difficulty' to all devices + 'gpu|N' - add 'Diff1 Work', 'Difficulty Accepted', + 'Difficulty Rejected', 'Last Share Difficulty' + 'pga|N' - add 'Diff1 Work', 'Difficulty Accepted', + 'Difficulty Rejected', 'Last Share Difficulty' 'notify' - add '*Dev Throttle' (for BFL Singles) - 'pools' - add 'Proxy Type', 'Proxy', 'Difficulty Accepted', - 'Difficulty Rejected', 'Difficulty Stale' + 'pools' - add 'Proxy Type', 'Proxy', 'Difficulty Accepted', 'Difficulty Rejected', + 'Difficulty Stale', 'Last Share Difficulty' 'config' - add 'Queue', 'Expiry' ---------- diff --git a/api.c b/api.c index 9b4e017e..ec07b44f 100644 --- a/api.c +++ b/api.c @@ -1387,6 +1387,7 @@ static void gpustatus(int gpu, bool isjson) root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false); root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false); root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false); + root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false); root = print_data(root, buf, isjson); strcat(io_buffer, buf); @@ -1473,6 +1474,7 @@ static void pgastatus(int pga, bool isjson) root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false); root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false); root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false); + root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false); root = print_data(root, buf, isjson); strcat(io_buffer, buf); @@ -1508,6 +1510,7 @@ static void cpustatus(int cpu, bool isjson) root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false); root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false); root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false); + root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false); root = print_data(root, buf, isjson); strcat(io_buffer, buf); @@ -1890,6 +1893,7 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, root = api_add_diff(root, "Difficulty Accepted", &(pool->diff_accepted), false); root = api_add_diff(root, "Difficulty Rejected", &(pool->diff_rejected), false); root = api_add_diff(root, "Difficulty Stale", &(pool->diff_stale), false); + root = api_add_diff(root, "Last Share Difficulty", &(pool->last_share_diff), false); if (isjson && (i > 0)) strcat(io_buffer, COMMA); diff --git a/cgminer.c b/cgminer.c index cb61958e..90bc4a83 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1877,7 +1877,9 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub pool->seq_rejects = 0; cgpu->last_share_pool = pool->pool_no; cgpu->last_share_pool_time = time(NULL); + cgpu->last_share_diff = work->work_difficulty; pool->last_share_time = cgpu->last_share_pool_time; + pool->last_share_diff = work->work_difficulty; applog(LOG_DEBUG, "PROOF OF WORK RESULT: true (yay!!!)"); if (!QUIET) { if (total_pools > 1) diff --git a/miner.h b/miner.h index b94645e5..d558bad8 100644 --- a/miner.h +++ b/miner.h @@ -405,6 +405,7 @@ struct cgpu_info { double diff_rejected; int last_share_pool; time_t last_share_pool_time; + double last_share_diff; time_t device_last_well; time_t device_last_not_well; @@ -800,6 +801,7 @@ struct pool { struct list_head curlring; time_t last_share_time; + double last_share_diff; struct cgminer_stats cgminer_stats; struct cgminer_pool_stats cgminer_pool_stats; From 22a8eee0b8c8226b4084898d70024dcb48a42824 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 19 Sep 2012 20:55:46 +1000 Subject: [PATCH 37/50] miner.php highlighting correctly handling difficulty --- miner.php | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/miner.php b/miner.php index 268e05bf..2c28f6fe 100644 --- a/miner.php +++ b/miner.php @@ -523,7 +523,15 @@ function classlastshare($when, $alldata, $warnclass, $errorclass) if (!isset($alldata['Last Share Time'])) return ''; + if (!isset($alldata['Last Share Difficulty'])) + return ''; + $expected = pow(2, 32) / ($alldata['MHS av'] * pow(10, 6)); + + // If the share difficulty changes while waiting on a share, + // this calculation will of course be incorrect + $expected *= $alldata['Last Share Difficulty']; + $howlong = $when - $alldata['Last Share Time']; if ($howlong < 1) $howlong = 1; @@ -658,11 +666,20 @@ function fmt($section, $name, $value, $when, $alldata) if ($value == 0) $class = $errorclass; else - if (isset($alldata['MHS av'])) + if (isset($alldata['Difficulty Accepted']) + && isset($alldata['Accepted']) + && isset($alldata['MHS av']) + && ($alldata['Difficulty Accepted'] > 0) + && ($alldata['Accepted'] > 0)) { $expected = 60 * $alldata['MHS av'] * (pow(10, 6) / pow(2, 32)); if ($expected == 0) $expected = 0.000001; // 1 H/s + + $da = $alldata['Difficulty Accepted']; + $a = $alldata['Accepted']; + $expected /= ($da / $a); + $ratio = $value / $expected; if ($ratio < 0.9) $class = $loclass; @@ -730,16 +747,26 @@ function fmt($section, $name, $value, $when, $alldata) $dec = ''; else $dec = '.'.$parts[1]; - $ret = number_format($parts[0]).$dec; + $ret = number_format((float)$parts[0]).$dec; if ($value == 0) $class = $errorclass; else - if (isset($alldata['Utility'])) + if (isset($alldata['Difficulty Accepted']) + && isset($alldata['Accepted']) + && isset($alldata['Utility']) + && ($alldata['Difficulty Accepted'] > 0) + && ($alldata['Accepted'] > 0)) { $expected = 60 * $value * (pow(10, 6) / pow(2, 32)); - $utility = $alldata['Utility']; - $ratio = $utility / $expected; + if ($expected == 0) + $expected = 0.000001; // 1 H/s + + $da = $alldata['Difficulty Accepted']; + $a = $alldata['Accepted']; + $expected /= ($da / $a); + + $ratio = $alldata['Utility'] / $expected; if ($ratio < 0.9) $class = $hiclass; else @@ -783,7 +810,7 @@ function fmt($section, $name, $value, $when, $alldata) $dec = ''; else $dec = '.'.$parts[1]; - $ret = number_format($parts[0]).$dec; + $ret = number_format((float)$parts[0]).$dec; break; case 'GPU.Status': case 'PGA.Status': From 17973c59c417d0786019b58191c321d3f9367752 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 21 Sep 2012 11:25:43 +1000 Subject: [PATCH 38/50] API don't change 'Diff1 Shares' - backward compatability FTW --- API-README | 1 - api.c | 2 +- miner.php | 9 ++++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/API-README b/API-README index d0653d44..6d0dda0e 100644 --- a/API-README +++ b/API-README @@ -391,7 +391,6 @@ Added API commands: 'setconfig|name,N' Modified API commands: - Change pool field name 'Diff1 Shares' to 'Diff1 Work' 'devs' - add 'Diff1 Work', 'Difficulty Accepted', 'Difficulty Rejected', 'Last Share Difficulty' to all devices 'gpu|N' - add 'Diff1 Work', 'Difficulty Accepted', diff --git a/api.c b/api.c index ec07b44f..0b6d54d6 100644 --- a/api.c +++ b/api.c @@ -1882,7 +1882,7 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, root = api_add_uint(root, "Remote Failures", &(pool->remotefail_occasions), false); root = api_add_escape(root, "User", pool->rpc_user, false); root = api_add_time(root, "Last Share Time", &(pool->last_share_time), false); - root = api_add_int(root, "Diff1 Work", &(pool->diff1), false); + root = api_add_int(root, "Diff1 Shares", &(pool->diff1), false); if (pool->rpc_proxy) { root = api_add_const(root, "Proxy Type", proxytype(pool->rpc_proxytype), false); root = api_add_escape(root, "Proxy", pool->rpc_proxy, false); diff --git a/miner.php b/miner.php index 2c28f6fe..f6250f0d 100644 --- a/miner.php +++ b/miner.php @@ -799,12 +799,11 @@ function fmt($section, $name, $value, $when, $alldata) case 'SUMMARY.Discarded': case 'POOL.Discarded': case 'total.Discarded': + case 'POOL.Diff1 Shares': + case 'total.Diff1 Shares': case 'GPU.Diff1 Work': case 'PGA.Diff1 Work': - case 'POOL.Diff1 Work': case 'total.Diff1 Work': - case 'POOL.Diff1 Shares': // old name - case 'total.Diff1 Shares': // old name $parts = explode('.', $value, 2); if (count($parts) == 1) $dec = ''; @@ -893,7 +892,7 @@ $singlerigsum = array( 'Hardware Errors' => 1, 'Utility' => 1, 'Total MH' => 1), 'pools' => array('Getworks' => 1, 'Accepted' => 1, 'Rejected' => 1, 'Discarded' => 1, 'Stale' => 1, 'Get Failures' => 1, 'Remote Failures' => 1, - 'Diff1 Work' => 1), + 'Diff1 Shares' => 1), 'notify' => array('*' => 1)); # function showtotal($total, $when, $oldvalues) @@ -2100,7 +2099,7 @@ function display() newtable(); doforeach('version', 'rig summary', array(), array(), true); - $sum = array('MHS av', 'Getworks', 'Found Blocks', 'Accepted', 'Rejected', 'Discarded', 'Stale', 'Utility', 'Local Work', 'Total MH', 'Work Utility', 'Diff1 Work'); + $sum = array('MHS av', 'Getworks', 'Found Blocks', 'Accepted', 'Rejected', 'Discarded', 'Stale', 'Utility', 'Local Work', 'Total MH', 'Work Utility', 'Diff1 Shares', 'Diff1 Work'); doforeach('summary', 'summary information', $sum, array(), false); endtable(); otherrow('

'); From 55b8f2e06e8a62a62f8ed79fcf9bff235a3c2201 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 21 Sep 2012 16:01:40 +1000 Subject: [PATCH 39/50] Test for the now-automatically exported variable AMDAPPSDKROOT when looking for the presence of the OpenCL headers. --- configure.ac | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 68ea6ca7..8ce1643c 100644 --- a/configure.ac +++ b/configure.ac @@ -104,14 +104,18 @@ case $target in ;; esac +if test "x$have_x86_64" = xtrue; then + ARCH_DIR=x86_64 +else + ARCH_DIR=x86 +fi + if test "x$ATISTREAMSDKROOT" != x; then - if test "x$have_x86_64" = xtrue; then - ATI_STREAM_ARCH_DIR=x86_64 - else - ATI_STREAM_ARCH_DIR=x86 - fi OPENCL_FLAGS="-I$ATISTREAMSDKROOT/include $OPENCL_FLAGS" - OPENCL_LIBS="-L$ATISTREAMSDKROOT/lib/$ATI_STREAM_ARCH_DIR $OPENCL_LIBS" + OPENCL_LIBS="-L$ATISTREAMSDKROOT/lib/$ARCH_DIR $OPENCL_LIBS" +elif test "x$AMDAPPSDKROOT" != x; then + OPENCL_FLAGS="-I$AMDAPPSDKROOT/include $OPENCL_FLAGS" + OPENCL_LIBS="-L$AMDAPPSDKROOT/lib/$ARCH_DIR $OPENCL_LIBS" fi cpumining="no" From 618999026f2b3863ab0a9477b500995c924d28b0 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 21 Sep 2012 16:10:34 +1000 Subject: [PATCH 40/50] As we average gpu time over 5 work intervals for dynamic GPU intensity, there is no need to maintain a rolling average and it avoids the potential long term corruption of a single overflow value. --- driver-opencl.c | 5 ++--- miner.h | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/driver-opencl.c b/driver-opencl.c index ded20c31..82cbc6bb 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -1585,15 +1585,14 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work, gpu_us = us_tdiff(&tv_gpuend, &gpu->tv_gpumid); if (gpu_us > 0 && ++gpu->hit > 4) { gpu_us = us_tdiff(&tv_gpuend, &gpu->tv_gpustart) / gpu->intervals; - gpu->gpu_us_average = (gpu->gpu_us_average + gpu_us * 0.63) / 1.63; /* Try to not let the GPU be out for longer than * opt_dynamic_interval in ms, but increase * intensity when the system is idle in dynamic mode */ - if (gpu->gpu_us_average > dynamic_us) { + if (gpu_us > dynamic_us) { if (gpu->intensity > MIN_INTENSITY) --gpu->intensity; - } else if (gpu->gpu_us_average < dynamic_us / 2) { + } else if (gpu_us < dynamic_us / 2) { if (gpu->intensity < MAX_INTENSITY) ++gpu->intensity; } diff --git a/miner.h b/miner.h index a234ecd3..ed6c67ca 100644 --- a/miner.h +++ b/miner.h @@ -374,7 +374,6 @@ struct cgpu_info { #endif struct timeval tv_gpustart; struct timeval tv_gpumid; - double gpu_us_average; int intervals, hit; #endif From 41dcb10d4c490e802b962090875e4911dda82221 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 21 Sep 2012 20:55:48 +1000 Subject: [PATCH 41/50] util.c - bug - proxy - no data end condition --- util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/util.c b/util.c index b3a5a1ba..3a0dbc18 100644 --- a/util.c +++ b/util.c @@ -480,6 +480,7 @@ static struct { { "socks4a:", CURLPROXY_SOCKS4A }, { "socks5h:", CURLPROXY_SOCKS5_HOSTNAME }, #endif + { NULL, 0 } }; #endif From 37f8a1f77593cdbaee65a4f63c9db99f0f81c34f Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 21 Sep 2012 22:04:39 +1000 Subject: [PATCH 42/50] reduce windows compile warnings --- compat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compat.h b/compat.h index c6e38d8a..f7cb4da5 100644 --- a/compat.h +++ b/compat.h @@ -57,7 +57,7 @@ enum { PRIO_PROCESS = 0, }; -static inline int setpriority(int which, int who, int prio) +static inline int setpriority(__maybe_unused int which, __maybe_unused int who, __maybe_unused int prio) { /* FIXME - actually do something */ return 0; From 57a73dce34816ef6c2ddb4a351a2b819c82c574d Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 24 Sep 2012 08:30:07 +1000 Subject: [PATCH 43/50] Test for sequential getwork failures on a pool that might actually be up but failing to deliver work as we may end up hammering it repeatedly by mistake. --- cgminer.c | 24 ++++++++++++++---------- miner.h | 1 + 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/cgminer.c b/cgminer.c index 90bc4a83..7645ff26 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2476,6 +2476,15 @@ out: static bool queue_request(void); +static void pool_died(struct pool *pool) +{ + if (!pool_tset(pool, &pool->idle)) { + applog(LOG_WARNING, "Pool %d %s not responding!", pool->pool_no, pool->rpc_url); + gettimeofday(&pool->tv_idle, NULL); + switch_pools(NULL); + } +} + static void *get_work_thread(void *userdata) { struct workio_cmd *wc = (struct workio_cmd *)userdata; @@ -2508,13 +2517,17 @@ static void *get_work_thread(void *userdata) /* obtain new work from bitcoin via JSON-RPC */ if (!get_upstream_work(ret_work, ce->curl)) { - /* pause, then restart work-request loop */ applog(LOG_DEBUG, "json_rpc_call failed on get work, retrying"); dec_queued(pool); + /* Make sure the pool just hasn't stopped serving + * requests but is up as we'll keep hammering it */ + if (++pool->seq_getfails > mining_threads + opt_queue) + pool_died(pool); queue_request(); free_work(ret_work); goto out; } + pool->seq_getfails = 0; ret_work->queued = true; } @@ -3998,15 +4011,6 @@ out: return ret; } -static void pool_died(struct pool *pool) -{ - if (!pool_tset(pool, &pool->idle)) { - applog(LOG_WARNING, "Pool %d %s not responding!", pool->pool_no, pool->rpc_url); - gettimeofday(&pool->tv_idle, NULL); - switch_pools(NULL); - } -} - static inline int cp_prio(void) { int prio; diff --git a/miner.h b/miner.h index 8d85475d..ede389aa 100644 --- a/miner.h +++ b/miner.h @@ -748,6 +748,7 @@ struct pool { int prio; int accepted, rejected; int seq_rejects; + int seq_getfails; int solved; int diff1; From 149f1d75bef8258af9a49e9f7c708abe8ccbc1c6 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 24 Sep 2012 08:49:40 +1000 Subject: [PATCH 44/50] README - FAQ - usermod group - shouldn't remove other groups --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 1591d66c..c034a7c5 100644 --- a/README +++ b/README @@ -905,7 +905,7 @@ will give output like: 0 crw-rw---- 1 root dialout 188, 0 2012-09-11 13:49 /dev/ttyUSB0 This means your account must have the group 'dialout' or root priviledges To permanently give your account the 'dialout' group: - sudo usermod -G dialout `whoami` + sudo usermod -G dialout -a `whoami` Then logout and back in again From fd28d9f4076b003159bc3b9fe293d9718c7d08ad Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 24 Sep 2012 09:03:27 +1000 Subject: [PATCH 45/50] Ignore any pings pushed to the worker threads if the thread is still paused to prevent it being enabled and disabled repeatedly. --- cgminer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index 7645ff26..bb522f35 100644 --- a/cgminer.c +++ b/cgminer.c @@ -4353,7 +4353,9 @@ static void mt_disable(struct thr_info *mythr, const int thr_id, mythr->rolling = mythr->cgpu->rolling = 0; applog(LOG_DEBUG, "Popping wakeup ping in miner thread"); thread_reportout(mythr); - tq_pop(mythr->q, NULL); /* Ignore ping that's popped */ + do { + tq_pop(mythr->q, NULL); /* Ignore ping that's popped */ + } while (mythr->pause); thread_reportin(mythr); applog(LOG_WARNING, "Thread %d being re-enabled", thr_id); if (api->thread_enable) From 7c32562d80b1b687b039097e3fabc28c2793e54f Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 24 Sep 2012 11:34:50 +1000 Subject: [PATCH 46/50] API stats add some pool getwork difficulty stats --- API-README | 2 ++ api.c | 5 +++++ cgminer.c | 17 +++++++++++++++++ miner.h | 5 +++++ 4 files changed, 29 insertions(+) diff --git a/API-README b/API-README index 6d0dda0e..a1c54c55 100644 --- a/API-README +++ b/API-README @@ -401,6 +401,8 @@ Modified API commands: 'pools' - add 'Proxy Type', 'Proxy', 'Difficulty Accepted', 'Difficulty Rejected', 'Difficulty Stale', 'Last Share Difficulty' 'config' - add 'Queue', 'Expiry' + 'stats' - add 'Work Diff', 'Min Diff', 'Max Diff', 'Min Diff Count', + 'Max Diff Count' to the pool stats ---------- diff --git a/api.c b/api.c index 0b6d54d6..8ebf94da 100644 --- a/api.c +++ b/api.c @@ -2789,6 +2789,11 @@ static int itemstats(int i, char *id, struct cgminer_stats *stats, struct cgmine root = api_add_bool(root, "Work Can Roll", &(pool_stats->canroll), false); root = api_add_bool(root, "Work Had Expire", &(pool_stats->hadexpire), false); root = api_add_uint32(root, "Work Roll Time", &(pool_stats->rolltime), false); + root = api_add_diff(root, "Work Diff", &(pool_stats->last_diff), false); + root = api_add_diff(root, "Min Diff", &(pool_stats->min_diff), false); + root = api_add_diff(root, "Max Diff", &(pool_stats->max_diff), false); + root = api_add_uint32(root, "Min Diff Count", &(pool_stats->min_diff_count), false); + root = api_add_uint32(root, "Max Diff Count", &(pool_stats->max_diff_count), false); } if (extra) diff --git a/cgminer.c b/cgminer.c index bb522f35..46806afa 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2047,6 +2047,7 @@ static double DIFFEXACTONE = 269599466671506397946670150870196306736371444225405 */ static void calc_diff(struct work *work) { + struct cgminer_pool_stats *pool_stats = &(work->pool->cgminer_pool_stats); double targ; int i; @@ -2057,6 +2058,22 @@ static void calc_diff(struct work *work) } work->work_difficulty = DIFFEXACTONE / (targ ? : DIFFEXACTONE); + + pool_stats->last_diff = work->work_difficulty; + + if (work->work_difficulty == pool_stats->min_diff) + pool_stats->min_diff_count++; + else if (work->work_difficulty < pool_stats->min_diff || pool_stats->min_diff == 0) { + pool_stats->min_diff = work->work_difficulty; + pool_stats->min_diff_count = 1; + } + + if (work->work_difficulty == pool_stats->max_diff) + pool_stats->max_diff_count++; + else if (work->work_difficulty > pool_stats->max_diff) { + pool_stats->max_diff = work->work_difficulty; + pool_stats->max_diff_count = 1; + } } static void get_benchmark_work(struct work *work) diff --git a/miner.h b/miner.h index ede389aa..169c9ee1 100644 --- a/miner.h +++ b/miner.h @@ -314,6 +314,11 @@ struct cgminer_pool_stats { bool canroll; bool hadexpire; uint32_t rolltime; + double min_diff; + double max_diff; + double last_diff; + uint32_t min_diff_count; + uint32_t max_diff_count; }; struct cgpu_info { From 823a710a54c832705e06718e0f617bb19a18bcc7 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 24 Sep 2012 14:08:35 +1000 Subject: [PATCH 47/50] Display share difficulty on log with a shortened hash display on submission. --- cgminer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index 46806afa..10c92207 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1818,7 +1818,9 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub if (opt_scrypt) sprintf(hashshow, "%08lx.%08lx", (unsigned long)(hash32[7]), (unsigned long)(hash32[6])); else { - sprintf(hashshow, "%08lx.%08lx%s", (unsigned long)(hash32[6]), (unsigned long)(hash32[5]), + int intdiff = round(work->work_difficulty); + + sprintf(hashshow, "%08lx Diff %d%s", (unsigned long)(hash32[6]), intdiff, work->block? " BLOCK!" : ""); } From 8ec87c64a9f33748dd44b43610e1168d08320b79 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 24 Sep 2012 14:14:37 +1000 Subject: [PATCH 48/50] Update NEWS. --- NEWS | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/NEWS b/NEWS index 6b104c30..115bf83c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,60 @@ +Version 2.7.6 - September 24, 2012 + +- Display share difficulty on log with a shortened hash display on submission. +- API stats add some pool getwork difficulty stats +- Ignore any pings pushed to the worker threads if the thread is still paused to +prevent it being enabled and disabled repeatedly. +- README - FAQ - usermod group - shouldn't remove other groups +- Test for sequential getwork failures on a pool that might actually be up but +failing to deliver work as we may end up hammering it repeatedly by mistake. +- reduce windows compile warnings +- util.c - bug - proxy - no data end condition +- As we average gpu time over 5 work intervals for dynamic GPU intensity, there +is no need to maintain a rolling average and it avoids the potential long term +corruption of a single overflow value. +- Test for the now-automatically exported variable AMDAPPSDKROOT when looking +for the presence of the OpenCL headers. +- API don't change 'Diff1 Shares' - backward compatability FTW +- miner.php highlighting correctly handling difficulty +- API - Add last share difficulty for devices and pool +- Store and report Accepted,Rejected,Stale difficulty in the summary and API +- WorkTime - display prevblock for scrypt +- api.c remove compile warnings +- Calculate work difficulty for each getwork and display with WorkTime debug +- remove MMQ unused variable warning +- FPGA - allow long or short device names in detect code + style police +- WorkTime - multiple nonce per work and identify the work source +- Optional WorkTime details with each Accepted/Rejected work item +- Icarus - ignore hardware errors in timing mode +- miner.php oops - mistype +- miner.php by default don't display IP/Port numbers in error messages +- api.c all STATUS messages automatically escaped +- api.c add missing escape for comma in MSG_PGAUNW +- API add display of and setting queue,scantime,expiry +- HW: dont submit bad shares +- save individual pool proxy settings to config +- --default-config - allow command line to define the default configuration file +for loading and saving +- API-README update for pools proxy info +- README URL proxy must use quote so show in the example +- bug: remove proxy: from the front of the proxy used +- CURL support for individual proxy per pool and all proxy types +- README spelling/etc +- README - FPGA device FAQ +- HW: error counter auto for all devices - ztex code not fixed +- API pgaidentify - unsupported message should be a warning +- API/BFL identify a device - currently only BFL to flash the led +- BFL add throttle count to internal stats + API +- BFL: missing device id in log message +- miner.php correct to new Diff1 Work field names +- API add device diff1 work +- API-README update +- api.c Correct diff1 field name +- count device diff1 shares +- API-README more debug parameter information +- API allow full debug settings control + + Version 2.7.5 - August 31, 2012 - Adjust opencl intensity when adjusting thread count to prevent it getting From 54dcd57f95a98a61cea11d1d1d176a10a2afe087 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 24 Sep 2012 14:15:05 +1000 Subject: [PATCH 49/50] Bump version number to 2.7.6 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 8ce1643c..fe618e02 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## m4_define([v_maj], [2]) m4_define([v_min], [7]) -m4_define([v_mic], [5]) +m4_define([v_mic], [6]) ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## m4_define([v_ver], [v_maj.v_min.v_mic]) m4_define([lt_rev], m4_eval(v_maj + v_min)) From 346d09c36dc866c7ff098d1628cf9581a3962891 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 24 Sep 2012 14:37:23 +1000 Subject: [PATCH 50/50] Reorder libztex header include order to fix missing struct definition. --- libztex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libztex.c b/libztex.c index 627dfb27..923c224a 100644 --- a/libztex.c +++ b/libztex.c @@ -23,8 +23,8 @@ #include #include -#include "fpgautils.h" #include "miner.h" +#include "fpgautils.h" #include "libztex.h" #define BUFSIZE 256