Browse Source

Use a pthread conditional that is broadcast whenever work restarts are required. Create a generic wait function waiting a specified time on that conditional that returns if the condition is met or a specified time passed to it has elapsed. Use this to do smarter polling in bitforce to abort work, queue more work, and check for results to minimise time spent working needlessly.

nfactor-troky
ckolivas 13 years ago
parent
commit
fd7b21ed56
  1. 33
      cgminer.c
  2. 29
      driver-bitforce.c
  3. 5
      miner.h

33
cgminer.c

@ -174,6 +174,9 @@ pthread_rwlock_t netacc_lock;
static pthread_mutex_t lp_lock; static pthread_mutex_t lp_lock;
static pthread_cond_t lp_cond; static pthread_cond_t lp_cond;
pthread_mutex_t restart_lock;
pthread_cond_t restart_cond;
double total_mhashes_done; double total_mhashes_done;
static struct timeval total_tv_start, total_tv_end; static struct timeval total_tv_start, total_tv_end;
@ -2472,8 +2475,26 @@ static void discard_stale(void)
subtract_queued(nonclone); subtract_queued(nonclone);
} }
static bool queue_request(struct thr_info *thr, bool needed); bool queue_request(struct thr_info *thr, bool needed);
/* A generic wait function for threads that poll that will wait a specified
* time tdiff waiting on the pthread conditional that is broadcast when a
* work restart is required. Returns the value of pthread_cond_timedwait
* which is zero if the condition was met or ETIMEDOUT if not.
*/
int restart_wait(struct timeval *tdiff)
{
struct timeval now, then;
struct timespec abstime;
gettimeofday(&now, NULL);
timeradd(&now, tdiff, &then);
abstime.tv_sec = then.tv_sec;
abstime.tv_nsec = then.tv_usec * 1000;
mutex_lock(&restart_lock);
return pthread_cond_timedwait(&restart_cond, &restart_lock, &abstime);
}
static void restart_threads(void) static void restart_threads(void)
{ {
int i; int i;
@ -2485,6 +2506,10 @@ static void restart_threads(void)
for (i = 0; i < mining_threads; i++) for (i = 0; i < mining_threads; i++)
work_restart[i].restart = 1; work_restart[i].restart = 1;
mutex_lock(&restart_lock);
pthread_cond_broadcast(&restart_cond);
mutex_unlock(&restart_lock);
} }
static void set_curblock(char *hexstr, unsigned char *hash) static void set_curblock(char *hexstr, unsigned char *hash)
@ -3568,7 +3593,7 @@ static void control_tclear(bool *var)
static bool queueing; static bool queueing;
static bool queue_request(struct thr_info *thr, bool needed) bool queue_request(struct thr_info *thr, bool needed)
{ {
struct workio_cmd *wc; struct workio_cmd *wc;
struct timeval now; struct timeval now;
@ -4997,6 +5022,10 @@ int main(int argc, char *argv[])
if (unlikely(pthread_cond_init(&lp_cond, NULL))) if (unlikely(pthread_cond_init(&lp_cond, NULL)))
quit(1, "Failed to pthread_cond_init lp_cond"); quit(1, "Failed to pthread_cond_init lp_cond");
mutex_init(&restart_lock);
if (unlikely(pthread_cond_init(&restart_cond, NULL)))
quit(1, "Failed to pthread_cond_init restart_cond");
sprintf(packagename, "%s %s", PACKAGE, VERSION); sprintf(packagename, "%s %s", PACKAGE, VERSION);
#ifdef WANT_CPUMINE #ifdef WANT_CPUMINE

29
driver-bitforce.c

@ -139,6 +139,7 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6
char pdevbuf[0x100]; char pdevbuf[0x100];
unsigned char ob[61] = ">>>>>>>>12345678901234567890123456789012123456789012>>>>>>>>"; unsigned char ob[61] = ">>>>>>>>12345678901234567890123456789012123456789012>>>>>>>>";
struct timeval tdiff;
int i; int i;
char *pnoncebuf; char *pnoncebuf;
char *s; char *s;
@ -195,9 +196,28 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6
} }
} }
usleep(4500000); /* Initially wait 2/3 of the average cycle time so we can request more
i = 4500; * work before full scan is up ~ 3.4 seconds */
while (1) { tdiff.tv_sec = 3;
tdiff.tv_usec = 4000000;
if (!restart_wait(&tdiff))
return 0;
queue_request(thr, false);
i = 3400;
/* Now wait another second; no bistream should be finished by now */
tdiff.tv_sec = 1;
tdiff.tv_usec = 0;
if (!restart_wait(&tdiff))
return 0;
i += 1000;
/* Now start looking for results. Stupid polling every 10ms... */
tdiff.tv_sec = 0;
tdiff.tv_usec = 10000;
while (42) {
int rc = restart_wait(&tdiff);
BFwrite(fdDev, "ZFX", 3); BFwrite(fdDev, "ZFX", 3);
BFgets(pdevbuf, sizeof(pdevbuf), fdDev); BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
if (unlikely(!pdevbuf[0])) { if (unlikely(!pdevbuf[0])) {
@ -206,7 +226,8 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6
} }
if (pdevbuf[0] != 'B') if (pdevbuf[0] != 'B')
break; break;
usleep(10000); if (!rc)
return 0;
i += 10; i += 10;
} }
applog(LOG_DEBUG, "BitForce waited %dms until %s\n", i, pdevbuf); applog(LOG_DEBUG, "BitForce waited %dms until %s\n", i, pdevbuf);

5
miner.h

@ -559,7 +559,12 @@ struct work_restart {
char padding[128 - sizeof(unsigned long)]; char padding[128 - sizeof(unsigned long)];
}; };
extern pthread_mutex_t restart_lock;
extern pthread_cond_t restart_cond;
extern void thread_reportin(struct thr_info *thr); extern void thread_reportin(struct thr_info *thr);
extern bool queue_request(struct thr_info *thr, bool needed);
extern int restart_wait(struct timeval *tdiff);
extern void kill_work(void); extern void kill_work(void);

Loading…
Cancel
Save