static void hfa_parse_gwq_status(struct cgpu_info *hashfast, struct hashfast_info *info, struct hf_header *h) { struct hf_gwq_data *g = (struct hf_gwq_data *)(h + 1); struct work *work; applog(LOG_DEBUG, "HFA %d: OP_GWQ_STATUS, device_head %4d tail %4d my tail %4d shed %3d inflight %4d", hashfast->device_id, g->sequence_head, g->sequence_tail, info->hash_sequence_tail, g->shed_count, HF_SEQUENCE_DISTANCE(info->hash_sequence_head,g->sequence_tail)); mutex_lock(&info->lock); info->hash_count += g->hash_count; info->device_sequence_head = g->sequence_head; info->device_sequence_tail = g->sequence_tail; info->shed_count = g->shed_count; /* Free any work that is no longer required */ while (info->device_sequence_tail != info->hash_sequence_tail) { if (++info->hash_sequence_tail >= info->num_sequence) info->hash_sequence_tail = 0; if (unlikely(!(work = info->works[info->hash_sequence_tail]))) { applog(LOG_ERR, "HFA %d: Bad work sequence tail", hashfast->device_id); hashfast->shutdown = true; break; } applog(LOG_DEBUG, "HFA %d: Completing work on hash_sequence_tail %d", hashfast->device_id, info->hash_sequence_tail); free_work(work); info->works[info->hash_sequence_tail] = NULL; } mutex_unlock(&info->lock); }
bool do_job_prepare(struct thr_info *mythr, struct timeval *tvp_now) { struct cgpu_info *proc = mythr->cgpu; struct device_drv *api = proc->drv; struct timeval tv_worktime; mythr->tv_morework.tv_sec = -1; mythr->_job_transition_in_progress = true; if (mythr->work) timersub(tvp_now, &mythr->work->tv_work_start, &tv_worktime); if ((!mythr->work) || abandon_work(mythr->work, &tv_worktime, proc->max_hashes)) { mythr->work_restart = false; request_work(mythr); // FIXME: Allow get_work to return NULL to retry on notification if (mythr->next_work) free_work(mythr->next_work); mythr->next_work = get_and_prepare_work(mythr); if (!mythr->next_work) return false; mythr->starting_next_work = true; api->job_prepare(mythr, mythr->next_work, mythr->_max_nonce); } else { mythr->starting_next_work = false; api->job_prepare(mythr, mythr->work, mythr->_max_nonce); } job_prepare_complete(mythr); return true; }
PRIVATE void error ( NumericType **Numeric, WorkType *Work ) { free_work (Work) ; UMFPACK_free_numeric ((void **) Numeric) ; ASSERT (UMF_malloc_count == init_count) ; }
static void gridseed_test_btc_nonce(struct cgpu_info *gridseed, GRIDSEED_INFO *info, struct thr_info *thr, unsigned char *data) { struct work *work; uint32_t nonce; int workid, index, i; bool valid = false; bool nowork = false; memcpy(&workid, data+8, 4); memcpy(&nonce, data+4, 4); nonce = htole32(nonce); mutex_lock(&info->qlock); nowork = (info->soft_queue_len <= 0); for(i=0; i<info->soft_queue_len; i++) { struct work *dupwork; work = info->workqueue[i]; if (work->devflag == false) continue; if (work->id > workid) break; dupwork = copy_work(work); if (dupwork == NULL) continue; if (test_nonce(dupwork, nonce)) { submit_tested_work(thr, dupwork); index = i; valid = true; free_work(dupwork); break; } else free_work(dupwork); } if (valid) __gridseed_purge_work_queue(gridseed, info, index); mutex_unlock(&info->qlock); if (!valid && !nowork) inc_hw_errors(thr); return; }
void pme_free_all_work(struct pme_solve_work_t **work, int nthread) { int thread; for (thread = 0; thread < nthread; thread++) { free_work(&(*work)[thread]); } sfree(work); *work = NULL; }
static void hfa_free_all_work(struct hashfast_info *info) { while (info->device_sequence_tail != info->hash_sequence_head) { struct work *work; if (++info->hash_sequence_tail >= info->num_sequence) info->hash_sequence_tail = 0; if (unlikely(!(work = info->works[info->hash_sequence_tail]))) break; free_work(work); info->works[info->hash_sequence_tail] = NULL; } }
static void do_queue_flush(struct thr_info *mythr) { struct cgpu_info *proc = mythr->cgpu; struct device_drv *api = proc->drv; api->queue_flush(mythr); if (mythr->next_work) { free_work(mythr->next_work); mythr->next_work = NULL; } }
static void hfa_parse_gwq_status(struct cgpu_info *hashfast, struct hashfast_info *info, struct hf_header *h) { struct hf_gwq_data *g = (struct hf_gwq_data *)(h + 1); struct work *work; applog(LOG_DEBUG, "HFA %d: OP_GWQ_STATUS, device_head %4d tail %4d my tail %4d shed %3d inflight %4d", hashfast->device_id, g->sequence_head, g->sequence_tail, info->hash_sequence_tail, g->shed_count, HF_SEQUENCE_DISTANCE(info->hash_sequence_head,g->sequence_tail)); /* This is a special flag that the thermal overload has been tripped */ if (unlikely(h->core_address & 0x80)) { applog(LOG_WARNING, "HFA %d Thermal overload tripped! Resetting device", hashfast->device_id); hfa_send_shutdown(hashfast); if (hfa_reset(hashfast, info)) { applog(LOG_NOTICE, "HFA %d: Succesfully reset, continuing operation", hashfast->device_id); return; } applog(LOG_WARNING, "HFA %d Failed to reset device, killing off thread to allow re-hotplug", hashfast->device_id); usb_nodev(hashfast); return; } mutex_lock(&info->lock); info->hash_count += g->hash_count; info->device_sequence_head = g->sequence_head; info->device_sequence_tail = g->sequence_tail; info->shed_count = g->shed_count; /* Free any work that is no longer required */ while (info->device_sequence_tail != info->hash_sequence_tail) { if (++info->hash_sequence_tail >= info->num_sequence) info->hash_sequence_tail = 0; if (unlikely(!(work = info->works[info->hash_sequence_tail]))) { applog(LOG_ERR, "HFA %d: Bad work sequence tail", hashfast->device_id); hashfast->shutdown = true; break; } applog(LOG_DEBUG, "HFA %d: Completing work on hash_sequence_tail %d", hashfast->device_id, info->hash_sequence_tail); free_work(work); info->works[info->hash_sequence_tail] = NULL; } mutex_unlock(&info->lock); }
void mt_job_transition(struct thr_info *mythr) { struct timeval tv_now; timer_set_now(&tv_now); if (mythr->starting_next_work) { mythr->next_work->tv_work_start = tv_now; if (mythr->prev_work) free_work(mythr->prev_work); mythr->prev_work = mythr->work; mythr->work = mythr->next_work; mythr->next_work = NULL; } mythr->tv_jobstart = tv_now; mythr->_job_transition_in_progress = false; }
static struct work *get_and_prepare_work(struct thr_info *thr) { struct cgpu_info *proc = thr->cgpu; struct device_drv *api = proc->drv; struct work *work; work = get_work(thr); if (!work) return NULL; if (api->prepare_work && !api->prepare_work(thr, work)) { free_work(work); applog(LOG_ERR, "%"PRIpreprv": Work prepare failed, disabling!", proc->proc_repr); proc->deven = DEV_RECOVER_ERR; run_cmd(cmd_idle); return NULL; } return work; }
GLOBAL Int UMFPACK_numeric ( const Int Ap [ ], const Int Ai [ ], const double Ax [ ], #ifdef COMPLEX const double Az [ ], #endif void *SymbolicHandle, void **NumericHandle, const double Control [UMFPACK_CONTROL], double User_Info [UMFPACK_INFO] ) { /* ---------------------------------------------------------------------- */ /* local variables */ /* ---------------------------------------------------------------------- */ double Info2 [UMFPACK_INFO], alloc_init, relpt, relpt2, droptol, front_alloc_init, stats [2] ; double *Info ; WorkType WorkSpace, *Work ; NumericType *Numeric ; SymbolicType *Symbolic ; Int n_row, n_col, n_inner, newsize, i, status, *inew, npiv, ulen, scale ; Unit *mnew ; /* ---------------------------------------------------------------------- */ /* get the amount of time used by the process so far */ /* ---------------------------------------------------------------------- */ umfpack_tic (stats) ; /* ---------------------------------------------------------------------- */ /* initialize and check inputs */ /* ---------------------------------------------------------------------- */ #ifndef NDEBUG UMF_dump_start ( ) ; init_count = UMF_malloc_count ; DEBUGm4 (("\nUMFPACK numeric: U transpose version\n")) ; #endif /* If front_alloc_init negative then allocate that size of front in * UMF_start_front. If alloc_init negative, then allocate that initial * size of Numeric->Memory. */ relpt = GET_CONTROL (UMFPACK_PIVOT_TOLERANCE, UMFPACK_DEFAULT_PIVOT_TOLERANCE) ; relpt2 = GET_CONTROL (UMFPACK_SYM_PIVOT_TOLERANCE, UMFPACK_DEFAULT_SYM_PIVOT_TOLERANCE) ; alloc_init = GET_CONTROL (UMFPACK_ALLOC_INIT, UMFPACK_DEFAULT_ALLOC_INIT) ; front_alloc_init = GET_CONTROL (UMFPACK_FRONT_ALLOC_INIT, UMFPACK_DEFAULT_FRONT_ALLOC_INIT) ; scale = GET_CONTROL (UMFPACK_SCALE, UMFPACK_DEFAULT_SCALE) ; droptol = GET_CONTROL (UMFPACK_DROPTOL, UMFPACK_DEFAULT_DROPTOL) ; relpt = MAX (0.0, MIN (relpt, 1.0)) ; relpt2 = MAX (0.0, MIN (relpt2, 1.0)) ; droptol = MAX (0.0, droptol) ; front_alloc_init = MIN (1.0, front_alloc_init) ; if (scale != UMFPACK_SCALE_NONE && scale != UMFPACK_SCALE_MAX) { scale = UMFPACK_DEFAULT_SCALE ; } if (User_Info != (double *) NULL) { /* return Info in user's array */ Info = User_Info ; /* clear the parts of Info that are set by UMFPACK_numeric */ for (i = UMFPACK_NUMERIC_SIZE ; i <= UMFPACK_MAX_FRONT_NCOLS ; i++) { Info [i] = EMPTY ; } for (i = UMFPACK_NUMERIC_DEFRAG ; i < UMFPACK_IR_TAKEN ; i++) { Info [i] = EMPTY ; } } else { /* no Info array passed - use local one instead */ Info = Info2 ; for (i = 0 ; i < UMFPACK_INFO ; i++) { Info [i] = EMPTY ; } } Symbolic = (SymbolicType *) SymbolicHandle ; Numeric = (NumericType *) NULL ; if (!UMF_valid_symbolic (Symbolic)) { Info [UMFPACK_STATUS] = UMFPACK_ERROR_invalid_Symbolic_object ; return (UMFPACK_ERROR_invalid_Symbolic_object) ; } /* compute alloc_init automatically for AMD or other symmetric ordering */ if (/* Symbolic->ordering == UMFPACK_ORDERING_AMD */ alloc_init >= 0 && Symbolic->amd_lunz > 0) { alloc_init = (Symbolic->nz + Symbolic->amd_lunz) / Symbolic->lunz_bound; alloc_init = MIN (1.0, alloc_init) ; alloc_init *= UMF_REALLOC_INCREASE ; } n_row = Symbolic->n_row ; n_col = Symbolic->n_col ; n_inner = MIN (n_row, n_col) ; /* check for integer overflow in Numeric->Memory minimum size */ if (INT_OVERFLOW (Symbolic->dnum_mem_init_usage * sizeof (Unit))) { /* :: int overflow, initial Numeric->Memory size :: */ /* There's no hope to allocate a Numeric object big enough simply to * hold the initial matrix, so return an out-of-memory condition */ DEBUGm4 (("out of memory: numeric int overflow\n")) ; Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; return (UMFPACK_ERROR_out_of_memory) ; } Info [UMFPACK_STATUS] = UMFPACK_OK ; Info [UMFPACK_NROW] = n_row ; Info [UMFPACK_NCOL] = n_col ; Info [UMFPACK_SIZE_OF_UNIT] = (double) (sizeof (Unit)) ; if (!Ap || !Ai || !Ax || !NumericHandle) { Info [UMFPACK_STATUS] = UMFPACK_ERROR_argument_missing ; return (UMFPACK_ERROR_argument_missing) ; } Info [UMFPACK_NZ] = Ap [n_col] ; *NumericHandle = (void *) NULL ; /* ---------------------------------------------------------------------- */ /* allocate the Work object */ /* ---------------------------------------------------------------------- */ /* (1) calls UMF_malloc 15 or 17 times, to obtain temporary workspace of * size c+1 Entry's and 2*(n_row+1) + 3*(n_col+1) + (n_col+n_inner+1) + * (nn+1) + * 3*(c+1) + 2*(r+1) + max(r,c) + (nfr+1) integers plus 2*nn * more integers if diagonal pivoting is to be done. r is the maximum * number of rows in any frontal matrix, c is the maximum number of columns * in any frontal matrix, n_inner is min (n_row,n_col), nn is * max (n_row,n_col), and nfr is the number of frontal matrices. For a * square matrix, this is c+1 Entry's and about 8n + 3c + 2r + max(r,c) + * nfr integers, plus 2n more for diagonal pivoting. */ Work = &WorkSpace ; Work->n_row = n_row ; Work->n_col = n_col ; Work->nfr = Symbolic->nfr ; Work->nb = Symbolic->nb ; Work->n1 = Symbolic->n1 ; if (!work_alloc (Work, Symbolic)) { DEBUGm4 (("out of memory: numeric work\n")) ; Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; error (&Numeric, Work) ; return (UMFPACK_ERROR_out_of_memory) ; } ASSERT (UMF_malloc_count == init_count + 16 + 2*Symbolic->prefer_diagonal) ; /* ---------------------------------------------------------------------- */ /* allocate Numeric object */ /* ---------------------------------------------------------------------- */ /* (2) calls UMF_malloc 10 or 11 times, for a total space of * sizeof (NumericType) bytes, 4*(n_row+1) + 4*(n_row+1) integers, and * (n_inner+1) Entry's, plus n_row Entry's if row scaling is to be done. * sizeof (NumericType) is a small constant. Next, it calls UMF_malloc * once, for the variable-sized part of the Numeric object * (Numeric->Memory). The size of this object is the larger of * (Control [UMFPACK_ALLOC_INIT]) * (the approximate upper bound computed * by UMFPACK_symbolic), and the minimum required to start the numerical * factorization. * This request is reduced if it fails. */ if (!numeric_alloc (&Numeric, Symbolic, alloc_init, scale)) { DEBUGm4 (("out of memory: initial numeric\n")) ; Info [UMFPACK_STATUS] = UMFPACK_ERROR_out_of_memory ; error (&Numeric, Work) ; return (UMFPACK_ERROR_out_of_memory) ; } DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n", init_count, UMF_malloc_count)) ; ASSERT (UMF_malloc_count == init_count + (16 + 2*Symbolic->prefer_diagonal) + (11 + (scale != UMFPACK_SCALE_NONE))) ; /* set control parameters */ Numeric->relpt = relpt ; Numeric->relpt2 = relpt2 ; Numeric->droptol = droptol ; Numeric->alloc_init = alloc_init ; Numeric->front_alloc_init = front_alloc_init ; Numeric->scale = scale ; DEBUG0 (("umf relpt %g %g init %g %g inc %g red %g\n", relpt, relpt2, alloc_init, front_alloc_init, UMF_REALLOC_INCREASE, UMF_REALLOC_REDUCTION)) ; /* ---------------------------------------------------------------------- */ /* scale and factorize */ /* ---------------------------------------------------------------------- */ /* (3) During numerical factorization (inside UMF_kernel), the variable-size * block of memory is increased in size via a call to UMF_realloc if it is * found to be too small. During factorization, this block holds the * pattern and values of L and U at the top end, and the elements * (contibution blocks) and the current frontal matrix (Work->F*) at the * bottom end. The peak size of the variable-sized object is estimated in * UMFPACK_*symbolic (Info [UMFPACK_VARIABLE_PEAK_ESTIMATE]), although this * upper bound can be very loose. The size of the Symbolic object * (which is currently allocated) is in Info [UMFPACK_SYMBOLIC_SIZE], and * is between 2*n and 13*n integers. */ DEBUG0 (("Calling umf_kernel\n")) ; status = UMF_kernel (Ap, Ai, Ax, #ifdef COMPLEX Az, #endif Numeric, Work, Symbolic) ; Info [UMFPACK_STATUS] = status ; if (status < UMFPACK_OK) { /* out of memory, or pattern has changed */ error (&Numeric, Work) ; return (status) ; } Info [UMFPACK_FORCED_UPDATES] = Work->nforced ; Info [UMFPACK_VARIABLE_INIT] = Numeric->init_usage ; if (Symbolic->prefer_diagonal) { Info [UMFPACK_NOFF_DIAG] = Work->noff_diagonal ; } DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n", init_count, UMF_malloc_count)) ; npiv = Numeric->npiv ; /* = n_inner for nonsingular matrices */ ulen = Numeric->ulen ; /* = 0 for square nonsingular matrices */ /* ---------------------------------------------------------------------- */ /* free Work object */ /* ---------------------------------------------------------------------- */ /* (4) After numerical factorization all of the objects allocated in step * (1) are freed via UMF_free, except that one object of size n_col+1 is * kept if there are off-diagonal nonzeros in the last pivot row (can only * occur for singular or rectangular matrices). This is Work->Upattern, * which is transfered to Numeric->Upattern if ulen > 0. */ DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n", init_count, UMF_malloc_count)) ; free_work (Work) ; DEBUG0 (("malloc: init_count "ID" UMF_malloc_count "ID"\n", init_count, UMF_malloc_count)) ; DEBUG0 (("Numeric->ulen: "ID" scale: "ID"\n", ulen, scale)) ; ASSERT (UMF_malloc_count == init_count + (ulen > 0) + (11 + (scale != UMFPACK_SCALE_NONE))) ; /* ---------------------------------------------------------------------- */ /* reduce Lpos, Lilen, Lip, Upos, Uilen and Uip to size npiv+1 */ /* ---------------------------------------------------------------------- */ /* (5) Six components of the Numeric object are reduced in size if the * matrix is singular or rectangular. The original size is 3*(n_row+1) + * 3*(n_col+1) integers. The new size is 6*(npiv+1) integers. For * square non-singular matrices, these two sizes are the same. */ if (npiv < n_row) { /* reduce Lpos, Uilen, and Uip from size n_row+1 to size npiv */ inew = (Int *) UMF_realloc (Numeric->Lpos, npiv+1, sizeof (Int)) ; if (inew) { Numeric->Lpos = inew ; } inew = (Int *) UMF_realloc (Numeric->Uilen, npiv+1, sizeof (Int)) ; if (inew) { Numeric->Uilen = inew ; } inew = (Int *) UMF_realloc (Numeric->Uip, npiv+1, sizeof (Int)) ; if (inew) { Numeric->Uip = inew ; } } if (npiv < n_col) { /* reduce Upos, Lilen, and Lip from size n_col+1 to size npiv */ inew = (Int *) UMF_realloc (Numeric->Upos, npiv+1, sizeof (Int)) ; if (inew) { Numeric->Upos = inew ; } inew = (Int *) UMF_realloc (Numeric->Lilen, npiv+1, sizeof (Int)) ; if (inew) { Numeric->Lilen = inew ; } inew = (Int *) UMF_realloc (Numeric->Lip, npiv+1, sizeof (Int)) ; if (inew) { Numeric->Lip = inew ; } } /* ---------------------------------------------------------------------- */ /* reduce Numeric->Upattern from size n_col+1 to size ulen+1 */ /* ---------------------------------------------------------------------- */ /* (6) The size of Numeric->Upattern (formerly Work->Upattern) is reduced * from size n_col+1 to size ulen + 1. If ulen is zero, the object does * not exist. */ DEBUG4 (("ulen: "ID" Upattern "ID"\n", ulen, (Int) Numeric->Upattern)) ; ASSERT (IMPLIES (ulen == 0, Numeric->Upattern == (Int *) NULL)) ; if (ulen > 0 && ulen < n_col) { inew = (Int *) UMF_realloc (Numeric->Upattern, ulen+1, sizeof (Int)) ; if (inew) { Numeric->Upattern = inew ; } } /* ---------------------------------------------------------------------- */ /* reduce Numeric->Memory to hold just the LU factors at the head */ /* ---------------------------------------------------------------------- */ /* (7) The variable-sized block (Numeric->Memory) is reduced to hold just L * and U, via a call to UMF_realloc, since the frontal matrices are no * longer needed. */ newsize = Numeric->ihead ; if (newsize < Numeric->size) { mnew = (Unit *) UMF_realloc (Numeric->Memory, newsize, sizeof (Unit)) ; if (mnew) { /* realloc succeeded (how can it fail since the size is reduced?) */ Numeric->Memory = mnew ; Numeric->size = newsize ; } } Numeric->ihead = Numeric->size ; Numeric->itail = Numeric->ihead ; Numeric->tail_usage = 0 ; Numeric->ibig = EMPTY ; /* UMF_mem_alloc_tail_block can no longer be called (no tail marker) */ /* ---------------------------------------------------------------------- */ /* report the results and return the Numeric object */ /* ---------------------------------------------------------------------- */ UMF_set_stats ( Info, Symbolic, (double) Numeric->max_usage, /* actual peak Numeric->Memory */ (double) Numeric->size, /* actual final Numeric->Memory */ Numeric->flops, /* actual "true flops" */ (double) Numeric->lnz + n_inner, /* actual nz in L */ (double) Numeric->unz + Numeric->nnzpiv, /* actual nz in U */ (double) Numeric->maxfrsize, /* actual largest front size */ (double) ulen, /* actual Numeric->Upattern size */ (double) npiv, /* actual # pivots found */ (double) Numeric->maxnrows, /* actual largest #rows in front */ (double) Numeric->maxncols, /* actual largest #cols in front */ scale != UMFPACK_SCALE_NONE, Symbolic->prefer_diagonal, ACTUAL) ; Info [UMFPACK_ALLOC_INIT_USED] = Numeric->alloc_init ; Info [UMFPACK_NUMERIC_DEFRAG] = Numeric->ngarbage ; Info [UMFPACK_NUMERIC_REALLOC] = Numeric->nrealloc ; Info [UMFPACK_NUMERIC_COSTLY_REALLOC] = Numeric->ncostly ; Info [UMFPACK_COMPRESSED_PATTERN] = Numeric->isize ; Info [UMFPACK_LU_ENTRIES] = Numeric->nLentries + Numeric->nUentries + Numeric->npiv ; Info [UMFPACK_UDIAG_NZ] = Numeric->nnzpiv ; Info [UMFPACK_RSMIN] = Numeric->rsmin ; Info [UMFPACK_RSMAX] = Numeric->rsmax ; Info [UMFPACK_WAS_SCALED] = Numeric->scale ; /* nz in L and U with no dropping of small entries */ Info [UMFPACK_ALL_LNZ] = Numeric->all_lnz + n_inner ; Info [UMFPACK_ALL_UNZ] = Numeric->all_unz + Numeric->nnzpiv ; Info [UMFPACK_NZDROPPED] = (Numeric->all_lnz - Numeric->lnz) + (Numeric->all_unz - Numeric->unz) ; /* estimate of the reciprocal of the condition number. */ if (SCALAR_IS_ZERO (Numeric->min_udiag) || SCALAR_IS_ZERO (Numeric->max_udiag) || SCALAR_IS_NAN (Numeric->min_udiag) || SCALAR_IS_NAN (Numeric->max_udiag)) { /* rcond is zero if there is any zero or NaN on the diagonal */ Numeric->rcond = 0.0 ; } else { /* estimate of the recipricol of the condition number. */ /* This is NaN if diagonal is zero-free, but has one or more NaN's. */ Numeric->rcond = Numeric->min_udiag / Numeric->max_udiag ; } Info [UMFPACK_UMIN] = Numeric->min_udiag ; Info [UMFPACK_UMAX] = Numeric->max_udiag ; Info [UMFPACK_RCOND] = Numeric->rcond ; if (Numeric->nnzpiv < n_inner || SCALAR_IS_ZERO (Numeric->rcond) || SCALAR_IS_NAN (Numeric->rcond)) { /* there are zeros and/or NaN's on the diagonal of U */ DEBUG0 (("Warning, matrix is singular in umfpack_numeric\n")) ; DEBUG0 (("nnzpiv "ID" n_inner "ID" rcond %g\n", Numeric->nnzpiv, n_inner, Numeric->rcond)) ; status = UMFPACK_WARNING_singular_matrix ; Info [UMFPACK_STATUS] = status ; } Numeric->valid = NUMERIC_VALID ; *NumericHandle = (void *) Numeric ; /* Numeric has 11 to 13 objects */ ASSERT (UMF_malloc_count == init_count + 11 + + (ulen > 0) /* Numeric->Upattern */ + (scale != UMFPACK_SCALE_NONE)) ; /* Numeric->Rs */ /* ---------------------------------------------------------------------- */ /* get the time used by UMFPACK_numeric */ /* ---------------------------------------------------------------------- */ umfpack_toc (stats) ; Info [UMFPACK_NUMERIC_WALLTIME] = stats [0] ; Info [UMFPACK_NUMERIC_TIME] = stats [1] ; /* return UMFPACK_OK or UMFPACK_WARNING_singular_matrix */ return (status) ; }
// Miner loop to manage a single processor (with possibly multiple threads per processor) void minerloop_scanhash(struct thr_info *mythr) { struct cgpu_info *cgpu = mythr->cgpu; struct device_drv *api = cgpu->drv; struct timeval tv_start, tv_end; struct timeval tv_hashes, tv_worktime; uint32_t max_nonce = api->can_limit_work ? api->can_limit_work(mythr) : 0xffffffff; int64_t hashes; struct work *work; const bool primary = (!mythr->device_thread) || mythr->primary_thread; #ifdef HAVE_PTHREAD_CANCEL pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); #endif while (likely(!cgpu->shutdown)) { mythr->work_restart = false; request_work(mythr); work = get_and_prepare_work(mythr); if (!work) break; timer_set_now(&work->tv_work_start); do { thread_reportin(mythr); /* Only allow the mining thread to be cancelled when * it is not in the driver code. */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); timer_set_now(&tv_start); hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce); timer_set_now(&tv_end); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); thread_reportin(mythr); timersub(&tv_end, &tv_start, &tv_hashes); if (!hashes_done(mythr, hashes, &tv_hashes, api->can_limit_work ? &max_nonce : NULL)) goto disabled; if (unlikely(mythr->work_restart)) { /* Apart from device_thread 0, we stagger the * starting of every next thread to try and get * all devices busy before worrying about * getting work for their extra threads */ if (!primary) { struct timespec rgtp; rgtp.tv_sec = 0; rgtp.tv_nsec = 250 * mythr->device_thread * 1000000; nanosleep(&rgtp, NULL); } break; } if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED)) disabled: mt_disable(mythr); timersub(&tv_end, &work->tv_work_start, &tv_worktime); } while (!abandon_work(work, &tv_worktime, cgpu->max_hashes)); free_work(work); } }
static int64_t serial_fpga_scanwork(struct thr_info *thr) { struct cgpu_info *serial_fpga; int fd; int ret; struct FPGA_INFO *info; unsigned char ob_bin[44], nonce_buf[SERIAL_READ_SIZE]; char *ob_hex; uint32_t nonce; int64_t hash_count; struct timeval tv_start, tv_finish, elapsed, tv_end, diff; int curr_hw_errors, i, j; uint32_t * ob; ob = (uint32_t *)ob_bin; int count; double Hs, W, fullnonce; int read_count; int64_t estimate_hashes; uint32_t values; int64_t hash_count_range; struct work *work; applog(LOG_DEBUG, "serial_fpga_scanwork..."); if (thr->cgpu->deven == DEV_DISABLED) return -1; serial_fpga = thr->cgpu; info = serial_fpga->device_data; work = get_work(thr, thr->id); if (info->device_fd == -1) { applog(LOG_INFO, "Attemping to Reopen Serial FPGA on %s", serial_fpga->device_path); fd = serial_open(serial_fpga->device_path, SERIAL_IO_SPEED, SERIAL_READ_TIMEOUT, false); if (unlikely(-1 == fd)) { applog(LOG_ERR, "Failed to open Serial FPGA on %s", serial_fpga->device_path); return -1; } else info->device_fd = fd; } fd = info->device_fd; memset(ob_bin, 0, sizeof(ob_bin)); // Currently, extra nonces are not supported // memset((unsigned char*)work->data + 144, 0, 12); // // calc_midstate(work); memcpy(ob_bin, work->midstate, 32); // Midstate memcpy(ob_bin + 32, work->data + 128, 12); // Remaining Bytes From Block Header // Send Bytes To FPGA In Reverse Order unsigned char swap[44]; uint32_t * sw; sw = (uint32_t *)swap; for (j=0; j<8; j++) { sw[j] = swab32(ob[j]); } memcpy(swap + 32, ob_bin + 32, 12); for (j=0; j<44; j++) { ob_bin[j] = swap[j]; } //unsigned char* b = (unsigned char*)(ob_bin); //applog(LOG_WARNING, "swap: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", b[28],b[29],b[30],b[31],b[32],b[33],b[34],b[35],b[36],b[37],b[38],b[39],b[40],b[41],b[42],b[43]); //applog(LOG_WARNING, "swap: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7],b[8],b[9],b[10],b[11],b[12],b[13],b[14],b[15],b[16],b[17],b[18],b[19],b[20],b[21],b[22],b[23],b[24],b[25],b[26],b[27],b[28],b[29],b[30],b[31],b[32],b[33],b[34],b[35],b[36],b[37],b[38],b[39],b[40],b[41],b[42],b[43]); //#ifndef WIN32 // tcflush(fd, TCOFLUSH); //#endif // Send Data To FPGA ret = write(fd, ob_bin, sizeof(ob_bin)); if (ret != sizeof(ob_bin)) { applog(LOG_ERR, "%s%i: Serial Send Error (ret=%d)", serial_fpga->drv->name, serial_fpga->device_id, ret); serial_fpga_close(thr); dev_error(serial_fpga, REASON_DEV_COMMS_ERROR); return 0; } if (opt_debug) { ob_hex = bin2hex(ob_bin, sizeof(ob_bin)); applog(LOG_DEBUG, "Serial FPGA %d sent: %s", serial_fpga->device_id, ob_hex); free(ob_hex); } elapsed.tv_sec = 0; elapsed.tv_usec = 0; cgtime(&tv_start); applog(LOG_DEBUG, "%s%i: Begin Scan For Nonces", serial_fpga->drv->name, serial_fpga->device_id); while (thr && !thr->work_restart) { memset(nonce_buf,0,4); // Check Serial Port For 1/10 Sec For Nonce ret = read(fd, nonce_buf, SERIAL_READ_SIZE); // Calculate Elapsed Time cgtime(&tv_end); timersub(&tv_end, &tv_start, &elapsed); if (ret == 0) { // No Nonce Found if (elapsed.tv_sec > info->timeout) { applog(LOG_DEBUG, "%s%i: End Scan For Nonces - Time = %d sec", serial_fpga->drv->name, serial_fpga->device_id, elapsed.tv_sec); break; } continue; } else if (ret < SERIAL_READ_SIZE) { applog(LOG_ERR, "%s%i: Serial Read Error (ret=%d)", serial_fpga->drv->name, serial_fpga->device_id, ret); serial_fpga_close(thr); dev_error(serial_fpga, REASON_DEV_COMMS_ERROR); break; } memcpy((char *)&nonce, nonce_buf, SERIAL_READ_SIZE); #if !defined (__BIG_ENDIAN__) && !defined(MIPSEB) nonce = swab32(nonce); #endif curr_hw_errors = serial_fpga->hw_errors; applog(LOG_INFO, "%s%i: Nonce Found - %08X (%5.1fMhz)", serial_fpga->drv->name, serial_fpga->device_id, nonce, (double)(1/(info->Hs * 1000000))); submit_nonce(thr, work, nonce); // Update Hashrate if (serial_fpga->hw_errors == curr_hw_errors) info->Hs = ((double)(elapsed.tv_sec) + ((double)(elapsed.tv_usec))/((double)1000000)) / (double)nonce; } // Estimate Number Of Hashes hash_count = ((double)(elapsed.tv_sec) + ((double)(elapsed.tv_usec))/((double)1000000)) / info->Hs; free_work(work); return hash_count; }