Commit e615b61f0ae44df3478d50a493511a0409c22161

Ycros 2011-07-23T02:26:07

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

diff --git a/README b/README
index 3c522ef..a4af798 100644
--- a/README
+++ b/README
@@ -66,6 +66,7 @@ Native WIN32 build instructions (on mingw32, on windows):
 
 Usage instructions:  Run "cgminer --help" to see options.
 
+---
 
 EXECUTIVE SUMMARY ON USAGE:
 
@@ -81,7 +82,42 @@ Multiple pool, dedicated miner:
 
 cgminer -o http://pool1:port -u pool1username -p pool1password -o http://pool2:port -u pool2usernmae -p pool2password -I 8
 
+---
 
+WHILE RUNNING:
+
+The following options are available while running with a single keypress:
+
+[P]ool management [S]ettings [D]isplay options [Q]uit
+
+P gives you:
+
+Current pool management strategy: Failover
+[A]dd pool [R]emove pool [D]isable pool [E]nable pool
+[C]hange management strategy [S]witch pool [I]nformation
+
+
+S gives you:
+
+[D]ynamic mode: On
+[L]ongpoll: On
+[I]ntensity: Dynamic
+[Q]ueue: 0
+[S]cantime: 60
+[R]etries: -1
+[P]ause: 5
+
+
+D gives you:
+
+Toggle: [D]ebug [N]ormal [S]ilent [V]erbose [R]PC debug
+[L]og interval [C]lear
+
+
+and Q quits the application.
+
+
+---
 Also many issues and FAQs are covered in the forum thread
 dedicated to this program,
 	http://forum.bitcoin.org/index.php?topic=28402.0
diff --git a/main.c b/main.c
index 7a9d64a..f823baf 100644
--- a/main.c
+++ b/main.c
@@ -327,10 +327,10 @@ static char *set_int_0_to_9999(const char *arg, int *i)
 	return set_int_range(arg, i, 0, 9999);
 }
 
-static char *forced_int_0_to_14(const char *arg, int *i)
+static char *forced_int_1010(const char *arg, int *i)
 {
 	opt_dynamic = false;
-	return set_int_range(arg, i, 0, 14);
+	return set_int_range(arg, i, -10, 10);
 }
 
 static char *force_nthreads_int(const char *arg, int *i)
@@ -501,8 +501,8 @@ static struct opt_table opt_config_table[] = {
 		     set_int_0_to_10, opt_show_intval, &opt_g_threads,
 		     "Number of threads per GPU (0 - 10)"),
 	OPT_WITH_ARG("--intensity|-I",
-		     forced_int_0_to_14, opt_show_intval, &scan_intensity,
-		     "Intensity of GPU scanning (0 - 14, default: dynamic to maintain desktop interactivity)"),
+		     forced_int_1010, opt_show_intval, &scan_intensity,
+		     "Intensity of GPU scanning (-10 -> 10, default: dynamic to maintain desktop interactivity)"),
 #endif
 	OPT_WITHOUT_ARG("--load-balance",
 		     set_loadbalance, &pool_strategy,
@@ -817,10 +817,8 @@ void log_curses(const char *f, va_list ap)
 
 static void clear_logwin(void)
 {
-	pthread_mutex_lock(&curses_lock);
 	wclear(logwin);
 	wrefresh(logwin);
-	pthread_mutex_unlock(&curses_lock);
 }
 
 static bool submit_upstream_work(const struct work *work)
@@ -1492,7 +1490,6 @@ static void display_pools(void)
 	immedok(logwin, true);
 updated:
 	clear_logwin();
-	pthread_mutex_lock(&curses_lock);
 	for (i = 0; i < total_pools; i++) {
 		pool = pools[i];
 
@@ -1516,7 +1513,7 @@ retry:
 	wprintw(logwin, "[A]dd pool [R]emove pool [D]isable pool [E]nable pool\n");
 	wprintw(logwin, "[C]hange management strategy [S]witch pool [I]nformation\n");
 	wprintw(logwin, "Or press any other key to continue\n");
-	pthread_mutex_unlock(&curses_lock);
+	wrefresh(logwin);
 	input = getch();
 
 	if (!strncasecmp(&input, "a", 1)) {
@@ -1622,6 +1619,7 @@ static void display_options(void)
 	opt_loginput = true;
 	immedok(logwin, true);
 retry:
+	clear_logwin();
 	wprintw(logwin, "\nToggle: [D]ebug [N]ormal [S]ilent [V]erbose [R]PC debug\n");
 	wprintw(logwin, "[L]og interval [C]lear\n");
 	wprintw(logwin, "Select an option or any other key to return\n");
@@ -1656,7 +1654,8 @@ retry:
 		}
 		opt_log_interval = selected;
 	}
-	wclear(logwin);
+
+	clear_logwin();
 	immedok(logwin, false);
 	opt_loginput = false;
 }
@@ -1669,7 +1668,7 @@ static void set_options(void)
 	opt_loginput = true;
 	immedok(logwin, true);
 retry:
-	wclear(logwin);
+	clear_logwin();
 	wprintw(logwin, "\n[D]ynamic mode: %s\n[L]ongpoll: %s\n",
 		opt_dynamic ? "On" : "Off", want_longpoll ? "On" : "Off");
 	if (opt_dynamic)
@@ -1679,6 +1678,7 @@ retry:
 	wprintw(logwin, "[Q]ueue: %d\n[S]cantime: %d\n[R]etries: %d\n[P]ause: %d\n",
 		opt_queue, opt_scantime, opt_retries, opt_fail_pause);
 	wprintw(logwin, "Select an option or any other key to return\n");
+	wrefresh(logwin);
 	input = getch();
 
 	if (!strncasecmp(&input, "q", 1)) {
@@ -1698,8 +1698,8 @@ retry:
 		restart_longpoll();
 		goto retry;
 	} else if (!strncasecmp(&input, "i", 1)) {
-		selected = curses_int("Set GPU scan intensity (0-10)");
-		if (selected < 0 || selected > 10) {
+		selected = curses_int("Set GPU scan intensity (-10 -> 10)");
+		if (selected < -10 || selected > 10) {
 			wprintw(logwin, "Invalid selection\n");
 			goto retry;
 		}
@@ -1731,7 +1731,8 @@ retry:
 		opt_fail_pause = selected;
 		goto retry;
 	}
-	wclear(logwin);
+
+	clear_logwin();
 	immedok(logwin, false);
 	opt_loginput = false;
 }
@@ -2053,11 +2054,12 @@ static void flush_requests(void)
 
 static inline bool can_roll(struct work *work)
 {
-	return (!stale_work(work) && work->pool->has_rolltime && work->rolls < 11);
+	return (work->pool && !stale_work(work) && work->pool->has_rolltime &&
+		work->rolls < 11);
 }
 
 static bool get_work(struct work *work, bool queued, struct thr_info *thr,
-		     const int thr_id)
+		     const int thr_id, uint32_t hash_div)
 {
 	struct timespec abstime = {};
 	struct timeval now;
@@ -2197,9 +2199,10 @@ bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce)
 
 static void *miner_thread(void *userdata)
 {
+	struct work work __attribute__((aligned(128)));
 	struct thr_info *mythr = userdata;
 	const int thr_id = mythr->id;
-	uint32_t max_nonce = 0xffffff;
+	uint32_t max_nonce = 0xffffff, total_hashes = 0;
 	unsigned long hashes_done = max_nonce;
 	bool needs_work = true;
 	/* Try to cycle approximately 5 times before each log update */
@@ -2208,6 +2211,7 @@ static void *miner_thread(void *userdata)
 	unsigned const int request_interval = opt_scantime * 2 / 3 ? : 1;
 	unsigned const long request_nonce = MAXTHREADS / 3 * 2;
 	bool requested = true;
+	uint32_t hash_div = 1;
 
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 
@@ -2222,8 +2226,10 @@ static void *miner_thread(void *userdata)
 	if (!(opt_n_threads % num_processors))
 		affine_to_cpu(thr_id - gpu_threads, dev_from_id(thr_id));
 
+	/* Invalidate pool so it fails can_roll() test */
+	work.pool = NULL;
+
 	while (1) {
-		struct work work __attribute__((aligned(128)));
 		struct timeval tv_workstart, tv_start, tv_end, diff;
 		uint64_t max64;
 		bool rc;
@@ -2231,15 +2237,16 @@ static void *miner_thread(void *userdata)
 		if (needs_work) {
 			gettimeofday(&tv_workstart, NULL);
 			/* obtain new work from internal workio thread */
-			if (unlikely(!get_work(&work, requested, mythr, thr_id))) {
+			if (unlikely(!get_work(&work, requested, mythr, thr_id, hash_div))) {
 				applog(LOG_ERR, "work retrieval failed, exiting "
 					"mining thread %d", thr_id);
 				goto out;
 			}
 			mythr->cgpu->getworks++;
 			needs_work = requested = false;
-			work.blk.nonce = 0;
-			max_nonce = hashes_done;
+			total_hashes = 0;
+			work.blk.nonce = work.res_nonce;;
+			max_nonce = work.blk.nonce + hashes_done;
 		}
 		hashes_done = 0;
 		gettimeofday(&tv_start, NULL);
@@ -2326,6 +2333,7 @@ static void *miner_thread(void *userdata)
 
 		hashes_done -= work.blk.nonce;
 		hashmeter(thr_id, &diff, hashes_done);
+		total_hashes += hashes_done;
 		work.blk.nonce += hashes_done;
 
 		/* adjust max_nonce to meet target cycle time */
@@ -2360,9 +2368,11 @@ static void *miner_thread(void *userdata)
 			requested = true;
 		}
 
-		if (diff.tv_sec > opt_scantime || work_restart[thr_id].restart ||
-			work.blk.nonce >= MAXTHREADS - hashes_done ||
-			stale_work(&work))
+		if (diff.tv_sec > opt_scantime) {
+			hash_div = (MAXTHREADS / total_hashes) ? : 1;
+			needs_work = true;
+		} else if (work_restart[thr_id].restart || stale_work(&work) ||
+			work.blk.nonce >= MAXTHREADS - hashes_done)
 				needs_work = true;
 	}
 
@@ -2428,9 +2438,13 @@ static inline cl_int queue_kernel_parameters(_clState *clState, dev_blk_ctx *blk
 }
 
 static void set_threads_hashes(unsigned int vectors, unsigned int *threads,
-			       unsigned int *hashes, size_t *globalThreads)
+			       unsigned int *hashes, size_t *globalThreads,
+			       unsigned int minthreads)
 {
-	*globalThreads = *threads = 1 << (15 + scan_intensity);
+	*threads = 1 << (15 + scan_intensity);
+	if (*threads < minthreads)
+		*threads = minthreads;
+	*globalThreads = *threads;
 	*hashes = *threads * vectors;
 }
 
@@ -2452,15 +2466,16 @@ static void *gpuminer_thread(void *userdata)
 	const cl_kernel *kernel = &clState->kernel;
 
 	struct work *work = malloc(sizeof(struct work));
-	unsigned int threads = 1 << (15 + scan_intensity);
+	unsigned int threads;
 	unsigned const int vectors = clState->preferred_vwidth;
-	unsigned int hashes = threads * vectors;
+	unsigned int hashes;
 	unsigned int hashes_done = 0;
 
 	/* Request the next work item at 2/3 of the scantime */
 	unsigned const int request_interval = opt_scantime * 2 / 3 ? : 1;
 	unsigned const long request_nonce = MAXTHREADS / 3 * 2;
 	bool requested = true;
+	uint32_t total_hashes = 0, hash_div = 1;
 
 	if (opt_dynamic) {
 		/* Minimise impact on desktop if we want dynamic mode */
@@ -2479,18 +2494,22 @@ static void *gpuminer_thread(void *userdata)
 	}
 
 	gettimeofday(&tv_start, NULL);
-	globalThreads[0] = threads;
 	localThreads[0] = clState->work_size;
+	set_threads_hashes(vectors, &threads, &hashes, &globalThreads[0],
+			   localThreads[0]);
+
 	diff.tv_sec = 0;
 	gettimeofday(&tv_end, NULL);
 
+	work->pool = NULL;
+
 	status = clEnqueueWriteBuffer(clState->commandQueue, clState->outputBuffer, CL_TRUE, 0,
 			BUFFERSIZE, blank_res, 0, NULL, NULL);
 	if (unlikely(status != CL_SUCCESS))
 		{ applog(LOG_ERR, "Error: clEnqueueWriteBuffer failed."); goto out; }
 	gettimeofday(&tv_workstart, NULL);
 	/* obtain new work from internal workio thread */
-	if (unlikely(!get_work(work, requested, mythr, thr_id))) {
+	if (unlikely(!get_work(work, requested, mythr, thr_id, hash_div))) {
 		applog(LOG_ERR, "work retrieval failed, exiting "
 			"gpu mining thread %d", thr_id);
 		goto out;
@@ -2517,15 +2536,14 @@ static void *gpuminer_thread(void *userdata)
 			 * increase intensity when the system is idle, unless
 			 * dynamic is disabled. */
 			if (gpu_ms_average > 7) {
-				if (scan_intensity > 0)
+				if (scan_intensity > -10)
 					scan_intensity--;
-				set_threads_hashes(vectors, &threads, &hashes, globalThreads);
 			} else if (gpu_ms_average < 3) {
-				if (scan_intensity < 14)
+				if (scan_intensity < 10)
 					scan_intensity++;
-				set_threads_hashes(vectors, &threads, &hashes, globalThreads);
 			}
 		}
+		set_threads_hashes(vectors, &threads, &hashes, globalThreads, localThreads[0]);
 
 		if (diff.tv_sec > opt_scantime ||
 		    work->blk.nonce >= MAXTHREADS - hashes ||
@@ -2540,7 +2558,7 @@ static void *gpuminer_thread(void *userdata)
 
 			gettimeofday(&tv_workstart, NULL);
 			/* obtain new work from internal workio thread */
-			if (unlikely(!get_work(work, requested, mythr, thr_id))) {
+			if (unlikely(!get_work(work, requested, mythr, thr_id, hash_div))) {
 				applog(LOG_ERR, "work retrieval failed, exiting "
 					"gpu mining thread %d", thr_id);
 				goto out;
@@ -2588,6 +2606,7 @@ static void *gpuminer_thread(void *userdata)
 		gettimeofday(&tv_end, NULL);
 		timeval_subtract(&diff, &tv_end, &tv_start);
 		hashes_done += hashes;
+		total_hashes += hashes;
 		work->blk.nonce += hashes;
 		if (diff.tv_usec > 500000)
 			diff.tv_sec++;
@@ -2598,12 +2617,16 @@ static void *gpuminer_thread(void *userdata)
 		}
 
 		timeval_subtract(&diff, &tv_end, &tv_workstart);
-		if (!requested && (diff.tv_sec > request_interval || work->blk.nonce > request_nonce)) {
-			if (unlikely(!queue_request())) {
-				applog(LOG_ERR, "Failed to queue_request in gpuminer_thread %d", thr_id);
-				goto out;
+		if (!requested) {
+			if (diff.tv_sec > request_interval)
+				hash_div = (MAXTHREADS / total_hashes) ? : 1;
+			if (diff.tv_sec > request_interval || work->blk.nonce > request_nonce) {
+				if (unlikely(!queue_request())) {
+					applog(LOG_ERR, "Failed to queue_request in gpuminer_thread %d", thr_id);
+					goto out;
+				}
+				requested = true;
 			}
-			requested = true;
 		}
 	}
 out:
@@ -3325,10 +3348,6 @@ int main (int argc, char *argv[])
 		quit(1, "stage thread create failed");
 	pthread_detach(*thr->pth);
 
-	/* Flag the work as ready forcing the mining threads to wait till we
-	 * actually put something into the queue */
-	inc_staged(current_pool(), mining_threads, true);
-
 	/* Create a unique get work queue */
 	getq = tq_new();
 	if (!getq)
@@ -3435,13 +3454,6 @@ int main (int argc, char *argv[])
 	if (thr_info_create(thr, NULL, watchdog_thread, NULL))
 		quit(1, "wakeup thread create failed");
 
-	/* Restart count as it will be wrong till all threads are started */
-	pthread_mutex_lock(&hash_lock);
-	gettimeofday(&total_tv_start, NULL);
-	gettimeofday(&total_tv_end, NULL);
-	total_mhashes_done = 0;
-	pthread_mutex_unlock(&hash_lock);
-
 	/* Now that everything's ready put enough work in the queue */
 	for (i = 0; i < opt_queue + mining_threads; i++) {
 		if (unlikely(!queue_request()))