Browse Source

Bugfix: opencl: Defer initial intensity assignment until init, so opt_scrypt has a chance to be set

Luke Dashjr 12 years ago
parent
commit
4c385c2af5
3 changed files with 33 additions and 14 deletions
  1. 24 11
      driver-opencl.c
  2. 2 1
      driver-opencl.h
  3. 7 2
      ocl.c

+ 24 - 11
driver-opencl.c

@@ -562,17 +562,15 @@ unsigned long xintensity_to_oclthreads(const double xintensity, const cl_uint ma
 	return xintensity * max_compute_units * 0x40;
 }
 
-static
-bool _set_intensity(struct cgpu_info * const cgpu, const char *_val)
+bool opencl_set_intensity_from_str(struct cgpu_info * const cgpu, const char *_val)
 {
 	struct opencl_device_data * const data = cgpu->device_data;
-	
-	data->dynamic = false;
-	data->_init_xintensity = 0;
+	unsigned long oclthreads = 0;
+	bool dynamic = false;
 	
 	if (!strncasecmp(_val, "d", 1))
 	{
-		data->dynamic = true;
+		dynamic = true;
 		++_val;
 	}
 	
@@ -582,15 +580,15 @@ bool _set_intensity(struct cgpu_info * const cgpu, const char *_val)
 		if (v < 1 || v > 9999)
 			return false;
 		
-		if (cgpu->thr)
+		// thr etc won't be initialised here, so avoid dereferencing it
+		if (data->oclthreads)
 		{
 			struct thr_info * const thr = cgpu->thr[0];
 			const int thr_id = thr->id;
 			_clState * const clState = clStates[thr_id];
 			
-			data->oclthreads = xintensity_to_oclthreads(v, clState->max_compute_units);
+			oclthreads = xintensity_to_oclthreads(v, clState->max_compute_units);
 		}
-		data->_init_xintensity = v;
 	}
 	else
 	if (isdigit(_val[0]))
@@ -598,11 +596,26 @@ bool _set_intensity(struct cgpu_info * const cgpu, const char *_val)
 		const double v = atof(_val);
 		if (v < MIN_INTENSITY || v > MAX_GPU_INTENSITY)
 			return false;
-		data->oclthreads = intensity_to_oclthreads(v, !opt_scrypt);
+		oclthreads = intensity_to_oclthreads(v, !opt_scrypt);
+	}
+	
+	// Make actual assignments after we know the values are valid
+	data->dynamic = dynamic;
+	if (data->oclthreads)
+	{
+		data->oclthreads = oclthreads;
+		pause_dynamic_threads(cgpu->device_id);
 	}
-	pause_dynamic_threads(cgpu->device_id);
+	else
+	{
+		if (unlikely(data->_init_intensity))
+			free(data->_init_intensity);
+		data->_init_intensity = strdup(_val);
+	}
+	
 	return true;
 }
+#define _set_intensity opencl_set_intensity_from_str
 _SET_INTERFACE(intensity)
 const char *set_intensity(char *arg)
 {

+ 2 - 1
driver-opencl.h

@@ -15,7 +15,7 @@ struct opencl_device_data {
 	int virtual_gpu;
 	int virtual_adl;
 	unsigned long oclthreads;
-	double _init_xintensity;
+	char *_init_intensity;
 	bool dynamic;
 	
 	cl_uint vwidth;
@@ -53,6 +53,7 @@ struct opencl_device_data {
 extern double oclthreads_to_intensity(unsigned long oclthreads, bool is_sha256d);
 extern unsigned long intensity_to_oclthreads(double intensity, bool is_sha256d);
 extern unsigned long xintensity_to_oclthreads(double xintensity, cl_uint max_compute_units);
+extern bool opencl_set_intensity_from_str(struct cgpu_info *, const char *newvalue);
 
 struct opencl_work_data {
 	cl_uint ctx_a; cl_uint ctx_b; cl_uint ctx_c; cl_uint ctx_d;

+ 7 - 2
ocl.c

@@ -557,8 +557,13 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize)
 		applog(LOG_ERR, "Error %d: Failed to clGetDeviceInfo when trying to get CL_DEVICE_MAX_COMPUTE_UNITS", status);
 		return NULL;
 	}
-	if (data->_init_xintensity)
-		data->oclthreads = xintensity_to_oclthreads(data->_init_xintensity, clState->max_compute_units);
+	if (data->_init_intensity)
+	{
+		data->oclthreads = 1;  // Needed to ensure we don't just try to re-save the string (which would free before strduping and segfault anyway)
+		opencl_set_intensity_from_str(cgpu, data->_init_intensity);
+	}
+	else
+		data->oclthreads = intensity_to_oclthreads(MIN_INTENSITY, !opt_scrypt);
 	applog(LOG_DEBUG, "Max compute units reported %u", (unsigned)clState->max_compute_units);
 	
 	status = clGetDeviceInfo(devices[gpu], CL_DEVICE_MAX_MEM_ALLOC_SIZE , sizeof(cl_ulong), (void *)&data->max_alloc, NULL);