Browse Source

Bugfix: opencl: Safely handle work->device_data across work copies and cleans

Luke Dashjr 12 years ago
parent
commit
1fa13a27bd
3 changed files with 34 additions and 5 deletions
  1. 24 3
      driver-opencl.c
  2. 5 1
      miner.c
  3. 5 1
      miner.h

+ 24 - 3
driver-opencl.c

@@ -853,12 +853,33 @@ static _clState *clStates[MAX_GPUDEVICES];
 #define CL_SET_ARG(var) status |= clSetKernelArg(*kernel, num++, sizeof(var), (void *)&var)
 #define CL_SET_VARG(args, var) status |= clSetKernelArg(*kernel, num++, args * sizeof(uint), (void *)var)
 
+static
+void *_opencl_work_data_dup(struct work * const work)
+{
+	struct opencl_work_data *p = malloc(sizeof(*p));
+	memcpy(p, work->device_data, sizeof(*p));
+#ifdef USE_SCRYPT
+	p->work = work;
+#endif
+	return p;
+}
+
+static
+void _opencl_work_data_free(struct work * const work)
+{
+	free(work->device_data);
+}
+
 static
 struct opencl_work_data *_opencl_work_data(struct work * const work)
 {
-	if (work->device_data)
-		return work->device_data;
-	return (work->device_data = calloc(1, sizeof(struct opencl_work_data)));
+	if (!work->device_data)
+	{
+		work->device_data = calloc(1, sizeof(struct opencl_work_data));
+		work->device_data_dup_func = _opencl_work_data_dup;
+		work->device_data_free_func = _opencl_work_data_free;
+	}
+	return work->device_data;
 }
 
 static

+ 5 - 1
miner.c

@@ -2701,7 +2701,8 @@ void clean_work(struct work *work)
 	free(work->job_id);
 	bytes_free(&work->nonce2);
 	free(work->nonce1);
-	free(work->device_data);
+	if (work->device_data_free_func)
+		work->device_data_free_func(work);
 
 	if (work->tmpl) {
 		struct pool *pool = work->pool;
@@ -5176,6 +5177,9 @@ static void _copy_work(struct work *work, const struct work *base_work, int noff
 		ntime += noffset;
 		*work_ntime = htobe32(ntime);
 	}
+	
+	if (work->device_data_dup_func)
+		work->device_data = work->device_data_dup_func(work);
 }
 
 /* Generates a copy of an existing work struct, creating fresh heap allocations

+ 5 - 1
miner.h

@@ -1306,9 +1306,13 @@ struct work {
 	unsigned char	work_restart_id;
 	int		id;
 	int		device_id;
-	void *device_data;
 	UT_hash_handle hh;
 	
+	// Please don't use this if it's at all possible, I'd like to get rid of it eventually.
+	void *device_data;
+	void *(*device_data_dup_func)(struct work *);
+	void (*device_data_free_func)(struct work *);
+	
 	double		work_difficulty;
 	float		nonce_diff;