/* * Ensure func() is run only once. */ void epicsThreadOnce(epicsThreadOnceId *id, void(*func)(void *), void *arg) { #define EPICS_THREAD_ONCE_DONE (epicsThreadId) 1 if (!initialized) epicsThreadInit(); epicsMutexMustLock(onceMutex); if (*id != EPICS_THREAD_ONCE_DONE) { if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */ *id = epicsThreadGetIdSelf(); /* mark active */ epicsMutexUnlock(onceMutex); func(arg); epicsMutexMustLock(onceMutex); *id = EPICS_THREAD_ONCE_DONE; /* mark done */ } else if (*id == epicsThreadGetIdSelf()) { epicsMutexUnlock(onceMutex); cantProceed("Recursive epicsThreadOnce() initialization\n"); } else while (*id != EPICS_THREAD_ONCE_DONE) { /* Another thread is in the above func(arg) call. */ epicsMutexUnlock(onceMutex); epicsThreadSleep(epicsThreadSleepQuantum()); epicsMutexMustLock(onceMutex); } } epicsMutexUnlock(onceMutex); }
static void asInitTask(ASDBCALLBACK *pcallback) { long status; taskwdInsert(epicsThreadGetIdSelf(), wdCallback, (void *)pcallback); status = asInitCommon(); taskwdRemove(epicsThreadGetIdSelf()); asInitTheadId = 0; if(pcallback) { pcallback->status = status; callbackRequest(&pcallback->callback); } }
// extern "C" int epicsShareAPI ca_clear_channel ( chid pChan ) { ca_client_context & cac = pChan->getClientCtx (); { epicsGuard < epicsMutex > guard ( cac.mutex ); try { pChan->eliminateExcessiveSendBacklog ( guard ); } catch ( cacChannel::notConnected & ) { // intentionally ignored } } if ( cac.pCallbackGuard.get() && cac.createdByThread == epicsThreadGetIdSelf () ) { epicsGuard < epicsMutex > guard ( cac.mutex ); pChan->destructor ( *cac.pCallbackGuard.get(), guard ); cac.oldChannelNotifyFreeList.release ( pChan ); } else { // // we will definately stall out here if all of the // following are true // // o user creates non-preemtive mode client library context // o user doesnt periodically call a ca function // o user calls this function from an auxiillary thread // CallbackGuard cbGuard ( cac.cbMutex ); epicsGuard < epicsMutex > guard ( cac.mutex ); pChan->destructor ( *cac.pCallbackGuard.get(), guard ); cac.oldChannelNotifyFreeList.release ( pChan ); } return ECA_NORMAL; }
void OrderedMutex::lock(const char *file, size_t line) { #ifdef DETECT_DEADLOCK LockMonitor::getInstance()->add(file, line, epicsThreadGetIdSelf(), *this); #endif if (epicsMutexLock(mutex) != epicsMutexLockOK) { if (getenv("ABORT_ON_ERRORS")) { LOG_MSG("%s (%zu): mutex lock '%s' failed\n", file, line, name.c_str()); abort(); } // else throw GenericException(file, line, "mutex lock '%s' failed", name.c_str()); } #ifdef DETECT_DEADLOCK if (getenv("TRACE_MUTEX")) { fprintf(stderr, "%25s:%4zu Lock : ", file, line); LockMonitor::getInstance()->dump(); } #endif }
/* * ca_sg_delete() */ extern "C" int epicsShareAPI ca_sg_delete ( const CA_SYNC_GID gid ) { ca_client_context * pcac; int caStatus = fetchClientContext ( & pcac ); if ( caStatus == ECA_NORMAL ) { if ( pcac->pCallbackGuard.get() && pcac->createdByThread == epicsThreadGetIdSelf () ) { epicsGuard < epicsMutex > guard ( pcac->mutex ); caStatus = ca_sync_group_destroy ( *pcac->pCallbackGuard.get(), guard, *pcac, gid ); } else { // // we will definately stall out here if all of the // following are true // // o user creates non-preemtive mode client library context // o user doesnt periodically call a ca function // o user calls this function from an auxiillary thread // CallbackGuard cbGuard ( pcac->cbMutex ); epicsGuard < epicsMutex > guard ( pcac->mutex ); caStatus = ca_sync_group_destroy ( cbGuard, guard, *pcac, gid ); } } return caStatus; }
void taskwdInsert(epicsThreadId tid, TASKWDFUNC callback, void *usr) { struct tNode *pt; struct mNode *pm; taskwdInit(); if (tid == 0) tid = epicsThreadGetIdSelf(); pt = &allocNode()->t; pt->tid = tid; pt->callback = callback; pt->usr = usr; pt->suspended = FALSE; epicsMutexMustLock(mLock); pm = (struct mNode *)ellFirst(&mList); while (pm) { if (pm->funcs->insert) { pm->funcs->insert(pm->usr, tid); } pm = (struct mNode *)ellNext(&pm->node); } epicsMutexUnlock(mLock); epicsMutexMustLock(tLock); ellAdd(&tList, (void *)pt); epicsMutexUnlock(tLock); }
void threadFunc_RTcore_DivideB(void *param) { ST_RTcore *pRTcore = (ST_RTcore*) param;; epicsThreadId pthreadInfo; #if USE_CPU_AFFINITY_RT pthreadInfo = epicsThreadGetIdSelf(); /* printf("%s: EPICS ID %p, pthreadID %lu\n", pthreadInfo->name, (void *)pthreadInfo, (unsigned long)pthreadInfo->tid); */ epicsThreadSetCPUAffinity( pthreadInfo, AFFINITY_RTCORE_DivB); epicsThreadSetPosixPriority(pthreadInfo, PRIOTY_RTCORE_DivB, "SCHED_FIFO"); #endif epicsThreadSleep(1.0); while(TRUE) { epicsEventWait( pRTcore->ST_DivThreadB.threadEventId); #if USE_RTCORE_DivB_HIGH WRITE32(pRTcore->base0 + 0x4, 0x1); #endif #if USE_RTCORE_DivB_LOW WRITE32(pRTcore->base0 + 0x4, 0x0); #endif } }
void casAttachThreadToClient ( struct client *pClient ) { epicsSignalInstallSigAlarmIgnore (); epicsSignalInstallSigPipeIgnore (); pClient->tid = epicsThreadGetIdSelf (); epicsThreadPrivateSet ( rsrvCurrentClient, pClient ); taskwdInsert ( pClient->tid, NULL, NULL ); }
void OrderedMutex::unlock() { epicsMutexUnlock(mutex); #ifdef DETECT_DEADLOCK LockMonitor::getInstance()->remove(epicsThreadGetIdSelf(), *this); if (getenv("TRACE_MUTEX")) { fprintf(stderr, " Unlock : "); LockMonitor::getInstance()->dump(); } #endif }
epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg) { static struct epicsThreadOSD threadOnceComplete; #define EPICS_THREAD_ONCE_DONE &threadOnceComplete int status; epicsThreadInit(); status = mutexLock(&onceLock); if(status) { fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n", strerror(status)); exit(-1); } if (*id != EPICS_THREAD_ONCE_DONE) { if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */ *id = epicsThreadGetIdSelf(); /* mark active */ status = pthread_mutex_unlock(&onceLock); checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); func(arg); status = mutexLock(&onceLock); checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce"); *id = EPICS_THREAD_ONCE_DONE; /* mark done */ } else if (*id == epicsThreadGetIdSelf()) { status = pthread_mutex_unlock(&onceLock); checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); cantProceed("Recursive epicsThreadOnce() initialization\n"); } else while (*id != EPICS_THREAD_ONCE_DONE) { /* Another thread is in the above func(arg) call. */ status = pthread_mutex_unlock(&onceLock); checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); epicsThreadSleep(epicsThreadSleepQuantum()); status = mutexLock(&onceLock); checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce"); } } status = pthread_mutex_unlock(&onceLock); checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce"); }
epicsShareFunc void * mallocMustSucceed(size_t size, const char *msg) { void * mem = NULL; if (size > 0) { while ((mem = malloc(size)) == NULL) { errlogPrintf("%s: mallocMustSucceed(%lu) - malloc failed\n", msg, (unsigned long)size); errlogPrintf("Thread %s (%p) suspending.\n", epicsThreadGetNameSelf(), (void *)epicsThreadGetIdSelf()); errlogFlush(); epicsThreadSuspendSelf(); } } return mem; }
epicsShareFunc void cantProceed(const char *msg, ...) { va_list pvar; va_start(pvar, msg); if (msg) errlogVprintf(msg, pvar); va_end(pvar); errlogPrintf("Thread %s (%p) can't proceed, suspending.\n", epicsThreadGetNameSelf(), (void *)epicsThreadGetIdSelf()); errlogFlush(); epicsThreadSleep(1.0); while (1) epicsThreadSuspendSelf(); }
static long doCalc(acalcoutRecord *pcalc) { calcMessage msg; int doAsync = 0; if (aCalcoutRecordDebug >= 10) printf("acalcoutRecord(%s):doCalc\n", pcalc->name); if ( acalcGetNumElements(pcalc) > aCalcAsyncThreshold ) doAsync = 1; /* if required infrastructure doesn't yet exist, create it */ if (doAsync && acalcMsgQueue == NULL) { acalcMsgQueue = epicsMessageQueueCreate(MAX_MSG, MSG_SIZE); if (acalcMsgQueue==NULL) { printf("aCalcoutRecord: Unable to create message queue\n"); return(-1); } acalcThreadId = epicsThreadCreate("acalcPerformTask", PRIORITY, epicsThreadGetStackSize(epicsThreadStackBig), (EPICSTHREADFUNC)acalcPerformTask, (void *)epicsThreadGetIdSelf()); if (acalcThreadId == NULL) { printf("aCalcoutRecord: Unable to create acalcPerformTask\n"); epicsMessageQueueDestroy(acalcMsgQueue); acalcMsgQueue = NULL; return(-1); } } /* Ideally, we should do short calculations in this thread, and queue long calculations. * But aCalcPerform is not reentrant (global value stack), so for now we queue everything. */ if (doAsync) { if (aCalcoutRecordDebug >= 2) printf("acalcoutRecord(%s):doCalc async\n", pcalc->name); pcalc->cact = 1; /* Tell caller that we went asynchronous */ msg.pcalc = pcalc; epicsMessageQueueSend(acalcMsgQueue, (void *)&msg, MSG_SIZE); return(0); } else { if (aCalcoutRecordDebug >= 2) printf("acalcoutRecord(%s):doCalc sync\n", pcalc->name); call_aCalcPerform(pcalc); } return(0); }
/* Action function for state "wait_z_pv2" in state set "reassign" */ static void A_reassign_0_wait_z_pv2(SS_ID ssId, struct UserVar *pVar, int transNum, int *pNextState) { switch(transNum) { case 0: { # line 81 "../reassign.st" testDiag("wait_z_pv2"); # line 82 "../reassign.st" testOk1(seq_pvChannelCount(ssId) == 3); # line 83 "../reassign.st" testOk1(seq_pvConnectCount(ssId) == 3); # line 84 "../reassign.st" testOk1(seq_pvAssignCount(ssId) == 3); # line 85 "../reassign.st" seqShow(epicsThreadGetIdSelf()); } return; } }
void sync_group_reset ( ca_client_context & client, CASG & sg ) { if ( client.pCallbackGuard.get() && client.createdByThread == epicsThreadGetIdSelf () ) { epicsGuard < epicsMutex > guard ( client.mutex ); sg.reset ( *client.pCallbackGuard.get(), guard ); } else { // // we will definately stall out here if all of the // following are true // // o user creates non-preemtive mode client library context // o user doesnt periodically call a ca function // o user calls this function from an auxiillary thread // CallbackGuard cbGuard ( client.cbMutex ); epicsGuard < epicsMutex > guard ( client.mutex ); sg.reset ( cbGuard, guard ); } }
/* * ca_sg_test */ extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid ) { ca_client_context * pcac; int caStatus = fetchClientContext ( &pcac ); if ( caStatus == ECA_NORMAL ) { epicsGuard < epicsMutex > guard ( pcac->mutexRef() ); CASG * pcasg = pcac->lookupCASG ( guard, gid ); if ( pcasg ) { bool isComplete; if ( pcac->pCallbackGuard.get() && pcac->createdByThread == epicsThreadGetIdSelf () ) { epicsGuard < epicsMutex > guard ( pcac->mutex ); isComplete = pcasg->ioComplete ( *pcac->pCallbackGuard.get(), guard ); } else { // // we will definately stall out here if all of the // following are true // // o user creates non-preemtive mode client library context // o user doesnt periodically call a ca function // o user calls this function from an auxiillary thread // CallbackGuard cbGuard ( pcac->cbMutex ); epicsGuard < epicsMutex > guard ( pcac->mutex ); isComplete = pcasg->ioComplete ( cbGuard, guard ); } if ( isComplete ) { caStatus = ECA_IODONE; } else{ caStatus = ECA_IOINPROGRESS; } } else { caStatus = ECA_BADSYNCGRP; } } return caStatus; }
void taskwdRemove(epicsThreadId tid) { struct tNode *pt; struct mNode *pm; char tName[40]; taskwdInit(); if (tid == 0) tid = epicsThreadGetIdSelf(); epicsMutexMustLock(tLock); pt = (struct tNode *)ellFirst(&tList); while (pt != NULL) { if (tid == pt->tid) { ellDelete(&tList, (void *)pt); epicsMutexUnlock(tLock); freeNode((union twdNode *)pt); epicsMutexMustLock(mLock); pm = (struct mNode *)ellFirst(&mList); while (pm) { if (pm->funcs->remove) { pm->funcs->remove(pm->usr, tid); } pm = (struct mNode *)ellNext(&pm->node); } epicsMutexUnlock(mLock); return; } pt = (struct tNode *)ellNext(&pt->node); } epicsMutexUnlock(tLock); epicsThreadGetName(tid, tName, sizeof(tName)); errlogPrintf("taskwdRemove: Thread %s (%p) not registered!\n", tName, (void *)tid); }
/* * caRepeaterThread () */ extern "C" void caRepeaterThread ( void * /* pDummy */ ) { taskwdInsert ( epicsThreadGetIdSelf(), NULL, NULL ); ca_repeater (); }
epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPrioritySelf(void) { epicsThreadInit(); return(epicsThreadGetPriority(epicsThreadGetIdSelf())); }
/* * sequencer() - Sequencer main thread entry point. */ void sequencer (void *arg) /* ptr to original (global) state program table */ { PROG *sp = (PROG *)arg; unsigned nss; size_t threadLen; char threadName[THREAD_NAME_SIZE+10]; /* Get this thread's id */ sp->ss->threadId = epicsThreadGetIdSelf(); /* Add the program to the program list */ seqAddProg(sp); createOrAttachPvSystem(sp); if (!pvSysIsDefined(sp->pvSys)) { sp->die = TRUE; goto exit; } /* Call sequencer init function to initialize variables. */ sp->initFunc(sp); /* Initialize state set variables. In safe mode, copy variable block to state set buffers. Must do all this before connecting. */ if (optTest(sp, OPT_SAFE)) { for (nss = 0; nss < sp->numSS; nss++) { SSCB *ss = sp->ss + nss; memcpy(ss->var, sp->var, sp->varSize); } } /* Attach to PV system */ pvSysAttach(sp->pvSys); /* Initiate connect & monitor requests to database channels, waiting for all connections to be established if the option is set. */ if (seq_connect(sp, optTest(sp, OPT_CONN) != pvStatOK)) goto exit; /* Emulate the 'first monitor event' for anonymous PVs */ if (optTest(sp, OPT_SAFE)) { unsigned nch; for (nch=0; nch<sp->numChans; nch++) if (sp->chan[nch].syncedTo && !sp->chan[nch].dbch) seq_efSet(sp->ss, sp->chan[nch].syncedTo); } /* Call program entry function if defined. Treat as if called from 1st state set. */ if (sp->entryFunc) sp->entryFunc(sp->ss); /* Create each additional state set task (additional state set thread names are derived from the first ss) */ epicsThreadGetName(sp->ss->threadId, threadName, sizeof(threadName)); threadLen = strlen(threadName); for (nss = 1; nss < sp->numSS; nss++) { SSCB *ss = sp->ss + nss; epicsThreadId tid; /* Form thread name from program name + state set number */ sprintf(threadName+threadLen, "_%d", nss); /* Spawn the task */ tid = epicsThreadCreate( threadName, /* thread name */ sp->threadPriority, /* priority */ sp->stackSize, /* stack size */ ss_entry, /* entry point */ ss); /* parameter */ DEBUG("Spawning additional state set thread %p: \"%s\"\n", tid, threadName); } /* First state set jumps directly to entry point */ ss_entry(sp->ss); DEBUG(" Wait for other state sets to exit\n"); for (nss = 1; nss < sp->numSS; nss++) { SSCB *ss = sp->ss + nss; epicsEventMustWait(ss->dead); } /* Call program exit function if defined. Treat as if called from 1st state set. */ if (sp->exitFunc) sp->exitFunc(sp->ss); exit: DEBUG(" Disconnect all channels\n"); seq_disconnect(sp); DEBUG(" Remove program instance from list\n"); seqDelProg(sp); errlogSevPrintf(errlogInfo, "Instance %d of sequencer program \"%s\" terminated\n", sp->instance, sp->progName); /* Free all allocated memory */ seq_free(sp); }
// // cac::cac () // cac::cac ( epicsMutex & mutualExclusionIn, epicsMutex & callbackControlIn, cacContextNotify & notifyIn ) : _refLocalHostName ( localHostNameCache.getReference () ), programBeginTime ( epicsTime::getCurrent() ), connTMO ( CA_CONN_VERIFY_PERIOD ), mutex ( mutualExclusionIn ), cbMutex ( callbackControlIn ), ipToAEngine ( ipAddrToAsciiEngine::allocate () ), timerQueue ( epicsTimerQueueActive::allocate ( false, lowestPriorityLevelAbove(epicsThreadGetPrioritySelf()) ) ), pUserName ( 0 ), pudpiiu ( 0 ), tcpSmallRecvBufFreeList ( 0 ), tcpLargeRecvBufFreeList ( 0 ), notify ( notifyIn ), initializingThreadsId ( epicsThreadGetIdSelf() ), initializingThreadsPriority ( epicsThreadGetPrioritySelf() ), maxRecvBytesTCP ( MAX_TCP ), maxContigFrames ( contiguousMsgCountWhichTriggersFlowControl ), beaconAnomalyCount ( 0u ), iiuExistenceCount ( 0u ), cacShutdownInProgress ( false ) { if ( ! osiSockAttach () ) { throwWithLocation ( udpiiu :: noSocket () ); } try { long status; /* * Certain os, such as HPUX, do not unblock a socket system call * when another thread asynchronously calls both shutdown() and * close(). To solve this problem we need to employ OS specific * mechanisms. */ epicsSignalInstallSigAlarmIgnore (); epicsSignalInstallSigPipeIgnore (); { char tmp[256]; size_t len; osiGetUserNameReturn gunRet; gunRet = osiGetUserName ( tmp, sizeof (tmp) ); if ( gunRet != osiGetUserNameSuccess ) { tmp[0] = '\0'; } len = strlen ( tmp ) + 1; this->pUserName = new char [ len ]; strncpy ( this->pUserName, tmp, len ); } this->_serverPort = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, static_cast <unsigned short> (CA_SERVER_PORT) ); status = envGetDoubleConfigParam ( &EPICS_CA_CONN_TMO, &this->connTMO ); if ( status ) { this->connTMO = CA_CONN_VERIFY_PERIOD; epicsGuard < epicsMutex > cbGuard ( this->cbMutex ); errlogPrintf ( "EPICS \"%s\" double fetch failed\n", EPICS_CA_CONN_TMO.name ); errlogPrintf ( "Defaulting \"%s\" = %f\n", EPICS_CA_CONN_TMO.name, this->connTMO ); } long maxBytesAsALong; status = envGetLongConfigParam ( &EPICS_CA_MAX_ARRAY_BYTES, &maxBytesAsALong ); if ( status || maxBytesAsALong < 0 ) { errlogPrintf ( "cac: EPICS_CA_MAX_ARRAY_BYTES was not a positive integer\n" ); } else { /* allow room for the protocol header so that they get the array size they requested */ static const unsigned headerSize = sizeof ( caHdr ) + 2 * sizeof ( ca_uint32_t ); ca_uint32_t maxBytes = ( unsigned ) maxBytesAsALong; if ( maxBytes < 0xffffffff - headerSize ) { maxBytes += headerSize; } else { maxBytes = 0xffffffff; } if ( maxBytes < MAX_TCP ) { errlogPrintf ( "cac: EPICS_CA_MAX_ARRAY_BYTES was rounded up to %u\n", MAX_TCP ); } else { this->maxRecvBytesTCP = maxBytes; } } freeListInitPvt ( &this->tcpSmallRecvBufFreeList, MAX_TCP, 1 ); if ( ! this->tcpSmallRecvBufFreeList ) { throw std::bad_alloc (); } freeListInitPvt ( &this->tcpLargeRecvBufFreeList, this->maxRecvBytesTCP, 1 ); if ( ! this->tcpLargeRecvBufFreeList ) { throw std::bad_alloc (); } unsigned bufsPerArray = this->maxRecvBytesTCP / comBuf::capacityBytes (); if ( bufsPerArray > 1u ) { maxContigFrames = bufsPerArray * contiguousMsgCountWhichTriggersFlowControl; } } catch ( ... ) { osiSockRelease (); delete [] this->pUserName; if ( this->tcpSmallRecvBufFreeList ) { freeListCleanup ( this->tcpSmallRecvBufFreeList ); } if ( this->tcpLargeRecvBufFreeList ) { freeListCleanup ( this->tcpLargeRecvBufFreeList ); } this->timerQueue.release (); throw; } /* * load user configured tcp name server address list, * create virtual circuits, and add them to server table */ ELLLIST dest, tmpList; ellInit ( & dest ); ellInit ( & tmpList ); addAddrToChannelAccessAddressList ( &tmpList, &EPICS_CA_NAME_SERVERS, this->_serverPort, false ); removeDuplicateAddresses ( &dest, &tmpList, 0 ); epicsGuard < epicsMutex > guard ( this->mutex ); while ( osiSockAddrNode * pNode = reinterpret_cast < osiSockAddrNode * > ( ellGet ( & dest ) ) ) { tcpiiu * piiu = NULL; SearchDestTCP * pdst = new SearchDestTCP ( *this, pNode->addr ); this->registerSearchDest ( guard, * pdst ); bool newIIU = findOrCreateVirtCircuit ( guard, pNode->addr, cacChannel::priorityDefault, piiu, CA_UKN_MINOR_VERSION, pdst ); free ( pNode ); if ( newIIU ) { piiu->start ( guard ); } } }
/* * ss_entry() - Thread entry point for all state sets. * Provides the main loop for state set processing. */ static void ss_entry(void *arg) { SSCB *ss = (SSCB *)arg; PROG *sp = ss->prog; /* Attach to PV system; was already done for the first state set */ if (ss != sp->ss) { ss->threadId = epicsThreadGetIdSelf(); createOrAttachPvSystem(sp); } /* Register this thread with the EPICS watchdog (no callback func) */ taskwdInsert(ss->threadId, 0, 0); /* In safe mode, update local var buffer with global one before entering the event loop. Must do this using ss_read_all_buffer since CA and other state sets could already post events resp. pvPut. */ if (optTest(sp, OPT_SAFE)) ss_read_all_buffer(sp, ss); /* Initial state is the first one */ ss->currentState = 0; ss->nextState = -1; ss->prevState = -1; DEBUG("ss %s: entering main loop\n", ss->ssName); /* * ============= Main loop ============== */ while (TRUE) { boolean ev_trig; int transNum = 0; /* highest prio trans. # triggered */ STATE *st = ss->states + ss->currentState; double now; /* Set state to current state */ assert(ss->currentState >= 0); /* Set state set event mask to this state's event mask */ ss->mask = st->eventMask; /* If we've changed state, do any entry actions. Also do these * even if it's the same state if option to do so is enabled. */ if (st->entryFunc && (ss->prevState != ss->currentState || optTest(st, OPT_DOENTRYFROMSELF))) { st->entryFunc(ss); } /* Flush any outstanding DB requests */ pvSysFlush(sp->pvSys); /* Setting this semaphore here guarantees that a when() is * always executed at least once when a state is first entered. */ epicsEventSignal(ss->syncSem); pvTimeGetCurrentDouble(&now); /* Set time we entered this state if transition from a different * state or else if option not to do so is off for this state. */ if ((ss->currentState != ss->prevState) || !optTest(st, OPT_NORESETTIMERS)) { ss->timeEntered = now; } ss->wakeupTime = epicsINF; /* Loop until an event is triggered, i.e. when() returns TRUE */ do { /* Wake up on PV event, event flag, or expired delay */ DEBUG("before epicsEventWaitWithTimeout(ss=%d,timeout=%f)\n", ss - sp->ss, ss->wakeupTime - now); epicsEventWaitWithTimeout(ss->syncSem, ss->wakeupTime - now); DEBUG("after epicsEventWaitWithTimeout()\n"); /* Check whether we have been asked to exit */ if (sp->die) goto exit; /* Copy dirty variable values from CA buffer * to user (safe mode only). */ if (optTest(sp, OPT_SAFE)) ss_read_all_buffer(sp, ss); ss->wakeupTime = epicsINF; /* Check state change conditions */ ev_trig = st->eventFunc(ss, &transNum, &ss->nextState); /* Clear all event flags (old ef mode only) */ if (ev_trig && !optTest(sp, OPT_NEWEF)) { unsigned i; for (i = 0; i < NWORDS(sp->numEvFlags); i++) { sp->evFlags[i] &= ~ss->mask[i]; } } if (!ev_trig) pvTimeGetCurrentDouble(&now); } while (!ev_trig); /* Execute the state change action */ st->actionFunc(ss, transNum, &ss->nextState); /* Check whether we have been asked to exit */ if (sp->die) goto exit; /* If changing state, do exit actions */ if (st->exitFunc && (ss->currentState != ss->nextState || optTest(st, OPT_DOEXITTOSELF))) { st->exitFunc(ss); } /* Change to next state */ ss->prevState = ss->currentState; ss->currentState = ss->nextState; } /* Thread exit has been requested */ exit: taskwdRemove(ss->threadId); /* Declare ourselves dead */ if (ss != sp->ss) epicsEventSignal(ss->dead); }
/* * * req_server() * * CA server task * * Waits for connections at the CA port and spawns a task to * handle each of them * */ static void req_server (void *pParm) { unsigned priorityOfSelf = epicsThreadGetPrioritySelf (); unsigned priorityOfBeacons; epicsThreadBooleanStatus tbs; struct sockaddr_in serverAddr; /* server's address */ osiSocklen_t addrSize; int status; SOCKET clientSock; epicsThreadId tid; int portChange; epicsSignalInstallSigPipeIgnore (); taskwdInsert ( epicsThreadGetIdSelf (), NULL, NULL ); rsrvCurrentClient = epicsThreadPrivateCreate (); if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) { ca_server_port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } else { ca_server_port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } if (IOC_sock != 0 && IOC_sock != INVALID_SOCKET) { epicsSocketDestroy ( IOC_sock ); } /* * Open the socket. Use ARPA Internet address format and stream * sockets. Format described in <sys/socket.h>. */ if ( ( IOC_sock = epicsSocketCreate (AF_INET, SOCK_STREAM, 0) ) == INVALID_SOCKET ) { errlogPrintf ("CAS: Socket creation error\n"); epicsThreadSuspendSelf (); } epicsSocketEnableAddressReuseDuringTimeWaitState ( IOC_sock ); /* Zero the sock_addr structure */ memset ( (void *) &serverAddr, 0, sizeof ( serverAddr ) ); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = htonl (INADDR_ANY); serverAddr.sin_port = htons ( ca_server_port ); /* get server's Internet address */ status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) ); if ( status < 0 ) { if ( SOCKERRNO == SOCK_EADDRINUSE ) { /* * enable assignment of a default port * (so the getsockname() call below will * work correctly) */ serverAddr.sin_port = ntohs (0); status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) ); } if ( status < 0 ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ( "CAS: Socket bind error was \"%s\"\n", sockErrBuf ); epicsThreadSuspendSelf (); } portChange = 1; } else { portChange = 0; } addrSize = ( osiSocklen_t ) sizeof ( serverAddr ); status = getsockname ( IOC_sock, (struct sockaddr *)&serverAddr, &addrSize); if ( status ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ( "CAS: getsockname() error %s\n", sockErrBuf ); epicsThreadSuspendSelf (); } ca_server_port = ntohs (serverAddr.sin_port); if ( portChange ) { errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n"); errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n", ca_server_port ); errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n"); errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" ); errlogPrintf ( "cas warning: reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)\n" ); } /* listen and accept new connections */ if ( listen ( IOC_sock, 20 ) < 0 ) { errlogPrintf ("CAS: Listen error\n"); epicsSocketDestroy (IOC_sock); epicsThreadSuspendSelf (); } tbs = epicsThreadHighestPriorityLevelBelow ( priorityOfSelf, &priorityOfBeacons ); if ( tbs != epicsThreadBooleanStatusSuccess ) { priorityOfBeacons = priorityOfSelf; } beacon_startStopEvent = epicsEventMustCreate(epicsEventEmpty); beacon_ctl = ctlPause; tid = epicsThreadCreate ( "CAS-beacon", priorityOfBeacons, epicsThreadGetStackSize (epicsThreadStackSmall), rsrv_online_notify_task, 0 ); if ( tid == 0 ) { epicsPrintf ( "CAS: unable to start beacon thread\n" ); } epicsEventMustWait(beacon_startStopEvent); epicsEventSignal(castcp_startStopEvent); while (TRUE) { struct sockaddr sockAddr; osiSocklen_t addLen = sizeof(sockAddr); while (castcp_ctl == ctlPause) { epicsThreadSleep(0.1); } clientSock = epicsSocketAccept ( IOC_sock, &sockAddr, &addLen ); if ( clientSock == INVALID_SOCKET ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf("CAS: Client accept error was \"%s\"\n", sockErrBuf ); epicsThreadSleep(15.0); continue; } else { epicsThreadId id; struct client *pClient; /* socket passed in is closed if unsuccessful here */ pClient = create_tcp_client ( clientSock ); if ( ! pClient ) { epicsThreadSleep ( 15.0 ); continue; } LOCK_CLIENTQ; ellAdd ( &clientQ, &pClient->node ); UNLOCK_CLIENTQ; id = epicsThreadCreate ( "CAS-client", epicsThreadPriorityCAServerLow, epicsThreadGetStackSize ( epicsThreadStackBig ), camsgtask, pClient ); if ( id == 0 ) { LOCK_CLIENTQ; ellDelete ( &clientQ, &pClient->node ); UNLOCK_CLIENTQ; destroy_tcp_client ( pClient ); errlogPrintf ( "CAS: task creation for new client failed\n" ); epicsThreadSleep ( 15.0 ); continue; } } } }
extern "C" void messageQueueTest(void *parm) { unsigned int i; char cbuf[80]; int len; int pass; int used; int want; epicsMessageQueue *q1 = new epicsMessageQueue(4, 20); testDiag("Simple single-thread tests:"); i = 0; used = 0; testOk1(q1->pending() == 0); while (q1->trySend((void *)msg1, i ) == 0) { i++; testOk(q1->pending() == i, "q1->pending() == %d", i); } testOk1(q1->pending() == 4); want = 0; len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 3); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); want++; len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 2); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); q1->trySend((void *)msg1, i++); want++; len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 2); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); q1->trySend((void *)msg1, i++); testOk1(q1->pending() == 3); i = 3; while ((len = q1->receive(cbuf, sizeof cbuf, 1.0)) >= 0) { --i; testOk(q1->pending() == i, "q1->pending() == %d", i); want++; if (!testOk1((len == want) & (strncmp(msg1, cbuf, len) == 0))) testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); } testOk1(q1->pending() == 0); testDiag("Test sender timeout:"); i = 0; used = 0; testOk1(q1->pending() == 0); while (q1->send((void *)msg1, i, 1.0 ) == 0) { i++; testOk(q1->pending() == i, "q1->pending() == %d", i); } testOk1(q1->pending() == 4); want = 0; len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 3); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); want++; len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 2); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); q1->send((void *)msg1, i++, 1.0); want++; len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 2); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); q1->send((void *)msg1, i++, 1.0); testOk1(q1->pending() == 3); i = 3; while ((len = q1->receive(cbuf, sizeof cbuf, 1.0)) >= 0) { --i; testOk(q1->pending() == i, "q1->pending() == %d", i); want++; if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); } testOk1(q1->pending() == 0); testDiag("Test receiver with timeout:"); for (i = 0 ; i < 4 ; i++) testOk1 (q1->send((void *)msg1, i, 1.0) == 0); testOk1(q1->pending() == 4); for (i = 0 ; i < 4 ; i++) testOk(q1->receive((void *)cbuf, sizeof cbuf, 1.0) == (int)i, "q1->receive(...) == %d", i); testOk1(q1->pending() == 0); testOk1(q1->receive((void *)cbuf, sizeof cbuf, 1.0) < 0); testOk1(q1->pending() == 0); testDiag("Single receiver with invalid size, single sender tests:"); epicsThreadCreate("Bad Receiver", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), badReceiver, q1); epicsThreadSleep(1.0); testOk(q1->send((void *)msg1, 10) == 0, "Send with waiting receiver"); epicsThreadSleep(2.0); testOk(q1->send((void *)msg1, 10) == 0, "Send with no receiver"); epicsThreadSleep(2.0); testDiag("Single receiver, single sender tests:"); epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityHigh); epicsThreadCreate("Receiver one", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), receiver, q1); for (pass = 1 ; pass <= 3 ; pass++) { for (i = 0 ; i < 10 ; i++) { if (q1->trySend((void *)msg1, i) < 0) break; if (pass >= 3) epicsThreadSleep(0.5); } switch (pass) { case 1: if (i<6) testDiag(" priority-based scheduler, sent %d messages", i); epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityLow); break; case 2: if (i<10) testDiag(" scheduler not strict priority, sent %d messages", i); else testDiag(" strict priority scheduler, sent 10 messages"); break; case 3: testOk(i == 10, "%d of 10 messages sent with sender pauses", i); break; } epicsThreadSleep(1.0); } /* * Single receiver, multiple sender tests */ testDiag("Single receiver, multiple sender tests:"); testDiag("This test takes 5 minutes..."); epicsThreadCreate("Sender 1", epicsThreadPriorityLow, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); epicsThreadCreate("Sender 2", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); epicsThreadCreate("Sender 3", epicsThreadPriorityHigh, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); epicsThreadCreate("Sender 4", epicsThreadPriorityHigh, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); epicsThreadSleep(300.0); testExit = 1; }
/* * RSRV_ONLINE_NOTIFY_TASK */ void rsrv_online_notify_task(void *pParm) { unsigned priorityOfSelf = epicsThreadGetPrioritySelf (); osiSockAddrNode *pNode; double delay; double maxdelay; long longStatus; double maxPeriod; caHdr msg; int status; SOCKET sock; int intTrue = TRUE; unsigned short port; ca_uint32_t beaconCounter = 0; char * pStr; int autoBeaconAddr; ELLLIST autoAddrList; char buf[16]; unsigned priorityOfUDP; epicsThreadBooleanStatus tbs; epicsThreadId tid; taskwdInsert (epicsThreadGetIdSelf(),NULL,NULL); if ( envGetConfigParamPtr ( & EPICS_CAS_BEACON_PERIOD ) ) { longStatus = envGetDoubleConfigParam ( & EPICS_CAS_BEACON_PERIOD, & maxPeriod ); } else { longStatus = envGetDoubleConfigParam ( & EPICS_CA_BEACON_PERIOD, & maxPeriod ); } if (longStatus || maxPeriod<=0.0) { maxPeriod = 15.0; epicsPrintf ("EPICS \"%s\" float fetch failed\n", EPICS_CAS_BEACON_PERIOD.name); epicsPrintf ("Setting \"%s\" = %f\n", EPICS_CAS_BEACON_PERIOD.name, maxPeriod); } delay = 0.02; /* initial beacon period in sec */ maxdelay = maxPeriod; /* * Open the socket. * Use ARPA Internet address format and datagram socket. * Format described in <sys/socket.h>. */ if ( (sock = epicsSocketCreate (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) { errlogPrintf ("CAS: online socket creation error\n"); epicsThreadSuspendSelf (); } status = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *)&intTrue, sizeof(intTrue)); if (status<0) { errlogPrintf ("CAS: online socket set up error\n"); epicsThreadSuspendSelf (); } { /* * this connect is to supress a warning message on Linux * when we shutdown the read side of the socket. If it * fails (and it will on old ip kernels) we just ignore * the failure. */ osiSockAddr sockAddr; sockAddr.ia.sin_family = AF_UNSPEC; sockAddr.ia.sin_port = htons ( 0 ); sockAddr.ia.sin_addr.s_addr = htonl (0); connect ( sock, & sockAddr.sa, sizeof ( sockAddr.sa ) ); shutdown ( sock, SHUT_RD ); } memset((char *)&msg, 0, sizeof msg); msg.m_cmmd = htons (CA_PROTO_RSRV_IS_UP); msg.m_count = htons (ca_server_port); msg.m_dataType = htons (CA_MINOR_PROTOCOL_REVISION); ellInit ( & beaconAddrList ); ellInit ( & autoAddrList ); pStr = envGetConfigParam(&EPICS_CAS_AUTO_BEACON_ADDR_LIST, sizeof(buf), buf); if ( ! pStr ) { pStr = envGetConfigParam(&EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf); } if (pStr) { if (strstr(pStr,"no")||strstr(pStr,"NO")) { autoBeaconAddr = FALSE; } else if (strstr(pStr,"yes")||strstr(pStr,"YES")) { autoBeaconAddr = TRUE; } else { fprintf(stderr, "CAS: EPICS_CA(S)_AUTO_ADDR_LIST = \"%s\"? Assuming \"YES\"\n", pStr); autoBeaconAddr = TRUE; } } else { autoBeaconAddr = TRUE; } /* * load user and auto configured * broadcast address list */ if (envGetConfigParamPtr(&EPICS_CAS_BEACON_PORT)) { port = envGetInetPortConfigParam (&EPICS_CAS_BEACON_PORT, (unsigned short) CA_REPEATER_PORT ); } else { port = envGetInetPortConfigParam (&EPICS_CA_REPEATER_PORT, (unsigned short) CA_REPEATER_PORT ); } /* * discover beacon addresses associated with this interface */ if ( autoBeaconAddr ) { osiSockAddr addr; ELLLIST tmpList; ellInit ( &tmpList ); addr.ia.sin_family = AF_UNSPEC; osiSockDiscoverBroadcastAddresses (&tmpList, sock, &addr); forcePort ( &tmpList, port ); removeDuplicateAddresses ( &autoAddrList, &tmpList, 1 ); } /* * by default use EPICS_CA_ADDR_LIST for the * beacon address list */ { const ENV_PARAM *pParam; if (envGetConfigParamPtr(&EPICS_CAS_INTF_ADDR_LIST) || envGetConfigParamPtr(&EPICS_CAS_BEACON_ADDR_LIST)) { pParam = &EPICS_CAS_BEACON_ADDR_LIST; } else { pParam = &EPICS_CA_ADDR_LIST; } /* * add in the configured addresses */ addAddrToChannelAccessAddressList ( &autoAddrList, pParam, port, pParam == &EPICS_CA_ADDR_LIST ); } removeDuplicateAddresses ( &beaconAddrList, &autoAddrList, 0 ); if ( ellCount ( &beaconAddrList ) == 0 ) { errlogPrintf ("The CA server's beacon address list was empty after initialization?\n"); } # ifdef DEBUG printChannelAccessAddressList (&beaconAddrList); # endif tbs = epicsThreadHighestPriorityLevelBelow ( priorityOfSelf, &priorityOfUDP ); if ( tbs != epicsThreadBooleanStatusSuccess ) { priorityOfUDP = priorityOfSelf; } casudp_startStopEvent = epicsEventMustCreate(epicsEventEmpty); casudp_ctl = ctlPause; tid = epicsThreadCreate ( "CAS-UDP", priorityOfUDP, epicsThreadGetStackSize (epicsThreadStackMedium), cast_server, 0 ); if ( tid == 0 ) { epicsPrintf ( "CAS: unable to start UDP daemon thread\n" ); } epicsEventMustWait(casudp_startStopEvent); epicsEventSignal(beacon_startStopEvent); while (TRUE) { pNode = (osiSockAddrNode *) ellFirst (&beaconAddrList); while (pNode) { char buf[64]; status = connect (sock, &pNode->addr.sa, sizeof(pNode->addr.sa)); if (status<0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); ipAddrToDottedIP (&pNode->addr.ia, buf, sizeof(buf)); errlogPrintf ( "%s: CA beacon routing (connect to \"%s\") error was \"%s\"\n", __FILE__, buf, sockErrBuf); } else { struct sockaddr_in if_addr; osiSocklen_t size = sizeof (if_addr); status = getsockname (sock, (struct sockaddr *) &if_addr, &size); if (status<0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ( "%s: CA beacon routing (getsockname) error was \"%s\"\n", __FILE__, sockErrBuf); } else if (if_addr.sin_family==AF_INET) { msg.m_available = if_addr.sin_addr.s_addr; msg.m_cid = htonl ( beaconCounter ); status = send (sock, (char *)&msg, sizeof(msg), 0); if (status < 0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); ipAddrToDottedIP (&pNode->addr.ia, buf, sizeof(buf)); errlogPrintf ( "%s: CA beacon (send to \"%s\") error was \"%s\"\n", __FILE__, buf, sockErrBuf); } else { assert (status == sizeof(msg)); } } } pNode = (osiSockAddrNode *) pNode->node.next; } epicsThreadSleep(delay); if (delay<maxdelay) { delay *= 2.0; if (delay>maxdelay) { delay = maxdelay; } } beaconCounter++; /* expected to overflow */ while (beacon_ctl == ctlPause) { epicsThreadSleep(0.1); delay = 0.02; /* Restart beacon timing if paused */ } } }
void threadFunc_EC1_ANT_RT (void *param) { ST_STD_device *pSTDmy = (ST_STD_device*) param; ST_EC1_ANT *pEC1_ANT; ST_MASTER *pMaster = NULL; epicsThreadId pthreadInfo; //int nFirst = 1; //int toggle = 1; pMaster = get_master(); if(!pMaster) return; pEC1_ANT = (ST_EC1_ANT *)pSTDmy->pUser; if( !pEC1_ANT ) { printf("ERROR! threadFunc_user_DAQ() has null pointer of pEC1_ANT.\n"); return; } #if USE_CPU_AFFINITY_RT pthreadInfo = epicsThreadGetIdSelf(); printf("%s: EPICS ID %p, pthreadID %lu\n", pthreadInfo->name, (void *)pthreadInfo, (unsigned long)pthreadInfo->tid); epicsThreadSetCPUAffinity( pthreadInfo, "5"); epicsThreadSetPosixPriority(pthreadInfo, PRIOTY_EC1_ANT, "SCHED_FIFO"); #endif int num_samples = 1; float read_buf[num_samples]; int scans_read; while(TRUE) { #if 0 epicsEventWait (pSTDmy->ST_RTthread.threadEventId); // pSTDmy->StatusDev |= TASK_WAIT_FOR_TRIGGER; // notify_refresh_master_status(); nFirst = 1; toggle = 1; printf("%s: Got epics RT Run event.\n", pSTDmy->taskName); #endif #if 0 while(TRUE) { got = read(pEC1_ANT->fd_event, &nval, 4); toggle = 0; pSTDmy->rtCnt++; if( nFirst ) { send_master_stop_event(); nFirst = 0; } if( pEC1_ANT->useScanIoRequest ) { scanIoRequest(pSTDmy->ioScanPvt_userCall); } if( !(pSTDmy->StatusDev & TASK_IN_PROGRESS ) ) { pSTDmy->StatusDev &= ~TASK_WAIT_FOR_TRIGGER; printf("system stop!.. bye RT thread!\n"); break; } } #else while (TRUE) { // read scaled samples for synchronization with PCSRT1 if (0 > (scans_read = pxi6259_read_ai (pEC1_ANT->channelFD, read_buf, num_samples))) { epicsThreadSleep (0.00001); continue; } kuDebug (kuDEBUG, "[EC1_ANT_RT] schedule RfmHandler ...\n"); // schedule RfmHandler epicsEventSignal (pEC1_ANT->ctrlRunEventId); } #endif if( pMaster->cUseAutoSave ) { //db_put("HICS_EC1_ANT_SEND_DATA", "1"); } } }
/* * Process breakpoint * Returns a zero if dbProcess() is to execute * record support, a one if dbProcess() is to * skip over record support. See dbProcess(). * * 1. See if there is at least a breakpoint set somewhere * in precord's lockset. If not, return immediately. * 2. Check the disable flag. * 3. Add entry points to the queue for future stepping and * schedule new entrypoints for the continuation task. * 4. Check the pact flag. * 5. Check to see if there is a breakpoint set in a record, and * if so, turn on stepping mode. * 6. If stepping mode is set, stop and report the breakpoint. */ int epicsShareAPI dbBkpt(dbCommon *precord) { struct LS_LIST *pnode; struct EP_LIST *pqe; /* * It is crucial that operations in dbBkpt() execute * in the correct order or certain features in the * breakpoint handler will not work as expected. */ /* * Take and give a semaphore to check for breakpoints * every time a record is processed. Slow. Thank * goodness breakpoint checking is turned off during * normal operation. */ epicsMutexMustLock(bkpt_stack_sem); FIND_LOCKSET(precord, pnode); epicsMutexUnlock(bkpt_stack_sem); if (pnode == NULL) { /* no breakpoints in precord's lockset */ return(0); } /* Check disable flag */ dbGetLink(&(precord->sdis),DBR_SHORT,&(precord->disa),0,0); if (precord->disa == precord->disv) { /* * Do not process breakpoints if the record is disabled, * but allow disable alarms. Alarms will be raised * in dbProcess() because returning 0 allows dbProcess() * to continue. However processing will be prevented * because disa and disv will be examined again in * dbProcess(). Note that checking for pact will occur * before checking for disa and disv in dbProcess(). */ return(0); } /* * Queue entry points for future stepping. The taskid comparison * is used to determine if the source of processing is the * continuation task or an external source. If it is an external * source, queue its execution, but dump out of dbProcess without * calling record support. */ if (pnode->taskid && (epicsThreadGetIdSelf() != pnode->taskid)) { /* CONTINUE TASK CANNOT ENTER HERE */ /* * Add an entry point to queue, if it does * not already exist. */ FIND_QUEUE_ENTRY(&pnode->ep_queue, pqe, precord); if (pqe == NULL) { pqe = (struct EP_LIST *) malloc(sizeof(struct EP_LIST)); if (pqe == NULL) return(1); pqe->entrypoint = precord; pqe->count = 1; epicsTimeGetCurrent(&pqe->time); pqe->sched = 0; #ifdef BKPT_DIAG printf(" BKPT> Adding entrypoint %s to queue\n", precord->name); #endif /* * Take semaphore, wait on continuation task */ epicsMutexMustLock(bkpt_stack_sem); /* Add entry to queue */ ellAdd(&pnode->ep_queue, (ELLNODE *)pqe); epicsMutexUnlock(bkpt_stack_sem); } else { if (pqe->count < MAX_EP_COUNT) pqe->count++; } /* check pact */ if (! precord->pact) { /* schedule if pact not set */ pqe->sched = 1; /* * Release the semaphore, letting the continuation * task begin execution of the new entrypoint. */ epicsEventSignal(pnode->ex_sem); } return(1); } /* * Don't mess with breakpoints if pact set! Skip * over rest of dbProcess() since we don't want * alarms going off. The pact flag is checked * AFTER entry point queuing so that the record * timing feature will work properly. */ if (precord->pact) return(1); /* Turn on stepping mode if a breakpoint is found */ if (precord->bkpt & BKPT_ON_MASK) { pnode->step = 1; #ifdef BKPT_DIAG printf(" BKPT> Bkpt detected: %s\n", precord->name); #endif } /* * If we are currently stepping through the lockset, * suspend task. */ if (pnode->step) { printf("\n BKPT> Stopped at: %s within Entrypoint: %s\n-> ", precord->name, pnode->current_ep->name); pnode->precord = precord; /* Move current lockset to top of stack */ ellDelete(&lset_stack, (ELLNODE *)pnode); ellInsert(&lset_stack, NULL, (ELLNODE *)pnode); /* * Unlock database while the task suspends itself. This * is done so that dbb() dbd() dbc() dbs() may be used * when the task is suspended. Scan tasks that also * use the scan lock feature will not be hung during * a breakpoint, so that records in other locksets will * continue to be processed. Cross your fingers, this * might actually work ! */ epicsMutexUnlock(bkpt_stack_sem); dbScanUnlock(precord); epicsThreadSuspendSelf(); dbScanLock(precord); epicsMutexMustLock(bkpt_stack_sem); } return(0); }
void threadFunc_RTcore_RT(void *param) { ST_STD_device *pSTDdev = (ST_STD_device*) param; ST_RTcore *pRTcore; // ST_MASTER *pMaster = NULL; ST_STD_device *pSTDRMchk = NULL; ST_RMCHK *pRMCHK; epicsThreadId pthreadInfo; int got; int nval; int nFirst = 1; // pMaster = get_master(); // if(!pMaster) return; pRTcore = (ST_RTcore *)pSTDdev->pUser; if( !pRTcore ) { printf("ERROR! threadFunc_user_DAQ() has null pointer of pRTcore.\n"); return; } /********************************************/ /* to get RFM, RMcheck device */ pSTDRMchk = get_STDev_from_type(STR_DEVICE_TYPE_2); if( !pSTDRMchk ) { printf("ERROR! threadFunc_RTcore_RT() has null pointer of Target device.\n"); return; } else { printf("target RMchk: %p, eventID:%d\n", pSTDRMchk, pSTDRMchk->ST_DAQThread.threadEventId ); } pRMCHK = (ST_RMCHK *)pSTDRMchk->pUser; if( !pRMCHK ) { printf("ERROR! threadFunc_RTcore_RT() has null pointer of pRMCHK.\n"); return; } /*********************/ #if USE_CPU_AFFINITY_RT pthreadInfo = epicsThreadGetIdSelf(); printf("%s: EPICS ID %p, pthreadID %lu\n", pthreadInfo->name, (void *)pthreadInfo, (unsigned long)pthreadInfo->tid); epicsThreadSetCPUAffinity( pthreadInfo, AFFINITY_RTCORE_RT); epicsThreadSetPosixPriority(pthreadInfo, PRIOTY_RTCORE_RT, "SCHED_FIFO"); #endif while(TRUE) { epicsEventWait( pSTDdev->ST_RTthread.threadEventId); nFirst = 1; rt_toggle = 1; printf("%s: Got epics RT Run event.\n", pSTDdev->taskName); while(TRUE) { got = read(pRTcore->fd_event, &nval, 4); #if USE_KERNEL_ACK_HIGH WRITE32(pRTcore->base0 + 0x4, 0x1); #endif #if USE_KERNEL_ACK_LOW WRITE32(pRTcore->base0 + 0x4, 0x0); #endif if( rt_toggle ) { /* Half clock, 10Khz, when 20Khz */ rt_toggle = 0; epicsEventSignal( pSTDdev->ST_DAQThread.threadEventId ); epicsEventSignal( pSTDRMchk->ST_DAQThread.threadEventId ); } else rt_toggle = 1; #if USE_DIVIDER_A if( (pSTDdev->stdCoreCnt % DIVIDER_A) == 0) { // value is 4, 5KHz if Mclk is 20Khz epicsEventSignal( pRTcore->ST_DivThreadA.threadEventId ); } #endif #if USE_DIVIDER_B if( (pSTDdev->stdCoreCnt % DIVIDER_B) == 0) { // value is 20, 1KHz if Mclk is 20Khz epicsEventSignal( pRTcore->ST_DivThreadB.threadEventId ); } #endif pSTDdev->stdCoreCnt++; /* not use scanIoRequest() */ if( nFirst ) { send_master_stop_event(); nFirst = 0; } if( !(pSTDdev->StatusDev & TASK_IN_PROGRESS ) ) { pSTDdev->StatusDev &= ~TASK_WAIT_FOR_TRIGGER; printf("system stop!.. bye RT thread!\n"); break; } } } }
void threadFunc_RTcore_DAQ(void *param) { ST_STD_device *pSTDdev = (ST_STD_device*) param; ST_RTcore *pRTcore; ST_MASTER *pMaster = NULL; ST_STD_device *pSTDRMchk = NULL; ST_RMCHK *pRMCHK; epicsThreadId pthreadInfo; ST_User_Buf_node queueData; ST_buf_node *pbufferNode = NULL; pMaster = get_master(); if(!pMaster) return; if( !pSTDdev ) { printf("ERROR! threadFunc_user_DAQ() has null pointer of STD device.\n"); return; } pRTcore = (ST_RTcore *)pSTDdev->pUser; if( !pRTcore ) { printf("ERROR! threadFunc_user_DAQ() has null pointer of pRTcore.\n"); return; } /* get RFM device ******************************************* */ pSTDRMchk = get_STDev_from_type(STR_DEVICE_TYPE_2); if( !pSTDRMchk ) { printf("ERROR! threadFunc_RTcore_DAQ() has null pointer of Dev2.\n"); return; } else { printf("target RMchk: %p, eventID:%d\n", pSTDRMchk, pSTDRMchk->ST_DAQThread.threadEventId ); } pRMCHK = (ST_RMCHK *)pSTDRMchk->pUser; if( !pRMCHK ) { printf("ERROR! threadFunc_RTcore_RT() has null pointer of pRMCHK.\n"); return; } /*********************************************************** */ #if USE_CPU_AFFINITY_RT pthreadInfo = epicsThreadGetIdSelf(); /* printf("%s: EPICS ID %p, pthreadID %lu\n", pthreadInfo->name, (void *)pthreadInfo, (unsigned long)pthreadInfo->tid); */ epicsThreadSetCPUAffinity( pthreadInfo, AFFINITY_RTCORE_DAQ); epicsThreadSetPosixPriority(pthreadInfo, PRIOTY_RTCORE_DAQ, "SCHED_FIFO"); #endif #if USE_RTCORE_DAQRING epicsThreadSleep(1.0); pbufferNode = (ST_buf_node *)ellFirst(pSTDdev->pList_BufferNode); ellDelete(pSTDdev->pList_BufferNode, &pbufferNode->node); #endif while(TRUE) { epicsEventWait( pSTDdev->ST_DAQThread.threadEventId); #if USE_RTCORE_DAQ_HIGH WRITE32(pRTcore->base0 + 0x4, 0x1); #endif #if USE_RTCORE_DAQ_LOW WRITE32(pRTcore->base0 + 0x4, 0x0); #endif #if USE_RTCORE_DAQRING pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 0] = pRMCHK->mapBuf[RM_PCS_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 1] = pRMCHK->mapBuf[RM_PF1_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 2] = pRMCHK->mapBuf[RM_PF2_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 3] = pRMCHK->mapBuf[RM_PF3U_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 4] = pRMCHK->mapBuf[RM_PF3L_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 5] = pRMCHK->mapBuf[RM_PF4U_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 6] = pRMCHK->mapBuf[RM_PF4L_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 7] = pRMCHK->mapBuf[RM_PF5U_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 8] = pRMCHK->mapBuf[RM_PF5L_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 9] = pRMCHK->mapBuf[RM_PF6U_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 10] = pRMCHK->mapBuf[RM_PF6L_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 11] = pRMCHK->mapBuf[RM_PF7_CNT/4]; pbufferNode->data[pRTcore->cntDAQ_loop * LOOP_ELM + 12] = pRMCHK->mapBuf[RM_IVC_CNT/4]; // pRTcore->cntDAQ++; pRTcore->cntDAQ_loop++; pRTcore->cntAccum += LOOP_ELM; if( pRTcore->cntDAQ_loop >= LOOP_CNT ) { queueData.pNode = pbufferNode; queueData.timeStamp = 0x0; epicsMessageQueueSend(pSTDdev->ST_RingBufThread.threadQueueId, (void*) &queueData, sizeof(ST_User_Buf_node)); pbufferNode = (ST_buf_node *)ellFirst(pSTDdev->pList_BufferNode); ellDelete(pSTDdev->pList_BufferNode, &pbufferNode->node); pRTcore->cntDAQ_loop = 0; } #endif pSTDdev->stdDAQCnt++; if( pRTcore->useScanIoRequest ) scanIoRequest(pSTDdev->ioScanPvt_userCall); } }
void threadFunc_RTcore_RingBuf(void *param) { int i, ellCnt; epicsThreadId pthreadInfo; ST_STD_device *pSTDdev = (ST_STD_device*) param; ST_User_Buf_node queueData; ST_buf_node *pbufferNode; ST_RTcore *pRTcore; pRTcore = (ST_RTcore *)pSTDdev->pUser; #if 0 epicsPrintf("\n %s: pSTDdev: %p, p16aiss8ao4: %p , pST_BuffThread: %p\n",pSTDdev->taskName, pSTDdev, p16aiss8ao4, pST_BufThread ); #endif for(i = 0; i< MAX_RING_BUF_NUM; i++) { ST_buf_node *pbufferNode1 = NULL; pbufferNode1 = (ST_buf_node*) malloc(sizeof(ST_buf_node)); if(!pbufferNode1) { epicsPrintf("\n>>> threadFunc_user_RingBuf: malloc(sizeof(ST_buf_node))... fail\n"); return; } ellAdd(pSTDdev->pList_BufferNode, &pbufferNode1->node); } epicsPrintf(" %s: create %d node (size:%dKB)\n", pSTDdev->ST_RingBufThread.threadName, MAX_RING_BUF_NUM, sizeof(ST_buf_node)/1024 ); #if 0 epicsPrintf(">>> %s, ellCnt:%d\n", pringThreadConfig->threadName, ellCount(p16aiss8ao4->pdrvBufferConfig->pbufferList)); #endif #if USE_CPU_AFFINITY_RT pthreadInfo = epicsThreadGetIdSelf(); /* printf("%s: EPICS ID %p, pthreadID %lu\n", pthreadInfo->name, (void *)pthreadInfo, (unsigned long)pthreadInfo->tid); */ epicsThreadSetCPUAffinity( pthreadInfo, AFFINITY_RTCORE_RING); epicsThreadSetPosixPriority(pthreadInfo, PRIOTY_RTCORE_RING, "SCHED_FIFO"); #endif while(TRUE) { epicsMessageQueueReceive(pSTDdev->ST_RingBufThread.threadQueueId, (void*) &queueData, sizeof(ST_User_Buf_node)); pbufferNode = queueData.pNode; /* fwrite( pbufferNode->data, sizeof(unsigned int), LOOP_CNT*LOOP_ELM, pRTcore->fp_raw); */ ellAdd(pSTDdev->pList_BufferNode, &pbufferNode->node); ellCnt = ellCount(pSTDdev->pList_BufferNode); /* printf("RTcore_RingBuf, ellCnt: %d\n", ellCnt); */ } /* while(TRUE) */ return; }