int coilFinish(coilContext *cctx) { char me[]="coilFinish", err[BIFF_STRLEN]; unsigned int tidx; if (!cctx) { sprintf(err, "%s: got NULL pointer", me); biffAdd(COIL, err); return 1; } if (cctx->verbose > 1) { fprintf(stderr, "%s: finishing workers\n", me); } cctx->finished = AIR_TRUE; if (cctx->numThreads > 1) { airThreadBarrierWait(cctx->filterBarrier); for (tidx=1; tidx<cctx->numThreads; tidx++) { airThreadJoin(cctx->task[tidx]->thread, &(cctx->task[tidx]->returnPtr)); cctx->task[tidx]->thread = airThreadNix(cctx->task[tidx]->thread); cctx->task[tidx] = _coilTaskNix(cctx->task[tidx]); } } cctx->task[0]->thread = airThreadNix(cctx->task[0]->thread); cctx->task[0] = _coilTaskNix(cctx->task[0]); cctx->task = (coilTask **)airFree(cctx->task); if (cctx->numThreads > 1) { cctx->nextSliceMutex = airThreadMutexNix(cctx->nextSliceMutex); cctx->filterBarrier = airThreadBarrierNix(cctx->filterBarrier); cctx->updateBarrier = airThreadBarrierNix(cctx->updateBarrier); } return 0; }
coilTask * _coilTaskNix(coilTask *task) { if (task) { task->thread = airThreadNix(task->thread); task->_iv3 = (coil_t *)airFree(task->_iv3); task->iv3 = (coil_t **)airFree(task->iv3); free(task); } return NULL; }
echoThreadState * echoThreadStateNix(echoThreadState *state) { if (state) { state->thread = airThreadNix(state->thread); nrrdNuke(state->njitt); nrrdNuke(state->nperm); state->permBuff = AIR_CAST(unsigned int *, airFree(state->permBuff)); state->chanBuff = AIR_CAST(echoCol_t *, airFree(state->chanBuff)); airFree(state); } return NULL; }
int alanRun(alanContext *actx) { char me[]="alanRun", err[BIFF_STRLEN]; int tid, hack=AIR_FALSE; alanTask task[ALAN_THREAD_MAX]; if (_alanCheck(actx)) { sprintf(err, "%s: ", me); biffAdd(ALAN, err); return 1; } if (!( actx->_nlev[0] && actx->_nlev[0] )) { sprintf(err, "%s: _nlev[0,1] not allocated: " "call alanUpdate + alanInit", me); biffAdd(ALAN, err); return 1; } if (!airThreadCapable && 1 == actx->numThreads) { hack = airThreadNoopWarning; airThreadNoopWarning = AIR_FALSE; } actx->changeMutex = airThreadMutexNew(); actx->iterBarrier = airThreadBarrierNew(actx->numThreads); actx->averageChange = 0; actx->changeCount = 0; actx->stop = alanStopNot; for (tid=0; tid<actx->numThreads; tid++) { task[tid].actx = actx; task[tid].idx = tid; task[tid].thread = airThreadNew(); airThreadStart(task[tid].thread, _alanTuringWorker, (void *)&(task[tid])); } for (tid=0; tid<actx->numThreads; tid++) { airThreadJoin(task[tid].thread, &(task[tid].me)); task[tid].thread = airThreadNix(task[tid].thread); } actx->iterBarrier = airThreadBarrierNix(actx->iterBarrier); actx->changeMutex = airThreadMutexNix(actx->changeMutex); if (!airThreadCapable && 1 == actx->numThreads) { airThreadNoopWarning = hack; } /* we assume that someone set actx->stop */ return 0; }
/* ** this is called *after* pushOutputGet ** ** should nix everything created by the many _push*Setup() functions */ int pushFinish(pushContext *pctx) { char me[]="pushFinish", err[BIFF_STRLEN]; unsigned int ii, tidx; if (!pctx) { sprintf(err, "%s: got NULL pointer", me); biffAdd(PUSH, err); return 1; } if (pctx->verbose > 1) { fprintf(stderr, "%s: finishing workers\n", me); } pctx->finished = AIR_TRUE; if (pctx->numThread > 1) { airThreadBarrierWait(pctx->stageBarrierA); } for (tidx=pctx->numThread; tidx>0; tidx--) { if (tidx-1) { airThreadJoin(pctx->task[tidx-1]->thread, &(pctx->task[tidx-1]->returnPtr)); } pctx->task[tidx-1]->thread = airThreadNix(pctx->task[tidx-1]->thread); pctx->task[tidx-1] = _pushTaskNix(pctx->task[tidx-1]); } pctx->task = (pushTask **)airFree(pctx->task); pctx->nten = nrrdNuke(pctx->nten); pctx->ninv = nrrdNuke(pctx->ninv); pctx->nmask = nrrdNuke(pctx->nmask); pctx->gctx = gageContextNix(pctx->gctx); pctx->fctx = tenFiberContextNix(pctx->fctx); for (ii=0; ii<pctx->numBin; ii++) { pushBinDone(pctx->bin + ii); } pctx->bin = (pushBin *)airFree(pctx->bin); pctx->binsEdge = pctx->numBin = 0; if (pctx->numThread > 1) { pctx->binMutex = airThreadMutexNix(pctx->binMutex); pctx->stageBarrierA = airThreadBarrierNix(pctx->stageBarrierA); pctx->stageBarrierB = airThreadBarrierNix(pctx->stageBarrierB); } return 0; }
pullTask * _pullTaskNix(pullTask *task) { unsigned int ii; if (task) { for (ii=0; ii<task->pctx->volNum; ii++) { task->vol[ii] = pullVolumeNix(task->vol[ii]); } if (task->pctx->threadNum > 1) { task->thread = airThreadNix(task->thread); } task->rng = airRandMTStateNix(task->rng); task->pointBuffer = pullPointNix(task->pointBuffer); task->neighPoint = airFree(task->neighPoint); airFree(task); } return NULL; }
/* ******** hooverRender() ** ** because of the biff usage(), only one thread can call hooverRender(), ** and no promises if the threads themselves call biff... */ int hooverRender(hooverContext *ctx, int *errCodeP, int *errThreadP) { char me[]="hooverRender", err[BIFF_STRLEN]; _hooverExtraContext *ec; _hooverThreadArg args[HOOVER_THREAD_MAX]; _hooverThreadArg *errArg; airThread *thread[HOOVER_THREAD_MAX]; _htpu u; void *render; int ret; airArray *mop; int threadIdx; if (!( errCodeP && errThreadP )) { sprintf(err, "%s: got NULL int return pointer", me); biffAdd(HOOVER, err); return hooverErrInit; } /* this calls limnCameraUpdate() */ if (hooverContextCheck(ctx)) { sprintf(err, "%s: problem detected in given context", me); biffAdd(HOOVER, err); *errCodeP = 0; *errThreadP = 0; return hooverErrInit; } if (!(ec = _hooverExtraContextNew(ctx))) { sprintf(err, "%s: problem creating thread context", me); biffAdd(HOOVER, err); *errCodeP = 0; *errThreadP = 0; return hooverErrInit; } mop = airMopNew(); airMopAdd(mop, ec, (airMopper)_hooverExtraContextNix, airMopAlways); if ( (ret = (ctx->renderBegin)(&render, ctx->user)) ) { *errCodeP = ret; *errCodeP = 0; *errThreadP = 0; airMopError(mop); return hooverErrRenderBegin; } for (threadIdx=0; threadIdx<ctx->numThreads; threadIdx++) { args[threadIdx].ctx = ctx; args[threadIdx].ec = ec; args[threadIdx].render = render; args[threadIdx].whichThread = threadIdx; args[threadIdx].whichErr = hooverErrNone; args[threadIdx].errCode = 0; thread[threadIdx] = airThreadNew(); } ctx->workIdx = 0; if (1 < ctx->numThreads) { ctx->workMutex = airThreadMutexNew(); } else { ctx->workMutex = NULL; } /* (done): call airThreadStart() once per thread, passing the address of a distinct (and appropriately intialized) _hooverThreadArg to each. If return of airThreadStart() is non-zero, put its return in *errCodeP, the number of the problematic in *errThreadP, and return hooverErrThreadCreate. Then call airThreadJoin() on all the threads, passing &errArg as "retval". On non-zero return, set *errCodeP and *errThreadP, and return hooverErrThreadJoin. If return of airThreadJoin() is zero, but the errArg is non-NULL, then assume that this errArg is actually just the passed _hooverThreadArg returned to us, and from this copy errArg->errCode into *errCodeP, and return errArg->whichErr */ if (1 < ctx->numThreads && !airThreadCapable) { fprintf(stderr, "%s: WARNING: not multi-threaded; will do %d " "\"threads\" serially !!!\n", me, ctx->numThreads); } for (threadIdx=0; threadIdx<ctx->numThreads; threadIdx++) { if ((ret = airThreadStart(thread[threadIdx], _hooverThreadBody, (void *) &args[threadIdx]))) { *errCodeP = ret; *errThreadP = threadIdx; airMopError(mop); return hooverErrThreadCreate; } } for (threadIdx=0; threadIdx<ctx->numThreads; threadIdx++) { u.h = &errArg; if ((ret = airThreadJoin(thread[threadIdx], u.v))) { *errCodeP = ret; *errThreadP = threadIdx; airMopError(mop); return hooverErrThreadJoin; } if (errArg != NULL) { *errCodeP = errArg->errCode; *errThreadP = threadIdx; return errArg->whichErr; } thread[threadIdx] = airThreadNix(thread[threadIdx]); } if (1 < ctx->numThreads) { ctx->workMutex = airThreadMutexNix(ctx->workMutex); } if ( (ret = (ctx->renderEnd)(render, ctx->user)) ) { *errCodeP = ret; *errThreadP = -1; return hooverErrRenderEnd; } render = NULL; airMopOkay(mop); *errCodeP = 0; *errThreadP = 0; return hooverErrNone; }