Browse Source

Implement minerloop_queue for devices that process work items too fast to keep track of which one they're currently working on

Luke Dashjr 13 years ago
parent
commit
67638b8416
4 changed files with 105 additions and 4 deletions
  1. 91 0
      deviceapi.c
  2. 2 0
      deviceapi.h
  3. 1 0
      miner.c
  4. 11 4
      miner.h

+ 91 - 0
deviceapi.c

@@ -449,6 +449,97 @@ defer_events:
 	}
 }
 
+static
+void do_queue_flush(struct thr_info *mythr)
+{
+	struct cgpu_info *proc = mythr->cgpu;
+	const struct device_api *api = proc->api;
+	
+	api->queue_flush(mythr);
+	if (mythr->next_work)
+	{
+		free_work(mythr->next_work);
+		mythr->next_work = NULL;
+	}
+}
+
+void minerloop_queue(struct thr_info *thr)
+{
+	struct thr_info *mythr;
+	struct cgpu_info *cgpu = thr->cgpu;
+	const struct device_api *api = cgpu->api;
+	struct timeval tv_now;
+	struct timeval tv_timeout;
+	struct cgpu_info *proc;
+	bool should_be_running;
+	struct work *work;
+	
+	if (thr->work_restart_notifier[1] == -1)
+		notifier_init(thr->work_restart_notifier);
+	
+	while (1) {
+		tv_timeout.tv_sec = -1;
+		gettimeofday(&tv_now, NULL);
+		for (proc = cgpu; proc; proc = proc->next_proc)
+		{
+			mythr = proc->thr[0];
+			
+			should_be_running = (proc->deven == DEV_ENABLED && !mythr->pause);
+redo:
+			if (should_be_running)
+			{
+				if (unlikely(!mythr->_last_sbr_state))
+				{
+					mt_disable_finish(mythr);
+					mythr->_last_sbr_state = should_be_running;
+				}
+				
+				if (unlikely(mythr->work_restart))
+				{
+					mythr->work_restart = false;
+					do_queue_flush(mythr);
+				}
+				
+				while (!mythr->queue_full)
+				{
+					if (mythr->next_work)
+					{
+						work = mythr->next_work;
+						mythr->next_work = NULL;
+					}
+					else
+					{
+						request_work(mythr);
+						// FIXME: Allow get_work to return NULL to retry on notification
+						work = get_and_prepare_work(mythr);
+					}
+					if (!work)
+						break;
+					if (!api->queue_append(mythr, work))
+						mythr->next_work = work;
+				}
+			}
+			else
+			if (unlikely(mythr->_last_sbr_state))
+			{
+				mythr->_last_sbr_state = should_be_running;
+				do_queue_flush(mythr);
+			}
+			
+			if (timer_passed(&mythr->tv_poll, &tv_now))
+				api->poll(mythr);
+			
+			should_be_running = (proc->deven == DEV_ENABLED && !mythr->pause);
+			if (should_be_running && !mythr->queue_full)
+				goto redo;
+			
+			reduce_timeout_to(&tv_timeout, &mythr->tv_poll);
+		}
+		
+		do_notifier_select(thr, &tv_timeout);
+	}
+}
+
 void *miner_thread(void *userdata)
 {
 	struct thr_info *mythr = userdata;

+ 2 - 0
deviceapi.h

@@ -28,6 +28,8 @@ extern void job_start_abort(struct thr_info *, bool failure);
 extern bool do_process_results(struct thr_info *, struct timeval *tvp_now, struct work *, bool stopping);
 extern void minerloop_async(struct thr_info *);
 
+extern void minerloop_queue(struct thr_info *);
+
 extern void *miner_thread(void *);
 
 #endif

+ 1 - 0
miner.c

@@ -8357,6 +8357,7 @@ begin_bench:
 			thr->mutex_request[1] = INVSOCK;
 			thr->_job_transition_in_progress = true;
 			timerclear(&thr->tv_morework);
+			thr->_last_sbr_state = true;
 
 			thr->scanhash_working = true;
 			thr->hashes_done = 0;

+ 11 - 4
miner.h

@@ -297,16 +297,18 @@ struct device_api {
 	void (*thread_shutdown)(struct thr_info *);
 	void (*thread_enable)(struct thr_info *);
 
-	// === Implemented by minerloop_async ===
-
-	// Can be used per-thread or per-processor
+	// Can be used per-thread or per-processor (only with minerloop async or queue!)
 	void (*poll)(struct thr_info *);
 
-	// Job-specific functions (only with minerloop_async!)
+	// === Implemented by minerloop_async ===
 	bool (*job_prepare)(struct thr_info*, struct work*, uint64_t);
 	void (*job_start)(struct thr_info*);
 	void (*job_get_results)(struct thr_info*, struct work*);
 	int64_t (*job_process_results)(struct thr_info*, struct work*, bool stopping);
+
+	// === Implemented by minerloop_queue ===
+	bool (*queue_append)(struct thr_info *, struct work *);
+	void (*queue_flush)(struct thr_info *);
 };
 
 enum dev_enable {
@@ -579,6 +581,11 @@ struct thr_info {
 	uint32_t _max_nonce;
 	notifier_t mutex_request;
 
+	// Used by minerloop_queue
+	struct list_head work_list;
+	bool queue_full;
+	bool _last_sbr_state;
+
 	bool	work_restart;
 	notifier_t work_restart_notifier;
 };