Browse Source

Refactor device disable/enable logic so that drv.thread_{disable,enable} actually get called

Luke Dashjr 12 years ago
parent
commit
1177917bf2
4 changed files with 45 additions and 27 deletions
  1. 28 23
      deviceapi.c
  2. 3 1
      driver-bitforce.c
  3. 13 2
      miner.c
  4. 1 1
      miner.h

+ 28 - 23
deviceapi.c

@@ -168,6 +168,9 @@ void minerloop_scanhash(struct thr_info *mythr)
 	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
 #endif
 	
+	if (cgpu->deven != DEV_ENABLED)
+		mt_disable(mythr);
+	
 	while (likely(!cgpu->shutdown)) {
 		mythr->work_restart = false;
 		request_work(mythr);
@@ -284,13 +287,16 @@ void job_results_fetched(struct thr_info *mythr)
 	if (mythr->_proceed_with_new_job)
 		do_job_start(mythr);
 	else
-	if (likely(mythr->prev_work))
 	{
-		struct timeval tv_now;
-		
-		timer_set_now(&tv_now);
-		
-		do_process_results(mythr, &tv_now, mythr->prev_work, true);
+		if (likely(mythr->prev_work))
+		{
+			struct timeval tv_now;
+			
+			timer_set_now(&tv_now);
+			
+			do_process_results(mythr, &tv_now, mythr->prev_work, true);
+		}
+		mt_disable_start(mythr);
 	}
 }
 
@@ -460,15 +466,20 @@ void minerloop_async(struct thr_info *mythr)
 			}
 			else  // ! should_be_running
 			{
-				if (unlikely(is_running && !mythr->_job_transition_in_progress))
+				if (unlikely((is_running || !thr->_mt_disable_called) && !mythr->_job_transition_in_progress))
 				{
 disabled: ;
-					mythr->tv_morework.tv_sec = -1;
-					if (mythr->busy_state != TBS_GETTING_RESULTS)
-						do_get_results(mythr, false);
-					else
-						// Avoid starting job when pending result fetch completes
-						mythr->_proceed_with_new_job = false;
+					timer_unset(&mythr->tv_morework);
+					if (is_running)
+					{
+						if (mythr->busy_state != TBS_GETTING_RESULTS)
+							do_get_results(mythr, false);
+						else
+							// Avoid starting job when pending result fetch completes
+							mythr->_proceed_with_new_job = false;
+					}
+					else  // !thr->_mt_disable_called
+						mt_disable_start(mythr);
 				}
 			}
 			
@@ -536,11 +547,8 @@ void minerloop_queue(struct thr_info *thr)
 redo:
 			if (should_be_running)
 			{
-				if (unlikely(!mythr->_last_sbr_state))
-				{
+				if (unlikely(mythr->_mt_disable_called))
 					mt_disable_finish(mythr);
-					mythr->_last_sbr_state = should_be_running;
-				}
 				
 				if (unlikely(mythr->work_restart))
 				{
@@ -568,10 +576,10 @@ redo:
 				}
 			}
 			else
-			if (unlikely(mythr->_last_sbr_state))
+			if (unlikely(!mythr->_mt_disable_called))
 			{
-				mythr->_last_sbr_state = should_be_running;
 				do_queue_flush(mythr);
+				mt_disable_start(mythr);
 			}
 			
 			if (timer_passed(&mythr->tv_poll, &tv_now))
@@ -615,13 +623,10 @@ void *miner_thread(void *userdata)
 		goto out;
 	}
 
-	if (cgpu->deven != DEV_ENABLED)
-		mt_disable_start(mythr);
-	
 	thread_reportout(mythr);
 	applog(LOG_DEBUG, "Popping ping in miner thread");
 	notifier_read(mythr->notifier);  // Wait for a notification to start
-
+	
 	cgtime(&cgpu->cgminer_stats.start_tv);
 	if (drv->minerloop)
 		drv->minerloop(mythr);

+ 3 - 1
driver-bitforce.c

@@ -2055,7 +2055,9 @@ static void bitforce_queue_thread_deven(struct thr_info *thr)
 	struct bitforce_data *data = bitforce->device_data;
 	struct thr_info *thisthr;
 	
-	for (thisbf = bitforce; thisbf && thisbf->device_data == data; thisbf = thisbf->next_proc)
+	for (thisbf = bitforce->device; thisbf && thisbf->device_data != data; thisbf = thisbf->next_proc)
+	{}
+	for ( ; thisbf && thisbf->device_data == data; thisbf = thisbf->next_proc)
 	{
 		thisthr = bitforce->thr[0];
 		

+ 13 - 2
miner.c

@@ -8439,6 +8439,7 @@ void __thr_being_msg(int prio, struct thr_info *thr, const char *being)
 		applog(prio, "%"PRIpreprv" %s", proc->proc_repr, being);
 }
 
+// Called by asynchronous minerloops, when they find their processor should be disabled
 void mt_disable_start(struct thr_info *mythr)
 {
 	struct cgpu_info *cgpu = mythr->cgpu;
@@ -8456,6 +8457,7 @@ void mt_disable_start(struct thr_info *mythr)
 	__thr_being_msg(LOG_WARNING, mythr, "being disabled");
 	mythr->rolling = mythr->cgpu->rolling = 0;
 	thread_reportout(mythr);
+	mythr->_mt_disable_called = true;
 }
 
 /* Create a hashtable of work items for devices with a queue. The device
@@ -8606,6 +8608,9 @@ void hash_queued_work(struct thr_info *mythr)
 	const int thr_id = mythr->id;
 	int64_t hashes_done = 0;
 
+	if (unlikely(cgpu->deven != DEV_ENABLED))
+		mt_disable(mythr);
+	
 	while (likely(!cgpu->shutdown)) {
 		struct timeval diff;
 		int64_t hashes;
@@ -8644,6 +8649,7 @@ void hash_queued_work(struct thr_info *mythr)
 	// cgpu->deven = DEV_DISABLED; set in miner_thread
 }
 
+// Called by minerloop, when it is re-enabling a processor
 void mt_disable_finish(struct thr_info *mythr)
 {
 	struct device_drv *drv = mythr->cgpu->drv;
@@ -8652,15 +8658,19 @@ void mt_disable_finish(struct thr_info *mythr)
 	__thr_being_msg(LOG_WARNING, mythr, "being re-enabled");
 	if (drv->thread_enable)
 		drv->thread_enable(mythr);
+	mythr->_mt_disable_called = false;
 }
 
+// Called by synchronous minerloops, when they find their processor should be disabled
+// Calls mt_disable_start, waits until it's re-enabled, then calls mt_disable_finish
 void mt_disable(struct thr_info *mythr)
 {
+	const struct cgpu_info * const cgpu = mythr->cgpu;
 	mt_disable_start(mythr);
 	applog(LOG_DEBUG, "Waiting for wakeup notification in miner thread");
 	do {
 		notifier_read(mythr->notifier);
-	} while (mythr->pause);
+	} while (mythr->pause || cgpu->deven != DEV_ENABLED);
 	mt_disable_finish(mythr);
 }
 
@@ -9935,7 +9945,6 @@ void allocate_cgpu(struct cgpu_info *cgpu, unsigned int *kp)
 		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;
@@ -9978,6 +9987,8 @@ void start_cgpu(struct cgpu_info *cgpu)
 
 		if (unlikely(thr_info_create(thr, NULL, miner_thread, thr)))
 			quit(1, "thread %d create failed", thr->id);
+		
+		notifier_wake(thr->notifier);
 	}
 	if (cgpu->deven == DEV_ENABLED)
 		proc_enable(cgpu);

+ 1 - 1
miner.h

@@ -627,6 +627,7 @@ struct thr_info {
 	struct work *work;
 	struct work *next_work;
 	enum thr_busy_state busy_state;
+	bool _mt_disable_called;
 	struct timeval tv_morework;
 	struct work *results_work;
 	bool _job_transition_in_progress;
@@ -643,7 +644,6 @@ struct thr_info {
 	// Used by minerloop_queue
 	struct work *work_list;
 	bool queue_full;
-	bool _last_sbr_state;
 
 	bool	work_restart;
 	notifier_t work_restart_notifier;