Browse Source

x6500: Make mutex management cleaner by blocking device select loop during idle get_stats

Luke Dashjr 13 years ago
parent
commit
bf0a6581a0
3 changed files with 27 additions and 16 deletions
  1. 15 0
      deviceapi.c
  2. 10 16
      driver-x6500.c
  3. 2 0
      miner.h

+ 15 - 0
deviceapi.c

@@ -390,8 +390,23 @@ djp: ;
 		maxfd = mythr->notifier[0];
 		FD_SET(mythr->work_restart_notifier[0], &rfds);
 		set_maxfd(&maxfd, mythr->work_restart_notifier[0]);
+		if (thr->mutex_request[1] != INVSOCK)
+		{
+			FD_SET(thr->mutex_request[0], &rfds);
+			set_maxfd(&maxfd, thr->mutex_request[0]);
+		}
 		if (select(maxfd + 1, &rfds, NULL, NULL, select_timeout(&tv_timeout, &tv_now)) < 0)
 			continue;
+		if (thr->mutex_request[1] != INVSOCK && FD_ISSET(thr->mutex_request[0], &rfds))
+		{
+			// FIXME: This can only handle one request at a time!
+			pthread_mutex_t *mutexp = &cgpu->device_mutex;
+			notifier_read(thr->mutex_request);
+			mutex_lock(mutexp);
+			pthread_cond_signal(&cgpu->device_cond);
+			pthread_cond_wait(&cgpu->device_cond, mutexp);
+			mutex_unlock(mutexp);
+		}
 		if (FD_ISSET(mythr->notifier[0], &rfds)) {
 			notifier_read(mythr->notifier);
 		}

+ 10 - 16
driver-x6500.c

@@ -337,6 +337,10 @@ static bool x6500_thread_init(struct thr_info *thr)
 	struct cgpu_info *x6500 = thr->cgpu;
 	struct ft232r_device_handle *ftdi = x6500->device_ft232r;
 
+	// Setup mutex request based on notifier and pthread cond
+	notifier_init(thr->mutex_request);
+	pthread_cond_init(&x6500->device_cond, NULL);
+	
 	for ( ; x6500; x6500 = x6500->next_proc)
 	{
 		thr = x6500->thr[0];
@@ -526,11 +530,14 @@ static bool x6500_get_stats(struct cgpu_info *x6500)
 {
 	float hottest = 0;
 	if (x6500_all_idle(x6500)) {
+		struct cgpu_info *cgpu = x6500->device;
 		// Getting temperature more efficiently while running
-		pthread_mutex_t *mutexp = &x6500->device->device_mutex;
+		pthread_mutex_t *mutexp = &cgpu->device_mutex;
 		mutex_lock(mutexp);
-		if (x6500_all_idle(x6500))
-			x6500_get_temperature(x6500);
+		notifier_wake(cgpu->thr[0]->mutex_request);
+		pthread_cond_wait(&cgpu->device_cond, mutexp);
+		x6500_get_temperature(x6500);
+		pthread_cond_signal(&cgpu->device_cond);
 		mutex_unlock(mutexp);
 	}
 
@@ -627,13 +634,6 @@ bool x6500_job_prepare(struct thr_info *thr, struct work *work, __maybe_unused u
 	struct cgpu_info *x6500 = thr->cgpu;
 	struct x6500_fpga_data *fpga = thr->cgpu_data;
 	struct jtag_port *jp = &fpga->jtag;
-
-	if (x6500_all_idle(x6500))
-	{
-		// Neither FPGA is running, so make sure we're not doing a temperature check
-		pthread_mutex_t *mutexp = &x6500->device->device_mutex;
-		mutex_lock(mutexp);
-	}
 	
 	for (int i = 1, j = 0; i < 9; ++i, j += 4)
 		x6500_set_register(jp, i, fromlebytes(work->midstate, j));
@@ -680,12 +680,6 @@ void x6500_job_start(struct thr_info *thr)
 		calc_hashes(thr, &tv_now);
 	fpga->hashes_left = 0x100000000;
 	mt_job_transition(thr);
-
-	if (x6500_all_idle(x6500))
-	{
-		pthread_mutex_t *mutexp = &x6500->device->device_mutex;
-		mutex_unlock(mutexp);
-	}
 	
 	if (opt_debug) {
 		char *xdata = bin2hex(thr->work->data, 80);

+ 2 - 0
miner.h

@@ -439,6 +439,7 @@ struct cgpu_info {
 #endif
 	void *cgpu_data;
 	pthread_mutex_t		device_mutex;
+	pthread_cond_t	device_cond;
 
 	enum dev_enable deven;
 	int accepted;
@@ -568,6 +569,7 @@ struct thr_info {
 	notifier_t notifier;
 	bool starting_next_work;
 	uint32_t _max_nonce;
+	notifier_t mutex_request;
 
 	bool	work_restart;
 	notifier_t work_restart_notifier;