epicsShareFunc void epicsExitCallAtExits(void) { exitPvt * pep = 0; epicsExitInit (); epicsMutexMustLock ( exitPvtLock ); if ( pExitPvtPerProcess ) { pep = pExitPvtPerProcess; pExitPvtPerProcess = 0; } epicsMutexUnlock ( exitPvtLock ); if ( pep ) { epicsExitCallAtExitsPvt ( pep ); destroyExitPvt ( pep ); } }
/* * Flush elements on syncQ queue and clear event flag. */ epicsShareFunc void epicsShareAPI seq_pvFlushQ(SS_ID ss, VAR_ID varId) { SPROG *sp = ss->sprog; CHAN *ch = sp->chan + varId; EV_ID ev_flag = ch->syncedTo; QUEUE queue = ch->queue; DEBUG("pvFlushQ: pv name=%s, count=%d\n", ch->dbch ? ch->dbch->dbName : "<anomymous>", seqQueueUsed(queue)); seqQueueFlush(queue); epicsMutexMustLock(sp->programLock); /* Clear event flag */ bitClear(sp->evFlags, ev_flag); epicsMutexUnlock(sp->programLock); }
static void interruptCallbackInput(void *drvPvt, asynUser *pasynUser, epicsInt32 value) { devInt32Pvt *pPvt = (devInt32Pvt *)drvPvt; dbCommon *pr = pPvt->pr; ringBufferElement *rp; if (pPvt->mask) { value &= pPvt->mask; if (pPvt->bipolar && (value & pPvt->signBit)) value |= ~pPvt->mask; } asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynInt32::interruptCallbackInput new value=%d\n", pr->name, value); /* There is a problem. A driver could be calling us with a value after * this record has registered for callbacks but before EPICS has set interruptAccept, * which means that scanIoRequest will return immediately. * This is very bad, because if we have pushed a value into the ring buffer * it won't get popped off because the record won't process. The values * read the next time the record processes would then be stale. * We previously worked around this problem by waiting here for interruptAccept. * But that does not work if the callback is coming from the thread that is executing * iocInit, which can happen with synchronous drivers (ASYN_CANBLOCK=0) that do callbacks * when a value is written to them, which can happen in initRecord for an output record. * Instead we just return. There will then be nothing in the ring buffer, so the first * read will do a read from the driver, which should be OK. */ if (!interruptAccept) return; epicsMutexLock(pPvt->ringBufferLock); rp = &pPvt->ringBuffer[pPvt->ringHead]; rp->value = value; rp->time = pasynUser->timestamp; rp->status = pasynUser->auxStatus; pPvt->ringHead = (pPvt->ringHead==pPvt->ringSize) ? 0 : pPvt->ringHead+1; if (pPvt->ringHead == pPvt->ringTail) { /* There was no room in the ring buffer. In the past we just threw away * the new value. However, it is better to remove the oldest value from the * ring buffer and add the new one. That way the final value the record receives * is guaranteed to be the most recent value */ pPvt->ringTail = (pPvt->ringTail==pPvt->ringSize) ? 0 : pPvt->ringTail+1; pPvt->ringBufferOverflows++; } else { /* We only need to request the record to process if we added a new * element to the ring buffer, not if we just replaced an element. */ scanIoRequest(pPvt->ioScanPvt); } epicsMutexUnlock(pPvt->ringBufferLock); }
static void srqPoll(asynUser *pasynUser) { void *drvPvt = pasynUser->userPvt; int srqStatus,primary,secondary; GETgpibPvtasynGpibPort epicsMutexMustLock(pgpibPvt->lock); if(!pgpibPvt->pollRequestIsQueued) printf("%s srqPoll but !pollRequestIsQueued. Why?\n",pgpibPvt->portName); pgpibPvt->pollRequestIsQueued = 0; epicsMutexUnlock(pgpibPvt->lock); srqStatus = pasynGpibPort->srqStatus(pgpibPvt->asynGpibPortPvt); while(srqStatus) { pasynGpibPort->serialPollBegin(pgpibPvt->asynGpibPortPvt); for(primary=0; primary<NUM_GPIB_ADDRESSES; primary++) { pollListPrimary *ppollListPrimary = &pgpibPvt->pollList[primary]; pollListNode *ppollListNode = &ppollListPrimary->primary; int statusByte; if(ppollListNode->pollIt) { statusByte = pasynGpibPort->serialPoll( pgpibPvt->asynGpibPortPvt,primary,SRQTIMEOUT); if(statusByte) { pgpibPvt->srq_handler(pgpibPvt->srqHandlerPvt, primary,statusByte); } } for(secondary=0; secondary<NUM_GPIB_ADDRESSES; secondary++) { ppollListNode = &ppollListPrimary->secondary[secondary]; if(ppollListNode->pollIt) { int addr = primary*100+secondary; statusByte = pasynGpibPort->serialPoll( pgpibPvt->asynGpibPortPvt,addr,SRQTIMEOUT); if(statusByte) { pgpibPvt->srq_handler(pgpibPvt->srqHandlerPvt, addr,statusByte); } } } } pasynGpibPort->serialPollEnd(pgpibPvt->asynGpibPortPvt); srqStatus = pasynGpibPort->srqStatus(pgpibPvt->asynGpibPortPvt); if(!srqStatus) break; printf("%s after srqPoll srqStatus is %x Why?\n", pgpibPvt->portName,srqStatus); } }
/* Caller must take devLock */ static void stopIsrThread(osdISR *isr) { if (isr->waiter_status==osdISRDone) return; isr->waiter_status = osdISRStopping; while (isr->waiter_status!=osdISRDone) { epicsMutexUnlock(isr->osd->devLock); epicsEventWait(isr->done); epicsMutexMustLock(isr->osd->devLock); } }
void drvEtherIP_remove_callback (PLC *plc, TagInfo *info, EIPCallback callback, void *arg) { TagCallback *cb; epicsMutexLock(plc->lock); for (cb = DLL_first(TagCallback, &info->callbacks); cb; cb=DLL_next(TagCallback, cb)) { if (cb->callback == callback && cb->arg == arg) { DLL_unlink(&info->callbacks, cb); free(cb); break; } } epicsMutexUnlock(plc->lock); }
/** Deletes all attributes from the list. */ int NDAttributeList::clear() { NDAttribute *pAttribute; NDAttributeListNode *pListNode; //const char *functionName = "NDAttributeList::clear"; epicsMutexLock(this->lock); pListNode = (NDAttributeListNode *)ellFirst(&this->list); while (pListNode) { pAttribute = pListNode->pNDAttribute; ellDelete(&this->list, &pListNode->node); delete pAttribute; pListNode = (NDAttributeListNode *)ellFirst(&this->list); } epicsMutexUnlock(this->lock); return(ND_SUCCESS); }
/** Removes an attribute from the list. * \param[in] pName The name of the attribute to be deleted. * \return Returns ND_SUCCESS if the attribute was found and deleted, ND_ERROR if the * attribute was not found. */ int NDAttributeList::remove(const char *pName) { NDAttribute *pAttribute; int status = ND_ERROR; //const char *functionName = "NDAttributeList::remove"; epicsMutexLock(this->lock); pAttribute = this->find(pName); if (!pAttribute) goto done; ellDelete(&this->list, &pAttribute->listNode.node); delete pAttribute; status = ND_SUCCESS; done: epicsMutexUnlock(this->lock); return(status); }
/** Finds the next attribute in the linked list of attributes. * \param[in] pAttributeIn A pointer to the previous attribute in the list; * if NULL the first attribute in the list is returned. * \return Returns a pointer to the next attribute if there is one, * NULL if there are no more attributes in the list. */ NDAttribute* NDAttributeList::next(NDAttribute *pAttributeIn) { NDAttribute *pAttribute=NULL; NDAttributeListNode *pListNode; //const char *functionName = "NDAttributeList::next"; epicsMutexLock(this->lock); if (!pAttributeIn) { pListNode = (NDAttributeListNode *)ellFirst(&this->list); } else { pListNode = (NDAttributeListNode *)ellNext(&pAttributeIn->listNode.node); } if (pListNode) pAttribute = pListNode->pNDAttribute; epicsMutexUnlock(this->lock); return(pAttribute); }
/** Adds an attribute to the list. * This is a convenience function for adding attributes to a list. * It first searches the list to see if there is an existing attribute * with the same name. If there is it just changes the properties of the * existing attribute. If not, it creates a new attribute with the * specified properties. * IMPORTANT: This method is only capable of creating attributes * of the NDAttribute base class type, not derived class attributes. * To add attributes of a derived class to a list the NDAttributeList::add(NDAttribute*) * method must be used. * \param[in] pName The name of the attribute to be added. * \param[in] pDescription The description of the attribute. * \param[in] dataType The data type of the attribute. * \param[in] pValue A pointer to the value for this attribute. * */ NDAttribute* NDAttributeList::add(const char *pName, const char *pDescription, NDAttrDataType_t dataType, void *pValue) { //const char *functionName = "NDAttributeList::add"; NDAttribute *pAttribute; epicsMutexLock(this->lock); pAttribute = this->find(pName); if (pAttribute) { pAttribute->setDescription(pDescription); pAttribute->setValue(dataType, pValue); } else { pAttribute = new NDAttribute(pName, pDescription, dataType, pValue); ellAdd(&this->list, &pAttribute->listNode.node); } epicsMutexUnlock(this->lock); return(pAttribute); }
epicsShareFunc void epicsShareAPI errlogAddListener( errlogListener listener, void *pPrivate) { listenerNode *plistenerNode; errlogInit(0); if (pvtData.atExit) return; plistenerNode = callocMustSucceed(1,sizeof(listenerNode), "errlogAddListener"); epicsMutexMustLock(pvtData.listenerLock); plistenerNode->listener = listener; plistenerNode->pPrivate = pPrivate; ellAdd(&pvtData.listenerList,&plistenerNode->node); epicsMutexUnlock(pvtData.listenerLock); }
static int motorAxisStop( AXIS_HDL pAxis, double acceleration ) { if (pAxis == NULL) return MOTOR_AXIS_ERROR; else { if (epicsMutexLock( pAxis->axisMutex ) == epicsMutexLockOK) { motorAxisVelocity( pAxis, 0.0, acceleration ); pAxis->deferred_move = 0; epicsMutexUnlock( pAxis->axisMutex ); pAxis->print( pAxis->logParam, TRACE_FLOW, "Set card %d, axis %d to stop with accel=%f", pAxis->card, pAxis->axis, acceleration ); } } return MOTOR_AXIS_OK; }
long dbCaGetAlarmLimits(const struct link *plink, double *lolo, double *low, double *high, double *hihi) { caLink *pca; int gotAttributes; pcaGetCheck gotAttributes = pca->gotAttributes; if (gotAttributes) { *lolo = pca->alarmLimits[0]; *low = pca->alarmLimits[1]; *high = pca->alarmLimits[2]; *hihi = pca->alarmLimits[3]; } epicsMutexUnlock(pca->lock); return gotAttributes ? 0 : -1; }
static void interruptCallbackAverage(void *drvPvt, asynUser *pasynUser, epicsFloat64 value) { devPvt *pPvt = (devPvt *)drvPvt; dbCommon *pr = pPvt->pr; asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynFloat64::interruptCallbackAverage new value=%f\n", pr->name, value); epicsMutexLock(pPvt->ringBufferLock); pPvt->numAverage++; pPvt->sum += value; pPvt->result.status |= pasynUser->auxStatus; pPvt->result.alarmStatus = pasynUser->alarmStatus; pPvt->result.alarmSeverity = pasynUser->alarmSeverity; epicsMutexUnlock(pPvt->ringBufferLock); }
/* * Set an event flag, then wake up each state * set that might be waiting on that event flag. */ epicsShareFunc void seq_efSet(SS_ID ss, EF_ID ev_flag) { PROG *sp = ss->prog; DEBUG("efSet: sp=%p, ev_flag=%d\n", sp, ev_flag); assert(ev_flag > 0 && ev_flag <= sp->numEvFlags); epicsMutexMustLock(sp->lock); /* Set this bit */ bitSet(sp->evFlags, ev_flag); /* Wake up state sets that are waiting for this event flag */ ss_wakeup(sp, ev_flag); epicsMutexUnlock(sp->lock); }
static gtProvider * findProvider(ELLLIST *plist, epicsMutexId lock, const char *name, int priority) { gtProvider *ptp; epicsMutexMustLock(lock); for (ptp = (gtProvider *)ellFirst(plist); ptp; ptp = (gtProvider *)ellNext(&ptp->node)) { if (ptp->priority == ptp->priority && !strcmp(ptp->name, name)) break; } epicsMutexUnlock(lock); return ptp; }
/* * Clear event flag. */ epicsShareFunc boolean seq_efClear(SS_ID ss, EF_ID ev_flag) { PROG *sp = ss->prog; boolean isSet; assert(ev_flag > 0 && ev_flag <= ss->prog->numEvFlags); epicsMutexMustLock(sp->lock); isSet = bitTest(sp->evFlags, ev_flag); bitClear(sp->evFlags, ev_flag); /* Wake up state sets that are waiting for this event flag */ ss_wakeup(sp, ev_flag); epicsMutexUnlock(sp->lock); return isSet; }
epicsShareFunc int epicsShareAPI epicsMessageQueuePending(epicsMessageQueueId pmsg) { char *myInPtr, *myOutPtr; int nmsg; epicsMutexLock(pmsg->mutex); myInPtr = (char *)pmsg->inPtr; myOutPtr = (char *)pmsg->outPtr; if (pmsg->full) nmsg = pmsg->capacity; else if (myInPtr >= myOutPtr) nmsg = (myInPtr - myOutPtr) / pmsg->slotSize; else nmsg = pmsg->capacity - (myOutPtr - myInPtr) / pmsg->slotSize; epicsMutexUnlock(pmsg->mutex); return nmsg; }
static asynStatus writeOctet(void *ppvt,asynUser *pasynUser,const char *data,size_t numchars,size_t *nbytes) { int addr; asynStatus status; Port* pport=(Port*)ppvt; Command* pcommand=(Command*)pasynUser->drvUser; if( pport->init==0 ) return( asynError ); if( pasynManager->getAddr(pasynUser,&addr)) return( asynError ); epicsMutexMustLock(pport->syncLock); status = pcommand->writeFunc(pcommand,pport->pasynUser,(char*)data,ifaceAsynOctet); epicsMutexUnlock(pport->syncLock); if( ASYN_ERROR(status) ) *nbytes=0; else *nbytes=strlen(data); return( status ); }
epicsShareFunc void epicsThreadPoolReleaseShared(epicsThreadPool *pool) { if (!pool) return; epicsMutexMustLock(sharedPoolsGuard); assert(pool->sharedCount > 0); pool->sharedCount--; if (pool->sharedCount == 0) { ellDelete(&sharedPools, &pool->sharedNode); epicsThreadPoolDestroy(pool); } epicsMutexUnlock(sharedPoolsGuard); }
LOCAL long devSiTPG262Read_gst_str(drvTPG262Config* pdrvTPG262Config, int gauge_num, char* gst_str) { TPG262_read* pTPG262_read = (TPG262_read*)pdrvTPG262Config->pTPG262_read; epicsMutexLock(pdrvTPG262Config->lock); switch(gauge_num){ case 0: strcpy(gst_str, pTPG262_read->gst_str0); break; case 1: strcpy(gst_str, pTPG262_read->gst_str1); break; default: gst_str[0] = NULL; } epicsMutexUnlock(pdrvTPG262Config->lock); return 0; }
static void drvMK80S_timeoutCallback(asynUser* pasynMK80SUser) { kuDebug (kuTRACE, "[drvMK80S_timeoutCallback] timeout \n"); asynMK80SUserData* pasynMK80SUserData = (asynMK80SUserData*) pasynMK80SUser->userPvt; drvMK80SConfig* pdrvMK80SConfig = (drvMK80SConfig*) pasynMK80SUserData->pdrvMK80SConfig; pdrvMK80SConfig->status |= MK80SSTATUS_TIMEOUT_MASK; epicsMutexLock(pdrvMK80SConfig->lock); pdrvMK80SConfig->cbCount =0; pdrvMK80SConfig->timeoutCount++; epicsMutexUnlock(pdrvMK80SConfig->lock); scanIoRequest(pdrvMK80SConfig->ioScanPvt); return; }
static void interruptCallbackOutput(void *drvPvt, asynUser *pasynUser, epicsInt32 value) { devInt32Pvt *pPvt = (devInt32Pvt *)drvPvt; dbCommon *pr = pPvt->pr; int count, size = sizeof(epicsInt32); asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynInt32::interruptCallbackOutput new value=%d\n", pr->name, value); epicsMutexLock(pPvt->mutexId); count = epicsRingBytesPut(pPvt->ringBuffer, (char *)&value, size); if (count != size) { pPvt->ringBufferOverflows++; } epicsMutexUnlock(pPvt->mutexId); scanOnce(pr); }
static unsigned countChanListBytes ( struct client *client, ELLLIST * pList ) { struct channel_in_use * pciu; unsigned bytes_reserved = 0; epicsMutexMustLock ( client->chanListLock ); pciu = ( struct channel_in_use * ) pList->node.next; while ( pciu ) { bytes_reserved += sizeof(struct channel_in_use); bytes_reserved += sizeof(struct event_ext)*ellCount( &pciu->eventq ); bytes_reserved += rsrvSizeOfPutNotify ( pciu->pPutNotify ); pciu = ( struct channel_in_use * ) ellNext( &pciu->node ); } epicsMutexUnlock ( client->chanListLock ); return bytes_reserved; }
static void anonymous_put(SS_ID ss, CHAN *ch) { char *var = valPtr(ch,ss); if (ch->queue) { QUEUE queue = ch->queue; pvType type = ch->type->getType; /*BUG? should that be putType?*/ size_t size = ch->type->size; boolean full; struct putq_cp_arg arg = {ch, var}; DEBUG("anonymous_put: type=%d, size=%d, count=%d, buf_size=%d, q=%p\n", type, size, ch->count, pv_size_n(type, ch->count), queue); print_channel_value(DEBUG, ch, var); /* Note: Must lock here because multiple state sets can issue pvPut calls concurrently. OTOH, no need to lock against CA callbacks, because anonymous and named PVs are disjoint. */ epicsMutexMustLock(ch->varLock); full = seqQueuePutF(queue, putq_cp, &arg); if (full) { errlogSevPrintf(errlogMinor, "pvPut on queued channel '%s' (anonymous): " "last queue element overwritten (queue is full)\n", ch->varName ); } epicsMutexUnlock(ch->varLock); } else { /* Set dirty flag only if monitored */ ss_write_buffer(ch, var, 0, ch->monitored); } /* If there's an event flag associated with this channel, set it */ if (ch->syncedTo) seq_efSet(ss, ch->syncedTo); /* Wake up each state set that uses this channel in an event */ ss_wakeup(ss->prog, ch->eventNum); }
static asynStatus readFloat64(void* ppvt,asynUser* pasynUser,epicsFloat64* value) { int addr,eom; asynStatus status; char inpBuf[BUFFER_SIZE]; Port* pport=(Port*)ppvt; Command* pcommand=(Command*)pasynUser->drvUser; if( pport->init==0 ) return( asynError ); if( pasynManager->getAddr(pasynUser,&addr)) return( asynError ); epicsMutexMustLock(pport->syncLock); status = pcommand->readFunc(pcommand,pport->pasynUser,inpBuf,sizeof(inpBuf),&eom,ifaceAsynFloat64); if( ASYN_SUCCESS(status) ) pcommand->readConv(pcommand,pasynUser,inpBuf,sizeof(epicsFloat64),value,ifaceAsynFloat64); epicsMutexUnlock(pport->syncLock); return( status ); }
static int motorAxisVelocityMove( AXIS_HDL pAxis, double min_velocity, double velocity, double acceleration ) { int status = MOTOR_AXIS_ERROR; if (pAxis == NULL) status = MOTOR_AXIS_ERROR; else { if (epicsMutexLock( pAxis->axisMutex ) == epicsMutexLockOK) { status = motorAxisVelocity( pAxis, velocity, acceleration ); motorParam->setInteger( pAxis->params, motorAxisDone, 0 ); motorParam->callCallback( pAxis->params ); epicsMutexUnlock( pAxis->axisMutex ); pAxis->print( pAxis->logParam, TRACE_FLOW, "Set card %d, axis %d move with velocity of %f, accel=%f", pAxis->card, pAxis->axis, velocity, acceleration ); } } return status; }
static int motorAxisHome( AXIS_HDL pAxis, double min_velocity, double max_velocity, double acceleration, int forwards ) { int status = MOTOR_AXIS_ERROR; if (pAxis == NULL) status = MOTOR_AXIS_ERROR; else { if (epicsMutexLock( pAxis->axisMutex ) == epicsMutexLockOK) { status = motorAxisVelocity( pAxis, (forwards? max_velocity: -max_velocity), acceleration ); pAxis->homing = 1; motorParam->setInteger( pAxis->params, motorAxisDone, 0 ); motorParam->callCallback( pAxis->params ); epicsMutexUnlock( pAxis->axisMutex ); pAxis->print( pAxis->logParam, TRACE_FLOW, "Set card %d, axis %d to home %s, min vel=%f, max_vel=%f, accel=%f", pAxis->card, pAxis->axis, (forwards?"FORWARDS":"REVERSE"), min_velocity, max_velocity, acceleration ); } } return status; }
static void interruptCallbackAverage(void *drvPvt, asynUser *pasynUser, epicsInt32 value) { devInt32Pvt *pPvt = (devInt32Pvt *)drvPvt; aiRecord *pai = (aiRecord *)pPvt->pr; if (pPvt->mask) { value &= pPvt->mask; if (pPvt->bipolar && (value & pPvt->signBit)) value |= ~pPvt->mask; } asynPrint(pPvt->pasynUser, ASYN_TRACEIO_DEVICE, "%s devAsynInt32::interruptCallbackAverage new value=%d\n", pai->name, value); epicsMutexLock(pPvt->ringBufferLock); pPvt->numAverage++; pPvt->sum += (double)value; pPvt->result.status |= pasynUser->auxStatus; epicsMutexUnlock(pPvt->ringBufferLock); }
LOCAL long devAiTPG262Read_prs(drvTPG262Config* pdrvTPG262Config, int gauge_num,double* prs) { TPG262_read* pTPG262_read = (TPG262_read*)pdrvTPG262Config->pTPG262_read; epicsMutexLock(pdrvTPG262Config->lock); switch(gauge_num) { case 0: *prs = pTPG262_read->prs0; break; case 1: *prs = pTPG262_read->prs1; break; default: *prs = -1.; } epicsMutexUnlock(pdrvTPG262Config->lock); return 0; }