// if we use 2 threads on the same gpu, we need to reinit the threads void cuda_reset_device(int thr_id, bool *init) { int dev_id = device_map[thr_id % MAX_GPUS]; cudaSetDevice(dev_id); if (init != NULL) { // with init array, its meant to be used in algo's scan code... for (int i=0; i < MAX_GPUS; i++) { if (device_map[i] == dev_id) { init[i] = false; } } // force exit from algo's scan loops/function restart_threads(); cudaDeviceSynchronize(); while (cudaStreamQuery(NULL) == cudaErrorNotReady) usleep(1000); } cudaDeviceReset(); if (opt_cudaschedule >= 0) { cudaSetDeviceFlags((unsigned)(opt_cudaschedule & cudaDeviceScheduleMask)); } else { cudaSetDeviceFlags(cudaDeviceScheduleBlockingSync); } cudaDeviceSynchronize(); }
// pool switching code bool pool_switch(int thr_id, int pooln) { int prevn = cur_pooln; bool algo_switch = false; struct pool_infos *prev = &pools[cur_pooln]; struct pool_infos* p = NULL; // save prev stratum connection infos (struct) if (prev->type & POOL_STRATUM) { // may not be the right moment to free, // to check if required on submit... stratum_free_job(&stratum); prev->stratum = stratum; } if (pooln < num_pools) { cur_pooln = pooln; p = &pools[cur_pooln]; } else { applog(LOG_ERR, "Switch to inexistant pool %d!", pooln); return false; } // save global attributes prev->allow_mininginfo = allow_mininginfo; prev->allow_gbt = allow_gbt; prev->check_dups = check_dups; pthread_mutex_lock(&stratum_work_lock); free(rpc_user); rpc_user = strdup(p->user); free(rpc_pass); rpc_pass = strdup(p->pass); free(rpc_url); rpc_url = strdup(p->url); short_url = p->short_url; // just a pointer, no alloc opt_scantime = p->scantime; opt_max_diff = p->max_diff; opt_max_rate = p->max_rate; opt_shares_limit = p->shares_limit; opt_time_limit = p->time_limit; want_stratum = have_stratum = (p->type & POOL_STRATUM) != 0; // yiimp stats reporting opt_stratum_stats = (strstr(p->pass, "stats") != NULL) || (strcmp(p->user, "benchmark") == 0); pthread_mutex_unlock(&stratum_work_lock); // algo "blind" switch without free, not proper // todo: barrier required to free algo resources if (p->algo != (int) opt_algo) { if (opt_algo != ALGO_AUTO) { algo_switch = true; pthread_mutex_lock(&stats_lock); for (int n=0; n<opt_n_threads; n++) thr_hashrates[n] = 0.; stats_purge_all(); if (check_dups) hashlog_purge_all(); pthread_mutex_unlock(&stats_lock); } opt_algo = (enum sha_algos) p->algo; } if (prevn != cur_pooln) { pool_switch_count++; net_diff = 0; g_work_time = 0; g_work.data[0] = 0; pool_is_switching = true; stratum_need_reset = true; // used to get the pool uptime firstwork_time = time(NULL); restart_threads(); // reset wait states for (int n=0; n<opt_n_threads; n++) conditional_state[n] = false; // restore flags allow_gbt = p->allow_gbt; allow_mininginfo = p->allow_mininginfo; check_dups = p->check_dups; if (want_stratum) { // temporary... until stratum code cleanup stratum = p->stratum; stratum.pooln = cur_pooln; // unlock the stratum thread tq_push(thr_info[stratum_thr_id].q, strdup(rpc_url)); applog(LOG_BLUE, "Switch to stratum pool %d: %s", cur_pooln, strlen(p->name) ? p->name : p->short_url); } else { applog(LOG_BLUE, "Switch to pool %d: %s", cur_pooln, strlen(p->name) ? p->name : p->short_url); } // will unlock the longpoll thread on /LP url receive want_longpoll = (p->type & POOL_LONGPOLL) || !(p->type & POOL_STRATUM); if (want_longpoll) { pthread_mutex_lock(&stratum_work_lock); // will issue a lp_url request to unlock the longpoll thread have_longpoll = false; get_work(&thr_info[0], &g_work); pthread_mutex_unlock(&stratum_work_lock); } } return true; }
static void *longpoll_thread(void *userdata) { struct thr_info *mythr = userdata; CURL *curl = NULL; char *copy_start, *hdr_path, *lp_url = NULL; bool need_slash = false; int failures = 0; hdr_path = tq_pop(mythr->q, NULL); if (!hdr_path) goto out; /* full URL */ if (strstr(hdr_path, "://")) { lp_url = hdr_path; hdr_path = NULL; } /* absolute path, on current server */ else { copy_start = (*hdr_path == '/') ? (hdr_path + 1) : hdr_path; if (rpc_url[strlen(rpc_url) - 1] != '/') need_slash = true; lp_url = malloc(strlen(rpc_url) + strlen(copy_start) + 2); if (!lp_url) goto out; sprintf(lp_url, "%s%s%s", rpc_url, need_slash ? "/" : "", copy_start); } applog(LOG_INFO, "Long-polling activated for %s", lp_url); curl = curl_easy_init(); if (unlikely(!curl)) { applog(LOG_ERR, "CURL initialization failed"); goto out; } while (1) { json_t *val; val = json_rpc_call(curl, lp_url, rpc_userpass, rpc_req, false, true); if (likely(val)) { failures = 0; json_decref(val); applog(LOG_INFO, "LONGPOLL detected new block"); restart_threads(); } else { if (failures++ < 10) { sleep(30); applog(LOG_ERR, "longpoll failed, sleeping for 30s"); } else { applog(LOG_ERR, "longpoll failed, ending thread"); goto out; } } } out: free(hdr_path); free(lp_url); tq_freeze(mythr->q); if (curl) curl_easy_cleanup(curl); return NULL; }