Commit cf30053793b128546c7e6b7d508e9f7a266c80cb

Kano 2013-08-12T08:35:29

Merge remote-tracking branch 'conman/master'

diff --git a/cgminer.c b/cgminer.c
index f22a44b..fc259c6 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -1565,33 +1565,6 @@ void free_work(struct work *work)
 	free(work);
 }
 
-/* Generate a GBT coinbase from the existing GBT variables stored. Must be
- * entered under gbt_lock */
-static void __build_gbt_coinbase(struct pool *pool)
-{
-	unsigned char *coinbase;
-	int cbt_len, orig_len;
-	uint8_t *extra_len;
-	size_t cal_len;
-
-	cbt_len = strlen(pool->coinbasetxn) / 2;
-	pool->coinbase_len = cbt_len + 4;
-	/* We add 4 bytes of extra data corresponding to nonce2 of stratum */
-	cal_len = pool->coinbase_len + 1;
-	align_len(&cal_len);
-	coinbase = calloc(cal_len, 1);
-	hex2bin(coinbase, pool->coinbasetxn, 42);
-	extra_len = (uint8_t *)(coinbase + 41);
-	orig_len = *extra_len;
-	hex2bin(coinbase + 42, pool->coinbasetxn + 84, orig_len);
-	memcpy(coinbase + 42 + orig_len, &pool->nonce2, 4);
-	*extra_len += 4;
-	hex2bin(coinbase + 42 + *extra_len, pool->coinbasetxn + 84 + (orig_len * 2), cbt_len - orig_len - 42);
-	pool->nonce2++;
-	free(pool->gbt_coinbase);
-	pool->gbt_coinbase = coinbase;
-}
-
 static void gen_hash(unsigned char *data, unsigned char *hash, int len);
 
 /* Process transactions with GBT by storing the binary value of the first
@@ -1724,9 +1697,10 @@ static void gen_gbt_work(struct pool *pool, struct work *work)
 	if (now.tv_sec - pool->tv_lastwork.tv_sec > 60)
 		update_gbt(pool);
 
-	cg_ilock(&pool->gbt_lock);
-	__build_gbt_coinbase(pool);
-	cg_dlock(&pool->gbt_lock);
+	cg_wlock(&pool->gbt_lock);
+	memcpy(pool->gbt_coinbase + 42 + pool->orig_len, &pool->nonce2, 4);
+	pool->nonce2++;
+	cg_dwlock(&pool->gbt_lock);
 	merkleroot = __gbt_merkleroot(pool);
 
 	memcpy(work->data, &pool->gbt_version, 4);
@@ -1784,6 +1758,9 @@ static bool gbt_decode(struct pool *pool, json_t *res_val)
 	bool submitold;
 	const char *bits;
 	const char *workid;
+	int cbt_len;
+	uint8_t *extra_len;
+	size_t cal_len;
 
 	previousblockhash = json_string_value(json_object_get(res_val, "previousblockhash"));
 	target = json_string_value(json_object_get(res_val, "target"));
@@ -1817,6 +1794,23 @@ static bool gbt_decode(struct pool *pool, json_t *res_val)
 	cg_wlock(&pool->gbt_lock);
 	free(pool->coinbasetxn);
 	pool->coinbasetxn = strdup(coinbasetxn);
+	cbt_len = strlen(pool->coinbasetxn) / 2;
+	pool->coinbase_len = cbt_len + 4;
+	/* We add 4 bytes of extra data corresponding to nonce2 of stratum */
+	cal_len = pool->coinbase_len + 1;
+	align_len(&cal_len);
+	free(pool->gbt_coinbase);
+	pool->gbt_coinbase = calloc(cal_len, 1);
+	if (unlikely(!pool->gbt_coinbase))
+		quit(1, "Failed to calloc pool gbt_coinbase in gbt_decode");
+	hex2bin(pool->gbt_coinbase, pool->coinbasetxn, 42);
+	extra_len = (uint8_t *)(pool->gbt_coinbase + 41);
+	pool->orig_len = *extra_len;
+	hex2bin(pool->gbt_coinbase + 42, pool->coinbasetxn + 84, pool->orig_len);
+	*extra_len += 4;
+	hex2bin(pool->gbt_coinbase + 42 + *extra_len, pool->coinbasetxn + 84 + (pool->orig_len * 2),
+		cbt_len - pool->orig_len - 42);
+
 	free(pool->longpollid);
 	pool->longpollid = strdup(longpollid);
 	free(pool->gbt_workid);
@@ -5597,24 +5591,23 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
 	size_t alloc_len;
 	int i;
 
-	/* Use intermediate lock to update the one pool variable */
-	cg_ilock(&pool->data_lock);
+	cg_wlock(&pool->data_lock);
 
 	/* Generate coinbase */
 	work->nonce2 = bin2hex((const unsigned char *)&pool->nonce2, pool->n2size);
 	pool->nonce2++;
 
 	/* Downgrade to a read lock to read off the pool variables */
-	cg_dlock(&pool->data_lock);
+	cg_dwlock(&pool->data_lock);
 	alloc_len = pool->swork.cb_len;
 	align_len(&alloc_len);
 	coinbase = calloc(alloc_len, 1);
 	if (unlikely(!coinbase))
 		quit(1, "Failed to calloc coinbase in gen_stratum_work");
-	hex2bin(coinbase, pool->swork.coinbase1, pool->swork.cb1_len);
-	hex2bin(coinbase + pool->swork.cb1_len, pool->nonce1, pool->n1_len);
+	memcpy(coinbase, pool->swork.cb1, pool->swork.cb1_len);
+	memcpy(coinbase + pool->swork.cb1_len, pool->nonce1bin, pool->n1_len);
 	hex2bin(coinbase + pool->swork.cb1_len + pool->n1_len, work->nonce2, pool->n2size);
-	hex2bin(coinbase + pool->swork.cb1_len + pool->n1_len + pool->n2size, pool->swork.coinbase2, pool->swork.cb2_len);
+	memcpy(coinbase + pool->swork.cb1_len + pool->n1_len + pool->n2size, pool->swork.cb2, pool->swork.cb2_len);
 
 	/* Generate merkle root */
 	gen_hash(coinbase, merkle_root, pool->swork.cb_len);
diff --git a/driver-opencl.c b/driver-opencl.c
index 38995eb..57df2dc 100644
--- a/driver-opencl.c
+++ b/driver-opencl.c
@@ -550,7 +550,7 @@ char *set_intensity(char *arg)
 	else {
 		gpus[device].dynamic = false;
 		val = atoi(nextptr);
-		if (val < MIN_INTENSITY || val > MAX_INTENSITY)
+		if (val < MIN_INTENSITY || val > MAX_GPU_INTENSITY)
 			return "Invalid value passed to set intensity";
 		tt = &gpus[device].intensity;
 		*tt = val;
@@ -564,7 +564,7 @@ char *set_intensity(char *arg)
 		else {
 			gpus[device].dynamic = false;
 			val = atoi(nextptr);
-			if (val < MIN_INTENSITY || val > MAX_INTENSITY)
+			if (val < MIN_INTENSITY || val > MAX_GPU_INTENSITY)
 				return "Invalid value passed to set intensity";
 
 			tt = &gpus[device].intensity;
diff --git a/miner.h b/miner.h
index a05c1e0..2bc7ba7 100644
--- a/miner.h
+++ b/miner.h
@@ -754,17 +754,28 @@ static inline void rw_unlock(pthread_rwlock_t *lock)
 {
 	if (unlikely(pthread_rwlock_unlock(lock)))
 		quit(1, "WTF RWLOCK ERROR ON UNLOCK!");
-	sched_yield();
+}
+
+static inline void rd_unlock_noyield(pthread_rwlock_t *lock)
+{
+	rw_unlock(lock);
+}
+
+static inline void wr_unlock_noyield(pthread_rwlock_t *lock)
+{
+	rw_unlock(lock);
 }
 
 static inline void rd_unlock(pthread_rwlock_t *lock)
 {
 	rw_unlock(lock);
+	sched_yield();
 }
 
 static inline void wr_unlock(pthread_rwlock_t *lock)
 {
 	rw_unlock(lock);
+	sched_yield();
 }
 
 static inline void mutex_init(pthread_mutex_t *lock)
@@ -820,6 +831,14 @@ static inline void cg_wlock(cglock_t *lock)
 	wr_lock(&lock->rwlock);
 }
 
+/* Downgrade write variant to a read lock */
+static inline void cg_dwlock(cglock_t *lock)
+{
+	wr_unlock_noyield(&lock->rwlock);
+	rd_lock(&lock->rwlock);
+	mutex_unlock_noyield(&lock->mutex);
+}
+
 /* Downgrade intermediate variant to a read lock */
 static inline void cg_dlock(cglock_t *lock)
 {
@@ -958,11 +977,13 @@ extern bool add_pool_details(struct pool *pool, bool live, char *url, char *user
 #define MIN_INTENSITY_STR (opt_scrypt ? MIN_SCRYPT_INTENSITY_STR : MIN_SHA_INTENSITY_STR)
 #define MAX_INTENSITY (opt_scrypt ? MAX_SCRYPT_INTENSITY : MAX_SHA_INTENSITY)
 #define MAX_INTENSITY_STR (opt_scrypt ? MAX_SCRYPT_INTENSITY_STR : MAX_SHA_INTENSITY_STR)
+#define MAX_GPU_INTENSITY MAX_SCRYPT_INTENSITY
 #else
 #define MIN_INTENSITY MIN_SHA_INTENSITY
 #define MIN_INTENSITY_STR MIN_SHA_INTENSITY_STR
 #define MAX_INTENSITY MAX_SHA_INTENSITY
 #define MAX_INTENSITY_STR MAX_SHA_INTENSITY_STR
+#define MAX_GPU_INTENSITY MAX_SHA_INTENSITY
 #endif
 
 extern bool hotplug_mode;
@@ -1066,6 +1087,8 @@ struct stratum_work {
 	char *nbit;
 	char *ntime;
 	bool clean;
+	unsigned char *cb1;
+	unsigned char *cb2;
 
 	size_t cb1_len;
 	size_t cb2_len;
@@ -1152,6 +1175,7 @@ struct pool {
 	size_t sockbuf_size;
 	char *sockaddr_url; /* stripped url used for sockaddr */
 	char *nonce1;
+	unsigned char *nonce1bin;
 	size_t n1_len;
 	uint32_t nonce2;
 	int n2size;
@@ -1183,6 +1207,8 @@ struct pool {
 	unsigned char *txn_hashes;
 	int gbt_txns;
 	int coinbase_len;
+	int orig_len;
+
 	struct timeval tv_lastwork;
 };
 
diff --git a/util.c b/util.c
index 173b2d7..82f6f37 100644
--- a/util.c
+++ b/util.c
@@ -1277,6 +1277,17 @@ static bool parse_notify(struct pool *pool, json_t *val)
 	/* workpadding */	 96;
 	pool->swork.header_len = pool->swork.header_len * 2 + 1;
 	align_len(&pool->swork.header_len);
+
+	free(pool->swork.cb1);
+	free(pool->swork.cb2);
+	pool->swork.cb1 = calloc(pool->swork.cb1_len, 1);
+	if (unlikely(!pool->swork.cb1))
+		quit(1, "Failed to calloc swork cb1 in parse_notify");
+	hex2bin(pool->swork.cb1, pool->swork.coinbase1, pool->swork.cb1_len);
+	pool->swork.cb2 = calloc(pool->swork.cb2_len, 1);
+	if (unlikely(!pool->swork.cb2))
+		quit(1, "Failed to calloc swork cb2 in parse_notify");
+	hex2bin(pool->swork.cb2, pool->swork.coinbase2, pool->swork.cb2_len);
 	cg_wunlock(&pool->data_lock);
 
 	if (opt_protocol) {
@@ -1707,6 +1718,11 @@ resend:
 	pool->sessionid = sessionid;
 	pool->nonce1 = nonce1;
 	pool->n1_len = strlen(nonce1) / 2;
+	free(pool->nonce1bin);
+	pool->nonce1bin = calloc(pool->n1_len, 1);
+	if (unlikely(!pool->nonce1bin))
+		quit(1, "Failed to calloc pool->nonce1bin in initiate_stratum");
+	hex2bin(pool->nonce1bin, pool->nonce1, pool->n1_len);
 	pool->n2size = n2size;
 	cg_wunlock(&pool->data_lock);