static void *run(hashpipe_thread_args_t * args) { // Local aliases to shorten access to args fields // Our input buffer is a paper_input_databuf // Our output buffer is a paper_gpu_input_databuf paper_input_databuf_t *db_in = (paper_input_databuf_t *)args->ibuf; paper_gpu_input_databuf_t *db_out = (paper_gpu_input_databuf_t *)args->obuf; hashpipe_status_t st = args->st; const char * status_key = args->thread_desc->skey; #ifdef DEBUG_SEMS fprintf(stderr, "s/tid %lu/ FLUFf/\n", pthread_self()); #endif // Init status variables hashpipe_status_lock_safe(&st); hputi8(st.buf, "FLUFMCNT", 0); hashpipe_status_unlock_safe(&st); /* Loop */ int rv; int curblock_in=0; int curblock_out=0; float gbps, min_gbps; struct timespec start, finish; while (run_threads()) { // Note waiting status, // query integrating status // and, if armed, start count hashpipe_status_lock_safe(&st); hputs(st.buf, status_key, "waiting"); hashpipe_status_unlock_safe(&st); // Wait for new input block to be filled while ((rv=paper_input_databuf_wait_filled(db_in, curblock_in)) != HASHPIPE_OK) { if (rv==HASHPIPE_TIMEOUT) { hashpipe_status_lock_safe(&st); hputs(st.buf, status_key, "blocked_in"); hashpipe_status_unlock_safe(&st); continue; } else { hashpipe_error(__FUNCTION__, "error waiting for filled databuf"); pthread_exit(NULL); break; } } // Wait for new gpu_input block (our output block) to be free while ((rv=paper_gpu_input_databuf_wait_free(db_out, curblock_out)) != HASHPIPE_OK) { if (rv==HASHPIPE_TIMEOUT) { hashpipe_status_lock_safe(&st); hputs(st.buf, status_key, "blocked gpu input"); hashpipe_status_unlock_safe(&st); continue; } else { hashpipe_error(__FUNCTION__, "error waiting for free databuf"); pthread_exit(NULL); break; } } // Got a new data block, update status hashpipe_status_lock_safe(&st); hputs(st.buf, status_key, "fluffing"); hputi4(st.buf, "FLUFBKIN", curblock_in); hputu8(st.buf, "FLUFMCNT", db_in->block[curblock_in].header.mcnt); hashpipe_status_unlock_safe(&st); // Copy header and call fluff function clock_gettime(CLOCK_MONOTONIC, &start); memcpy(&db_out->block[curblock_out].header, &db_in->block[curblock_in].header, sizeof(paper_input_header_t)); paper_fluff(db_in->block[curblock_in].data, db_out->block[curblock_out].data); clock_gettime(CLOCK_MONOTONIC, &finish); // Note processing time hashpipe_status_lock_safe(&st); // Bits per fluff / ns per fluff = Gbps hgetr4(st.buf, "FLUFMING", &min_gbps); gbps = (float)(8*N_BYTES_PER_BLOCK)/ELAPSED_NS(start,finish); hputr4(st.buf, "FLUFGBPS", gbps); if(min_gbps == 0 || gbps < min_gbps) { hputr4(st.buf, "FLUFMING", gbps); } hashpipe_status_unlock_safe(&st); // Mark input block as free and advance paper_input_databuf_set_free(db_in, curblock_in); curblock_in = (curblock_in + 1) % db_in->header.n_block; // Mark output block as full and advance paper_gpu_input_databuf_set_filled(db_out, curblock_out); curblock_out = (curblock_out + 1) % db_out->header.n_block; /* Check for cancel */ pthread_testcancel(); } // Thread success! return NULL; }
static void *run(void * _args) { // Cast _args struct guppi_thread_args *args = (struct guppi_thread_args *)_args; #ifdef DEBUG_SEMS fprintf(stderr, "s/tid %lu/ FLUFf/\n", pthread_self()); #endif THREAD_RUN_BEGIN(args); THREAD_RUN_SET_AFFINITY_PRIORITY(args); /* Attach to status shared mem area */ THREAD_RUN_ATTACH_STATUS(args->instance_id, st); /* Attach to paper_input_databuf */ THREAD_RUN_ATTACH_DATABUF(args->instance_id, paper_input_databuf, db_in, args->input_buffer); /* Attach to paper_gpu_input_databuf */ THREAD_RUN_ATTACH_DATABUF(args->instance_id, paper_gpu_input_databuf, db_out, args->output_buffer); // Init status variables guppi_status_lock_safe(&st); hputi8(st.buf, "FLUFMCNT", 0); guppi_status_unlock_safe(&st); /* Loop */ int rv; int curblock_in=0; int curblock_out=0; struct timespec start, finish; while (run_threads) { // Note waiting status, // query integrating status // and, if armed, start count guppi_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "waiting"); guppi_status_unlock_safe(&st); // Wait for new input block to be filled while ((rv=paper_input_databuf_wait_filled(db_in, curblock_in)) != GUPPI_OK) { if (rv==GUPPI_TIMEOUT) { guppi_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "blocked_in"); guppi_status_unlock_safe(&st); continue; } else { guppi_error(__FUNCTION__, "error waiting for filled databuf"); run_threads=0; pthread_exit(NULL); break; } } // Wait for new gpu_input block (our output block) to be free while ((rv=paper_gpu_input_databuf_wait_free(db_out, curblock_out)) != GUPPI_OK) { if (rv==GUPPI_TIMEOUT) { guppi_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "blocked gpu input"); guppi_status_unlock_safe(&st); continue; } else { guppi_error(__FUNCTION__, "error waiting for free databuf"); run_threads=0; pthread_exit(NULL); break; } } // Got a new data block, update status guppi_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "fluffing"); hputi4(st.buf, "FLUFBKIN", curblock_in); hputu8(st.buf, "FLUFMCNT", db_in->block[curblock_in].header.mcnt); guppi_status_unlock_safe(&st); // Copy header and call fluff function clock_gettime(CLOCK_MONOTONIC, &start); memcpy(&db_out->block[curblock_out].header, &db_in->block[curblock_in].header, sizeof(paper_input_header_t)); paper_fluff(db_in->block[curblock_in].data, db_out->block[curblock_out].data); clock_gettime(CLOCK_MONOTONIC, &finish); // Note processing time guppi_status_lock_safe(&st); // Bits per fluff / ns per fluff = Gbps hputr4(st.buf, "FLUFGBPS", (float)(8*N_BYTES_PER_BLOCK)/ELAPSED_NS(start,finish)); guppi_status_unlock_safe(&st); // Mark input block as free and advance paper_input_databuf_set_free(db_in, curblock_in); curblock_in = (curblock_in + 1) % db_in->header.n_block; // Mark output block as full and advance paper_gpu_input_databuf_set_filled(db_out, curblock_out); curblock_out = (curblock_out + 1) % db_out->header.n_block; /* Check for cancel */ pthread_testcancel(); } run_threads=0; // Have to close all pushes THREAD_RUN_DETACH_DATAUF; THREAD_RUN_DETACH_DATAUF; THREAD_RUN_DETACH_STATUS; THREAD_RUN_END; // Thread success! return NULL; }