Provide a control lock around global bools to avoid racing on them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
diff --git a/main.c b/main.c
index eb111fe..1b129fc 100644
--- a/main.c
+++ b/main.c
@@ -168,9 +168,12 @@ static pthread_mutex_t curses_lock;
static double total_mhashes_done;
static struct timeval total_tv_start, total_tv_end;
+pthread_mutex_t control_lock;
+
static int accepted, rejected;
int hw_errors;
static int total_queued, total_staged, lp_staged;
+static bool submit_fail = false;
static bool localgen = false;
static bool idlenet = false;
static unsigned int getwork_requested;
@@ -181,6 +184,8 @@ static unsigned int local_work;
static unsigned int localgen_occasions;
static unsigned int remotefail_occasions;
+static bool curses_active = false;
+
static char current_block[37];
static char longpoll_block[37];
static char blank[37];
@@ -540,7 +545,6 @@ static WINDOW *mainwin, *statuswin, *logwin;
static double total_secs = 0.1;
static char statusline[256];
static int cpucursor, gpucursor, logstart, logcursor;
-static bool curses_active = false;
static struct cgpu_info *gpus, *cpus;
static void text_print_status(int thr_id)
@@ -626,8 +630,6 @@ void log_curses(const char *f, va_list ap)
vprintf(f, ap);
}
-static bool submit_fail = false;
-
static bool submit_upstream_work(const struct work *work)
{
char *hexstr = NULL;
@@ -662,16 +664,13 @@ static bool submit_upstream_work(const struct work *work)
val = json_rpc_call(curl, rpc_url, rpc_userpass, s, false, false);
if (unlikely(!val)) {
applog(LOG_INFO, "submit_upstream_work json_rpc_call failed");
- if (!submit_fail) {
- submit_fail = true;
+ if (!test_and_set(&submit_fail)) {
remotefail_occasions++;
applog(LOG_WARNING, "Upstream communication failure, caching submissions");
}
goto out;
- } else if (submit_fail) {
- submit_fail = false;
+ } else if (test_and_clear(&submit_fail))
applog(LOG_WARNING, "Upstream communication resumed, submitting work");
- }
res = json_object_get(val, "result");
@@ -764,8 +763,7 @@ static void workio_cmd_free(struct workio_cmd *wc)
static void disable_curses(void)
{
- if (curses_active) {
- curses_active = false;
+ if (test_and_clear(&curses_active)) {
delwin(logwin);
delwin(statuswin);
delwin(mainwin);
@@ -1293,8 +1291,7 @@ retry:
uint32_t ntime;
/* Only print this message once each time we shift to localgen */
- if (!localgen) {
- localgen = true;
+ if (!test_and_set(&localgen)) {
applog(LOG_WARNING, "Server not providing work fast enough, generating work locally");
localgen_occasions++;
gettimeofday(&tv_localgen, NULL);
@@ -1329,10 +1326,8 @@ retry:
}
/* If we make it here we have succeeded in getting fresh work */
- if (localgen) {
- localgen = false;
+ if (test_and_clear(&localgen))
applog(LOG_WARNING, "Resuming with work from server");
- }
dec_queued();
memcpy(work, work_heap, sizeof(*work));
@@ -2118,6 +2113,8 @@ int main (int argc, char *argv[])
return 1;
if (unlikely(pthread_mutex_init(&curses_lock, NULL)))
return 1;
+ if (unlikely(pthread_mutex_init(&control_lock, NULL)))
+ return 1;
handler.sa_handler = &sighandler;
sigaction(SIGTERM, &handler, &termhandler);
@@ -2404,7 +2401,7 @@ int main (int argc, char *argv[])
scrollok(logwin, true);
leaveok(logwin, true);
leaveok(statuswin, true);
- curses_active = true;
+ test_and_set(&curses_active);
for (i = 0; i < mining_threads; i++)
print_status(i);
}
diff --git a/miner.h b/miner.h
index 53a537e..ee6b55e 100644
--- a/miner.h
+++ b/miner.h
@@ -232,6 +232,7 @@ extern bool use_syslog;
extern struct thr_info *thr_info;
extern int longpoll_thr_id;
extern struct work_restart *work_restart;
+extern pthread_mutex_t control_lock;
#ifdef HAVE_OPENCL
typedef struct {
@@ -279,6 +280,8 @@ extern bool tq_push(struct thread_q *tq, void *data);
extern void *tq_pop(struct thread_q *tq, const struct timespec *abstime);
extern void tq_freeze(struct thread_q *tq);
extern void tq_thaw(struct thread_q *tq);
+extern bool test_and_set(bool *var);
+extern bool test_and_clear(bool *var);
extern bool successful_connect;
#endif /* __MINER_H__ */
diff --git a/util.c b/util.c
index bf0f288..02a488e 100644
--- a/util.c
+++ b/util.c
@@ -34,6 +34,28 @@
bool successful_connect = false;
+bool test_and_set(bool *var)
+{
+ bool ret;
+
+ pthread_mutex_lock(&control_lock);
+ ret = *var;
+ *var = true;
+ pthread_mutex_unlock(&control_lock);
+ return ret;
+}
+
+bool test_and_clear(bool *var)
+{
+ bool ret;
+
+ pthread_mutex_lock(&control_lock);
+ ret = *var;
+ *var = false;
+ pthread_mutex_unlock(&control_lock);
+ return ret;
+}
+
struct data_buffer {
void *buf;
size_t len;