/* Starts "mcnt" jobs in a pool with initial and max * thread counts "icnt" and "mcnt". * The test ensures that all jobs run in parallel. * "cork" checks the function of pausing the run queue * with epicsThreadPoolQueueRun */ static void postjobs(size_t icnt, size_t mcnt, int cork) { size_t i; epicsThreadPool *pool; countPriv *priv=callocMustSucceed(1, sizeof(*priv), "postjobs priv alloc"); priv->guard=epicsMutexMustCreate(); priv->done=epicsEventMustCreate(epicsEventEmpty); priv->allrunning=epicsEventMustCreate(epicsEventEmpty); priv->count=mcnt; priv->job=callocMustSucceed(mcnt, sizeof(*priv->job), "postjobs job array"); testDiag("postjobs(%lu,%lu)", (unsigned long)icnt, (unsigned long)mcnt); { epicsThreadPoolConfig conf; epicsThreadPoolConfigDefaults(&conf); conf.initialThreads=icnt; conf.maxThreads=mcnt; testOk1((pool=epicsThreadPoolCreate(&conf))!=NULL); if(!pool) return; } if(cork) epicsThreadPoolControl(pool, epicsThreadPoolQueueRun, 0); for(i=0; i<mcnt; i++) { testDiag("i=%lu", (unsigned long)i); priv->job[i] = epicsJobCreate(pool, &countjob, priv); testOk1(priv->job[i]!=NULL); testOk1(epicsJobQueue(priv->job[i])==0); } if(cork) { /* no jobs should have run */ epicsMutexMustLock(priv->guard); testOk1(priv->count==mcnt); epicsMutexUnlock(priv->guard); epicsThreadPoolControl(pool, epicsThreadPoolQueueRun, 1); } testDiag("Waiting for all jobs to start"); epicsEventMustWait(priv->allrunning); testDiag("Stop all"); epicsEventSignal(priv->done); for(i=0; i<mcnt; i++) { testDiag("i=%lu", (unsigned long)i); epicsJobDestroy(priv->job[i]); } epicsThreadPoolDestroy(pool); epicsMutexDestroy(priv->guard); epicsEventDestroy(priv->allrunning); epicsEventDestroy(priv->done); free(priv->job); free(priv); }
static void errlogInitPvt(void *arg) { struct initArgs *pconfig = (struct initArgs *) arg; epicsThreadId tid; pvtData.errlogInitFailed = TRUE; pvtData.buffersize = pconfig->bufsize; pvtData.maxMsgSize = pconfig->maxMsgSize; pvtData.msgNeeded = adjustToWorstCaseAlignment(pvtData.maxMsgSize + sizeof(msgNode)); ellInit(&pvtData.listenerList); ellInit(&pvtData.msgQueue); pvtData.toConsole = TRUE; pvtData.console = stderr; pvtData.waitForWork = epicsEventMustCreate(epicsEventEmpty); pvtData.listenerLock = epicsMutexMustCreate(); pvtData.msgQueueLock = epicsMutexMustCreate(); pvtData.waitForFlush = epicsEventMustCreate(epicsEventEmpty); pvtData.flush = epicsEventMustCreate(epicsEventEmpty); pvtData.flushLock = epicsMutexMustCreate(); pvtData.waitForExit = epicsEventMustCreate(epicsEventEmpty); pvtData.pbuffer = callocMustSucceed(1, pvtData.buffersize, "errlogInitPvt"); errSymBld(); /* Better not to do this lazily... */ tid = epicsThreadCreate("errlog", epicsThreadPriorityLow, epicsThreadGetStackSize(epicsThreadStackSmall), (EPICSTHREADFUNC)errlogThread, 0); if (tid) { pvtData.errlogInitFailed = FALSE; } }
static int testInit(const char *port,int addr, cmdInfo **ppcmdInfo, threadInfo **ppthreadInfo,int ind,FILE *file) { cmdInfo *pcmdInfo; threadInfo *pthreadInfo; asynUser *pasynUser; asynStatus status; asynInterface *pasynInterface; size_t size; pcmdInfo = (cmdInfo *)pasynManager->memMalloc(sizeof(cmdInfo)); memset(pcmdInfo,0,sizeof(cmdInfo)); *ppcmdInfo = pcmdInfo; size = sizeof(threadInfo) + (strlen(port)+ 1) + (strlen(thread) + 2); pthreadInfo = (threadInfo *)pasynManager->memMalloc(size); memset(pthreadInfo,0,sizeof(threadInfo)); pthreadInfo->size = size; *ppthreadInfo = pthreadInfo; pthreadInfo->portName = (char *)(pthreadInfo +1); strcpy(pthreadInfo->portName,port); pthreadInfo->threadName = pthreadInfo->portName + strlen(pthreadInfo->portName) + 1; sprintf(pthreadInfo->threadName,"%s%1.1d",thread,ind); pcmdInfo->callbackDone = epicsEventMustCreate(epicsEventEmpty); pthreadInfo->work = epicsEventMustCreate(epicsEventEmpty); pthreadInfo->done = epicsEventMustCreate(epicsEventEmpty); pthreadInfo->tid = epicsThreadCreate(pthreadInfo->threadName, epicsThreadPriorityHigh, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC)workThread,pthreadInfo); if(!pthreadInfo->tid) { fprintf(pcmdInfo->file,"epicsThreadCreate failed\n"); return -1; } pcmdInfo->pasynUser = pasynManager->createAsynUser( workCallback,timeoutCallback); pasynUser = pcmdInfo->pasynUser; pasynUser->userPvt = pcmdInfo; status = pasynManager->connectDevice(pasynUser,port,addr); if(status!=asynSuccess) { fprintf(pcmdInfo->file,"connectDevice failed %s\n",pasynUser->errorMessage); return -1; } pasynInterface = pasynManager->findInterface(pasynUser, asynCommonType, 1); if(!pasynInterface) { fprintf(pcmdInfo->file,"can't find asynCommon\n"); return -1; } pcmdInfo->pasynCommon = (asynCommon *) pasynInterface->pinterface; pcmdInfo->asynCommonPvt = pasynInterface->drvPvt; pcmdInfo->file = file; pcmdInfo->pthreadInfo = pthreadInfo; pthreadInfo->pcmdInfo = pcmdInfo; return 0; }
epicsShareFunc int asynShowEos(const char *portName, int addr, enum eosType type) { asynInterface *pasynInterface; eosArgs eosargs; asynUser *pasynUser; if (findInterface(portName, addr, asynOctetType, getEos, &pasynUser, &pasynInterface) != asynSuccess) return asynError; pasynUser->timeout = 2; pasynUser->userPvt = &eosargs; pasynUser->reason = ASYN_REASON_QUEUE_EVEN_IF_NOT_CONNECTED; eosargs.pasynOctet = (asynOctet *)pasynInterface->pinterface; eosargs. drvPvt = pasynInterface->drvPvt; eosargs.type = type; eosargs.done = epicsEventMustCreate(epicsEventEmpty); eosargs.status = pasynManager->queueRequest(pasynUser, asynQueuePriorityConnect, 0.0); if (eosargs.status == asynSuccess) epicsEventWait(eosargs.done); epicsEventDestroy(eosargs.done); if (eosargs.status != asynSuccess) printf("Set EOS failed: %s\n", pasynUser->errorMessage); pasynManager->freeAsynUser(pasynUser); if (eosargs.status == asynSuccess) { char cbuf[4*sizeof eosargs.eos + 2]; epicsStrnEscapedFromRaw(cbuf, sizeof cbuf, eosargs.eos, eosargs.eosLen); printf("\"%s\"\n", cbuf); } return eosargs.status; }
static void initPeriodic(void) { dbMenu *pmenu = dbFindMenu(pdbbase, "menuScan"); double quantum = epicsThreadSleepQuantum(); int i; if (!pmenu) { errlogPrintf("initPeriodic: menuScan not present\n"); return; } nPeriodic = pmenu->nChoice - SCAN_1ST_PERIODIC; papPeriodic = dbCalloc(nPeriodic, sizeof(periodic_scan_list*)); periodicTaskId = dbCalloc(nPeriodic, sizeof(void *)); for (i = 0; i < nPeriodic; i++) { periodic_scan_list *ppsl = dbCalloc(1, sizeof(periodic_scan_list)); const char *choice = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC]; double number; char *unit; int status = epicsParseDouble(choice, &number, &unit); ppsl->scan_list.lock = epicsMutexMustCreate(); ellInit(&ppsl->scan_list.list); ppsl->name = choice; if (status || number == 0) { errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice); ppsl->period = i; } else if (!*unit || !epicsStrCaseCmp(unit, "second") || !epicsStrCaseCmp(unit, "seconds")) { ppsl->period = number; } else if (!epicsStrCaseCmp(unit, "minute") || !epicsStrCaseCmp(unit, "minutes")) { ppsl->period = number * 60; } else if (!epicsStrCaseCmp(unit, "hour") || !epicsStrCaseCmp(unit, "hours")) { ppsl->period = number * 60 * 60; } else if (!epicsStrCaseCmp(unit, "Hz") || !epicsStrCaseCmp(unit, "Hertz")) { ppsl->period = 1 / number; } else { errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice); ppsl->period = i; } number = ppsl->period / quantum; if ((ppsl->period < 2 * quantum) || (number / floor(number) > 1.1)) { errlogPrintf("initPeriodic: Scan rate '%s' is not achievable.\n", choice); } ppsl->scanCtl = ctlPause; ppsl->loopEvent = epicsEventMustCreate(epicsEventEmpty); papPeriodic[i] = ppsl; } }
epicsShareFunc int asynSetOption(const char *portName, int addr, const char *key, const char *val) { asynUser *pasynUser; asynInterface *pasynInterface; setOptionArgs optionargs; if ((key == NULL) || (val == NULL)) { printf("Missing key/value argument\n"); return asynError; } if (findInterface(portName, addr, asynOptionType, setOption, &pasynUser, &pasynInterface) != asynSuccess) return asynError; pasynUser->timeout = 2; pasynUser->userPvt = &optionargs; pasynUser->reason = ASYN_REASON_QUEUE_EVEN_IF_NOT_CONNECTED; optionargs.pasynOption = (asynOption *)pasynInterface->pinterface; optionargs. drvPvt = pasynInterface->drvPvt; optionargs.key = key; optionargs.val = val; optionargs.done = epicsEventMustCreate(epicsEventEmpty); if (pasynManager->queueRequest(pasynUser,asynQueuePriorityConnect,0.0) != asynSuccess) { printf("queueRequest failed: %s\n", pasynUser->errorMessage); epicsEventDestroy(optionargs.done); pasynManager->freeAsynUser(pasynUser); return asynError; } epicsEventWait(optionargs.done); epicsEventDestroy(optionargs.done); pasynManager->freeAsynUser(pasynUser); return asynSuccess; }
static asynStatus asynSetEos(const char *portName, int addr, enum eosType type, const char *eos) { asynUser *pasynUser; asynInterface *pasynInterface; eosArgs eosargs; if (eos == NULL) { printf("Missing EOS argument\n"); return asynError; } eosargs.eosLen = epicsStrnRawFromEscaped(eosargs.eos, sizeof eosargs.eos, eos, strlen(eos)); if (eosargs.eosLen >= sizeof eosargs.eos) { printf("End of string argument \"%s\" too long.\n", eos); return asynError; } if (findInterface(portName, addr, asynOctetType, setEos, &pasynUser, &pasynInterface) != asynSuccess) return asynError; pasynUser->timeout = 2; pasynUser->userPvt = &eosargs; pasynUser->reason = ASYN_REASON_QUEUE_EVEN_IF_NOT_CONNECTED; eosargs.pasynOctet = (asynOctet *)pasynInterface->pinterface; eosargs. drvPvt = pasynInterface->drvPvt; eosargs.type = type; eosargs.done = epicsEventMustCreate(epicsEventEmpty); eosargs.status = pasynManager->queueRequest(pasynUser, asynQueuePriorityConnect, 0.0); if (eosargs.status == asynSuccess) epicsEventWait(eosargs.done); epicsEventDestroy(eosargs.done); if (eosargs.status != asynSuccess) printf("Set EOS failed: %s\n", pasynUser->errorMessage); pasynManager->freeAsynUser(pasynUser); return eosargs.status; }
void callbackInit(void) { int i; int j; char threadName[32]; if (callbackIsInit) { errlogMessage("Warning: callbackInit called again before callbackCleanup\n"); return; } callbackIsInit = 1; if(!startStopEvent) startStopEvent = epicsEventMustCreate(epicsEventEmpty); cbCtl = ctlRun; timerQueue = epicsTimerQueueAllocate(0, epicsThreadPriorityScanHigh); for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) { epicsThreadId tid; callbackQueue[i].semWakeUp = epicsEventMustCreate(epicsEventEmpty); callbackQueue[i].queue = epicsRingPointerLockedCreate(callbackQueueSize); if (callbackQueue[i].queue == 0) cantProceed("epicsRingPointerLockedCreate failed for %s\n", threadNamePrefix[i]); callbackQueue[i].queueOverflow = FALSE; if (callbackQueue[i].threadsConfigured == 0) callbackQueue[i].threadsConfigured = callbackThreadsDefault; for (j = 0; j < callbackQueue[i].threadsConfigured; j++) { if (callbackQueue[i].threadsConfigured > 1 ) sprintf(threadName, "%s-%d", threadNamePrefix[i], j); else strcpy(threadName, threadNamePrefix[i]); tid = epicsThreadCreate(threadName, threadPriority[i], epicsThreadGetStackSize(epicsThreadStackBig), (EPICSTHREADFUNC)callbackTask, &priorityValue[i]); if (tid == 0) { cantProceed("Failed to spawn callback thread %s\n", threadName); } else { epicsEventWait(startStopEvent); epicsAtomicIncrIntT(&callbackQueue[i].threadsRunning); } } } }
static epicsThreadOSD * create_threadInfo(const char *name) { epicsThreadOSD *pthreadInfo; pthreadInfo = callocMustSucceed(1,sizeof(*pthreadInfo),"create_threadInfo"); pthreadInfo->suspendEvent = epicsEventMustCreate(epicsEventEmpty); pthreadInfo->name = epicsStrDup(name); return pthreadInfo; }
void dbCaLinkInitIsolated(void) { if (!workListLock) workListLock = epicsMutexMustCreate(); if (!workListEvent) workListEvent = epicsEventMustCreate(epicsEventEmpty); dbCaCtl = ctlExit; epicsAtExit(dbCaExit, NULL); }
void dbCaLinkInit(void) { dbServiceIOInit(); dbCaLinkInitIsolated(); startStopEvent = epicsEventMustCreate(epicsEventEmpty); dbCaCtl = ctlPause; epicsThreadCreate("dbCaLink", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackBig), dbCaTask, NULL); epicsEventMustWait(startStopEvent); }
static void initOnce(void) { if ((onceQ = epicsRingPointerCreate(onceQueueSize)) == NULL) { cantProceed("initOnce: Ring buffer create failed\n"); } onceSem = epicsEventMustCreate(epicsEventEmpty); onceTaskId = epicsThreadCreate("scanOnce", epicsThreadPriorityScanLow + nPeriodic, epicsThreadGetStackSize(epicsThreadStackBig), onceTask, 0); epicsEventWait(startStopEvent); }
static void twdInitOnce(void *arg) { epicsThreadId tid; tLock = epicsMutexMustCreate(); mLock = epicsMutexMustCreate(); fLock = epicsMutexMustCreate(); ellInit(&fList); VALGRIND_CREATE_MEMPOOL(&fList, 0, 0); twdCtl = twdctlRun; loopEvent = epicsEventMustCreate(epicsEventEmpty); exitEvent = epicsEventMustCreate(epicsEventEmpty); tid = epicsThreadCreate("taskwd", epicsThreadPriorityLow, epicsThreadGetStackSize(epicsThreadStackSmall), twdTask, NULL); if (tid == 0) cantProceed("Failed to spawn task watchdog thread\n"); epicsAtExit(twdShutdown, NULL); }
static struct eventNode * getEventNode(epicsMessageQueueId pmsg) { struct eventNode *evp; evp = reinterpret_cast < struct eventNode * > ( ellGet(&pmsg->eventFreeList) ); if (evp == NULL) { evp = (struct eventNode *) callocMustSucceed(1, sizeof(*evp), "epicsMessageQueueGetEventNode"); evp->event = epicsEventMustCreate(epicsEventEmpty); } return evp; }
/* Test re-queueing a job while it is running. * Check that a single job won't run concurrently. */ static void testreadd(void) { epicsThreadPoolConfig conf; epicsThreadPool *pool; readdPriv *priv=callocMustSucceed(1, sizeof(*priv), "testcleanup priv"); readdPriv *priv2=callocMustSucceed(1, sizeof(*priv), "testcleanup priv"); testDiag("testreadd"); priv->done=epicsEventMustCreate(epicsEventEmpty); priv->count=5; priv2->done=epicsEventMustCreate(epicsEventEmpty); priv2->count=5; epicsThreadPoolConfigDefaults(&conf); conf.maxThreads = 2; testOk1((pool=epicsThreadPoolCreate(&conf))!=NULL); if(!pool) return; testOk1((priv->job=epicsJobCreate(pool, &readdjob, priv))!=NULL); testOk1((priv2->job=epicsJobCreate(pool, &readdjob, priv2))!=NULL); testOk1(epicsJobQueue(priv->job)==0); testOk1(epicsJobQueue(priv2->job)==0); epicsEventMustWait(priv->done); epicsEventMustWait(priv2->done); testOk1(epicsThreadPoolNThreads(pool)==2); testDiag("epicsThreadPoolNThreads = %d", epicsThreadPoolNThreads(pool)); epicsThreadPoolDestroy(pool); epicsEventDestroy(priv->done); epicsEventDestroy(priv2->done); free(priv); free(priv2); }
long scanInit(void) { int i; startStopEvent = epicsEventMustCreate(epicsEventEmpty); scanCtl = ctlPause; initPeriodic(); initOnce(); buildScanLists(); for (i = 0; i < nPeriodic; i++) spawnPeriodic(i); return 0; }
static void ClockTime_InitOnce(void *pfirst) { *(int *) pfirst = 1; ClockTimePvt.loopEvent = epicsEventMustCreate(epicsEventEmpty); ClockTimePvt.lock = epicsMutexCreate(); epicsAtExit(ClockTime_Shutdown, NULL); /* Register the iocsh commands */ iocshRegister(&ReportFuncDef, ReportCallFunc); iocshRegister(&ShutdownFuncDef, ShutdownCallFunc); /* Register as a time provider */ generalTimeRegisterCurrentProvider("OS Clock", LAST_RESORT_PRIORITY, ClockTimeGetCurrent); }
void verifyTryLock () { struct verifyTryLock verify; verify.mutex = epicsMutexMustCreate (); verify.done = epicsEventMustCreate ( epicsEventEmpty ); testOk1(epicsMutexTryLock(verify.mutex) == epicsMutexLockOK); epicsThreadCreate ( "verifyTryLockThread", 40, epicsThreadGetStackSize(epicsThreadStackSmall), verifyTryLockThread, &verify ); testOk1(epicsEventWait ( verify.done ) == epicsEventWaitOK); epicsMutexUnlock ( verify.mutex ); epicsMutexDestroy ( verify.mutex ); epicsEventDestroy ( verify.done ); }
int devIocStatsInitCpuUsage(void) { int nBurnNoContention = 0; double tToWait = SECONDS_TO_BURN; epicsTimeStamp tStart, tEnd; if (cpuUsage.startSem) return 0; /* Initialize only if OS wants to spin */ if (tToWait > 0) { /*wait for a tick*/ epicsTimeGetCurrent(&tStart); do { epicsTimeGetCurrent(&tEnd); } while ( epicsTimeDiffInSeconds(&tEnd, &tStart) <= 0.0 ); epicsTimeGetCurrent(&tStart); while(TRUE) { cpuBurn(); epicsTimeGetCurrent(&tEnd); cpuUsage.tNow = epicsTimeDiffInSeconds(&tEnd, &tStart); if (cpuUsage.tNow >= tToWait ) break; nBurnNoContention++; } cpuUsage.nBurnNoContention = nBurnNoContention; cpuUsage.nBurnNow = nBurnNoContention; cpuUsage.startSem = epicsEventMustCreate(epicsEventFull); cpuUsage.tNoContention = cpuUsage.tNow; /* * FIXME: epicsThreadPriorityMin is not really the lowest * priority. We could use a native call to * lower our priority further but OTOH there is not * much going on at these low levels... */ epicsThreadCreate("cpuUsageTask", epicsThreadPriorityMin, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC)cpuUsageTask, 0); } else { cpuUsage.startSem = 0; } return 0; }
/* Start one thread per CPU which will all try lock * the same spinlock. They break as soon as one * fails to take the lock. */ static void verifyTryLock() { int N, i; struct verifyTryLock verify; N = epicsThreadGetCPUs(); if(N==1) { testSkip(1, "verifyTryLock() only for SMP systems"); return; } verify.flag = 0; verify.spin = epicsSpinMustCreate(); testDiag("Starting %d spinners", N); verify.ents = calloc(N, sizeof(*verify.ents)); for(i=0; i<N; i++) { verify.ents[i].main = &verify; verify.ents[i].done = epicsEventMustCreate(epicsEventEmpty); epicsThreadMustCreate("verifyTryLockThread", 40, epicsThreadGetStackSize(epicsThreadStackSmall), verifyTryLockThread, &verify.ents[i]); } testDiag("All started"); for(i=0; i<N; i++) { epicsEventMustWait(verify.ents[i].done); epicsEventDestroy(verify.ents[i].done); } testDiag("All done"); testOk(verify.flag==1, "epicsTryLock returns %d (expect 1)", verify.flag); epicsSpinDestroy(verify.spin); free(verify.ents); }
static void NTPTime_InitOnce(void *pprio) { struct timespec timespecNow; NTPTimePvt.synchronize = 1; NTPTimePvt.synchronized = 0; NTPTimePvt.loopEvent = epicsEventMustCreate(epicsEventEmpty); NTPTimePvt.syncsFailed = 0; NTPTimePvt.lock = epicsMutexCreate(); /* Initialize OS-dependent code */ osdNTPInit(); /* Try to sync with NTP server */ if (!osdNTPGet(×pecNow)) { NTPTimePvt.syncTick = osdTickGet(); if (timespecNow.tv_sec > POSIX_TIME_AT_EPICS_EPOCH && epicsTimeOK == epicsTimeFromTimespec(&NTPTimePvt.syncTime, ×pecNow)) { NTPTimePvt.clockTick = NTPTimePvt.syncTick; NTPTimePvt.clockTime = NTPTimePvt.syncTime; NTPTimePvt.synchronized = 1; } } /* Start the sync thread */ epicsThreadCreate("NTPTimeSync", epicsThreadPriorityHigh, epicsThreadGetStackSize(epicsThreadStackSmall), NTPTimeSync, NULL); epicsAtExit(NTPTime_Shutdown, NULL); /* Register the iocsh commands */ iocshRegister(&ReportFuncDef, ReportCallFunc); iocshRegister(&ShutdownFuncDef, ShutdownCallFunc); /* Finally register as a time provider */ generalTimeRegisterCurrentProvider("NTP", *(int *)pprio, NTPTimeGetCurrent); }
static void testSingleThreading(void) { int i; testsingle data[2]; xdrv *drvs[2]; memset(data, 0, sizeof(data)); for(i=0; i<2; i++) { int p; for(p=0; p<NUM_CALLBACK_PRIORITIES; p++) { data[i].wake[p] = epicsEventMustCreate(epicsEventEmpty); data[i].wait[p] = epicsEventMustCreate(epicsEventEmpty); } } testDiag("Test single-threaded I/O Intr scanning"); testdbPrepare(); testdbReadDatabase("dbTestIoc.dbd", NULL, NULL); dbTestIoc_registerRecordDeviceDriver(pdbbase); /* create two scan lists with one record on each of three priorities */ /* group#, member#, priority */ loadRecord(0, 0, "LOW"); loadRecord(1, 0, "LOW"); loadRecord(0, 1, "MEDIUM"); loadRecord(1, 1, "MEDIUM"); loadRecord(0, 2, "HIGH"); loadRecord(1, 2, "HIGH"); drvs[0] = xdrv_add(0, &testcb, &data[0]); drvs[1] = xdrv_add(1, &testcb, &data[1]); scanIoSetComplete(drvs[0]->scan, &testcomp, &data[0]); scanIoSetComplete(drvs[1]->scan, &testcomp, &data[1]); eltc(0); testIocInitOk(); eltc(1); testDiag("Scan first list"); scanIoRequest(drvs[0]->scan); testDiag("Scan second list"); scanIoRequest(drvs[1]->scan); testDiag("Wait for first list to complete"); for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) epicsEventMustWait(data[0].wait[i]); testDiag("Wait one more second"); epicsThreadSleep(1.0); testOk1(data[0].hasprocd[0]==1); testOk1(data[0].hasprocd[1]==1); testOk1(data[0].hasprocd[2]==1); testOk1(data[0].getcomplete[0]==1); testOk1(data[0].getcomplete[1]==1); testOk1(data[0].getcomplete[2]==1); testOk1(data[1].hasprocd[0]==0); testOk1(data[1].hasprocd[1]==0); testOk1(data[1].hasprocd[2]==0); testOk1(data[1].getcomplete[0]==0); testOk1(data[1].getcomplete[1]==0); testOk1(data[1].getcomplete[2]==0); testDiag("Release the first scan and wait for the second"); for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) epicsEventMustTrigger(data[0].wake[i]); for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) epicsEventMustWait(data[1].wait[i]); testOk1(data[0].hasprocd[0]==1); testOk1(data[0].hasprocd[1]==1); testOk1(data[0].hasprocd[2]==1); testOk1(data[0].getcomplete[0]==1); testOk1(data[0].getcomplete[1]==1); testOk1(data[0].getcomplete[2]==1); testOk1(data[1].hasprocd[0]==1); testOk1(data[1].hasprocd[1]==1); testOk1(data[1].hasprocd[2]==1); testOk1(data[1].getcomplete[0]==1); testOk1(data[1].getcomplete[1]==1); testOk1(data[1].getcomplete[2]==1); testDiag("Release the second scan and complete"); for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) epicsEventMustTrigger(data[1].wake[i]); testIocShutdownOk(); testdbCleanup(); xdrv_reset(); for(i=0; i<2; i++) { int p; for(p=0; p<NUM_CALLBACK_PRIORITIES; p++) { epicsEventDestroy(data[i].wake[p]); epicsEventDestroy(data[i].wait[p]); } } }
int MM4000AsynConfig(int card, /* Controller number */ const char *portName, /* asyn port name of serial or GPIB port */ int asynAddress, /* asyn subaddress for GPIB */ int numAxes, /* Number of axes this controller supports */ int movingPollPeriod, /* Time to poll (msec) when an axis is in motion */ int idlePollPeriod) /* Time to poll (msec) when an axis is idle. 0 for no polling */ { AXIS_HDL pAxis; int axis; MM4000Controller *pController; char threadName[20]; int status; int totalAxes; int loopState; int digits; int modelNum; int retry = 0; char *p, *tokSave; char inputBuff[BUFFER_SIZE]; char outputBuff[BUFFER_SIZE]; if (numMM4000Controllers < 1) { printf("MM4000Config: no MM4000 controllers allocated, call MM4000Setup first\n"); return MOTOR_AXIS_ERROR; } if ((card < 0) || (card >= numMM4000Controllers)) { printf("MM4000Config: card must in range 0 to %d\n", numMM4000Controllers-1); return MOTOR_AXIS_ERROR; } if ((numAxes < 1) || (numAxes > MM4000_MAX_AXES)) { printf("MM4000Config: numAxes must in range 1 to %d\n", MM4000_MAX_AXES); return MOTOR_AXIS_ERROR; } pController = &pMM4000Controller[card]; pController->pAxis = (AXIS_HDL) calloc(numAxes, sizeof(motorAxis)); pController->numAxes = numAxes; pController->movingPollPeriod = movingPollPeriod/1000.; pController->idlePollPeriod = idlePollPeriod/1000.; status = pasynOctetSyncIO->connect(portName, asynAddress, &pController->pasynUser, NULL); if (status != asynSuccess) { printf("MM4000AsynConfig: cannot connect to asyn port %s\n", portName); return MOTOR_AXIS_ERROR; } do { status = sendAndReceive(pController, "VE;", inputBuff, sizeof(inputBuff)); retry++; /* Return value is length of response string */ } while (status != asynSuccess && retry < 3); if (status != asynSuccess) return (MOTOR_AXIS_ERROR); strcpy(pController->firmwareVersion, &inputBuff[2]); /* Skip "VE" */ /* Set Motion Master model indicator. */ p = strstr(pController->firmwareVersion, "MM"); if (p == NULL) { printf("MM4000AsynConfig: invalid model = %s\n", pController->firmwareVersion); return MOTOR_AXIS_ERROR; } modelNum = atoi(p+2); if (modelNum == 4000) pController->model = MM4000; else if (modelNum == 4005 || modelNum == 4006) pController->model = MM4005; else { printf("MM4000AsynConfig: invalid model = %s\n", pController->firmwareVersion); return MOTOR_AXIS_ERROR; } sendAndReceive(pController, "TP;", inputBuff, sizeof(inputBuff)); /* The return string will tell us how many axes this controller has */ for (totalAxes = 0, tokSave = NULL, p = epicsStrtok_r(inputBuff, ",", &tokSave); p != 0; p = epicsStrtok_r(NULL, ",", &tokSave), totalAxes++) ; if (totalAxes < numAxes) { printf("MM4000AsynConfig: actual number of axes=%d < numAxes=%d\n", totalAxes, numAxes); return MOTOR_AXIS_ERROR; } for (axis=0; axis<numAxes; axis++) { pAxis = &pController->pAxis[axis]; pAxis->pController = pController; pAxis->card = card; pAxis->axis = axis; pAxis->mutexId = epicsMutexMustCreate(); pAxis->params = motorParam->create(0, MOTOR_AXIS_NUM_PARAMS); /* Determine if encoder present based on open/closed loop mode. */ sprintf(outputBuff, "%dTC", axis+1); sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); loopState = atoi(&inputBuff[3]); /* Skip first 3 characters */ if (loopState != 0) pAxis->closedLoop = 1; /* Determine drive resolution. */ sprintf(outputBuff, "%dTU", axis+1); sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); pAxis->stepSize = atof(&inputBuff[3]); digits = (int) -log10(pAxis->stepSize) + 2; if (digits < 1) digits = 1; pAxis->maxDigits = digits; /* Save home preset position. */ sprintf(outputBuff, "%dXH", axis+1); sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); pAxis->homePreset = atof(&inputBuff[3]); /* Determine low limit */ sprintf(outputBuff, "%dTL", axis+1); sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); pAxis->lowLimit = atof(&inputBuff[3]); /* Determine high limit */ sprintf(outputBuff, "%dTR", axis+1); sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); pAxis->highLimit = atof(&inputBuff[3]); } pController->pollEventId = epicsEventMustCreate(epicsEventEmpty); /* Create the poller thread for this controller */ epicsSnprintf(threadName, sizeof(threadName), "MM4000:%d", card); epicsThreadCreate(threadName, epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC) MM4000Poller, (void *) pController); return MOTOR_AXIS_OK; }
/* * * 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; } } } }
/* * rsrv_init () */ int rsrv_init (void) { epicsThreadBooleanStatus tbs; unsigned priorityOfConnectDaemon; epicsThreadId tid; long maxBytesAsALong; long status; clientQlock = epicsMutexMustCreate(); ellInit ( &clientQ ); freeListInitPvt ( &rsrvClientFreeList, sizeof(struct client), 8 ); freeListInitPvt ( &rsrvChanFreeList, sizeof(struct channel_in_use), 512 ); freeListInitPvt ( &rsrvEventFreeList, sizeof(struct event_ext), 512 ); freeListInitPvt ( &rsrvSmallBufFreeListTCP, MAX_TCP, 16 ); initializePutNotifyFreeList (); status = envGetLongConfigParam ( &EPICS_CA_MAX_ARRAY_BYTES, &maxBytesAsALong ); if ( status || maxBytesAsALong < 0 ) { errlogPrintf ( "CAS: EPICS_CA_MAX_ARRAY_BYTES was not a positive integer\n" ); rsrvSizeofLargeBufTCP = MAX_TCP; } 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 ( "CAS: EPICS_CA_MAX_ARRAY_BYTES was rounded up to %u\n", MAX_TCP ); rsrvSizeofLargeBufTCP = MAX_TCP; } else { rsrvSizeofLargeBufTCP = maxBytes; } } freeListInitPvt ( &rsrvLargeBufFreeListTCP, rsrvSizeofLargeBufTCP, 1 ); ellInit ( &beaconAddrList ); prsrv_cast_client = NULL; pCaBucket = NULL; castcp_startStopEvent = epicsEventMustCreate(epicsEventEmpty); castcp_ctl = ctlPause; /* * go down two levels so that we are below * the TCP and event threads started on behalf * of individual clients */ tbs = epicsThreadHighestPriorityLevelBelow ( epicsThreadPriorityCAServerLow, &priorityOfConnectDaemon ); if ( tbs == epicsThreadBooleanStatusSuccess ) { tbs = epicsThreadHighestPriorityLevelBelow ( priorityOfConnectDaemon, &priorityOfConnectDaemon ); if ( tbs != epicsThreadBooleanStatusSuccess ) { priorityOfConnectDaemon = epicsThreadPriorityCAServerLow; } } else { priorityOfConnectDaemon = epicsThreadPriorityCAServerLow; } tid = epicsThreadCreate ( "CAS-TCP", priorityOfConnectDaemon, epicsThreadGetStackSize(epicsThreadStackMedium), req_server, 0); if ( tid == 0 ) { epicsPrintf ( "CAS: unable to start connection request thread\n" ); } epicsEventMustWait(castcp_startStopEvent); return RSRV_OK; }
/** * Constructor */ ADSBIG::ADSBIG(const char *portName, int maxBuffers, size_t maxMemory) : ADDriver(portName, 1, NUM_DRIVER_PARAMS, maxBuffers, maxMemory, asynInt32Mask | asynInt32ArrayMask | asynDrvUserMask, asynInt32Mask | asynFloat64Mask, ASYN_CANBLOCK | ASYN_MULTIDEVICE, 1, 0, 0) { int status = 0; const char *functionName = "ADSBIG::ADSBIG"; m_Acquiring = 0; m_CamWidth = 0; m_CamHeight = 0; m_aborted = false; //Create the epicsEvents for signaling the readout thread. m_startEvent = epicsEventMustCreate(epicsEventEmpty); if (!m_startEvent) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s epicsEventCreate failure for start event.\n", functionName); return; } m_stopEvent = epicsEventMustCreate(epicsEventEmpty); if (!m_stopEvent) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s epicsEventCreate failure for stop event.\n", functionName); return; } //Add the params to the paramLib //createParam adds the parameters to all param lists automatically (using maxAddr). createParam(ADSBIGFirstParamString, asynParamInt32, &ADSBIGFirstParam); createParam(ADSBIGDarkFieldParamString, asynParamInt32, &ADSBIGDarkFieldParam); createParam(ADSBIGReadoutModeParamString, asynParamInt32, &ADSBIGReadoutModeParam); createParam(ADSBIGPercentCompleteParamString, asynParamFloat64, &ADSBIGPercentCompleteParam); createParam(ADSBIGTEStatusParamString, asynParamInt32, &ADSBIGTEStatusParam); createParam(ADSBIGTEPowerParamString, asynParamFloat64, &ADSBIGTEPowerParam); createParam(ADSBIGLastParamString, asynParamInt32, &ADSBIGLastParam); //Connect to camera here and get library handle printf("%s Connecting to camera...\n", functionName); p_Cam = new CSBIGCam(DEV_USB1); PAR_ERROR cam_err = CE_NO_ERROR; if (p_Cam == NULL) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s. CSBIGCam constructor failed. p_Cam is NULL.\n", functionName); return; } if ((cam_err = p_Cam->GetError()) != CE_NO_ERROR) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s. CSBIGCam constructor failed. %s\n", functionName, p_Cam->GetErrorString(cam_err).c_str()); return; } if ((cam_err = p_Cam->EstablishLink()) != CE_NO_ERROR) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s. Failed to establish link to camera. %s\n", functionName, p_Cam->GetErrorString(cam_err).c_str()); return; } printf("%s Successfully connected to camera: %s\n", functionName, p_Cam->GetCameraTypeString().c_str()); //Set some default camera modes p_Cam->SetActiveCCD(CCD_IMAGING); p_Cam->SetReadoutMode(RM_1X1); p_Cam->SetExposureTime(1); //A lot of defaults are set in the CSBIGCam::Init function as well. //FastReadout only seems to apply to the STF-8300. p_Cam->SetABGState(ABG_LOW7); p_Cam->SetFastReadout(false); p_Cam->SetDualChannelMode(false); if ((cam_err = p_Cam->GetFullFrame(m_CamWidth, m_CamHeight)) != CE_NO_ERROR) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s. Failed to read camera dimensions. %s\n", functionName, p_Cam->GetErrorString(cam_err).c_str()); return; } else { printf("%s Camera Width: %d\n", functionName, m_CamWidth); printf("%s Camera Height: %d\n", functionName, m_CamHeight); } //SetSubFrame is called again when we change the ReadoutMode (ie. do on-chip binning). p_Cam->SetSubFrame(0, 0, m_CamWidth, m_CamHeight); //Create image object p_Img = new CSBIGImg(); if (p_Img->AllocateImageBuffer(m_CamWidth, m_CamHeight) != TRUE) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s. Failed to allocate image buffer for maximum image size.\n", functionName); return; } bool paramStatus = true; //Initialise any paramLib parameters that need passing up to device support paramStatus = ((setStringParam(ADManufacturer, "SBIG") == asynSuccess) && paramStatus); paramStatus = ((setStringParam(ADModel, p_Cam->GetCameraTypeString().c_str()) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADMaxSizeX, m_CamWidth) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADMaxSizeY, m_CamHeight) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADSizeX, m_CamWidth) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADSizeY, m_CamHeight) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADBinX, 1) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADBinY, 1) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADMinX, 0) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADMinY, 0) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADNumExposures, 1) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADNumImages, 1) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADImageMode, ADImageSingle) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADTriggerMode, ADTriggerInternal) == asynSuccess) && paramStatus); paramStatus = ((setDoubleParam(ADAcquireTime, 1.0) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(NDDataType, NDUInt16) == asynSuccess) && paramStatus); paramStatus = ((setDoubleParam(ADTemperatureActual, 0.0) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADSBIGDarkFieldParam, 0) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADSBIGReadoutModeParam, 0) == asynSuccess) && paramStatus); paramStatus = ((setDoubleParam(ADSBIGPercentCompleteParam, 0.0) == asynSuccess) && paramStatus); paramStatus = ((setIntegerParam(ADSBIGTEStatusParam, 0) == asynSuccess) && paramStatus); paramStatus = ((setDoubleParam(ADSBIGTEPowerParam, 0.0) == asynSuccess) && paramStatus); if (!paramStatus) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s Unable To Set Driver Parameters In Constructor.\n", functionName); return; } //Create the thread that reads the data status = (epicsThreadCreate("ADSBIGReadoutTask", epicsThreadPriorityHigh, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC)ADSBIGReadoutTaskC, this) == NULL); if (status) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s epicsThreadCreate failure for ADSBIGReadoutTask.\n", functionName); return; } //Create the thread that periodically reads the temperature and readout progress status = (epicsThreadCreate("ADSBIGPollingTask", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC)ADSBIGPollingTaskC, this) == NULL); if (status) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s epicsThreadCreate failure for ADSBIGPollingTask.\n", functionName); return; } printf("%s Created OK.\n", functionName); }
static void testMultiThreading(void) { int i; int masks[2]; testmulti data[6]; xdrv *drvs[2]; memset(masks, 0, sizeof(masks)); memset(data, 0, sizeof(data)); for(i=0; i<NELEMENTS(data); i++) { data[i].wake = epicsEventMustCreate(epicsEventEmpty); data[i].wait = epicsEventMustCreate(epicsEventEmpty); } testDiag("Test multi-threaded I/O Intr scanning"); testdbPrepare(); testdbReadDatabase("dbTestIoc.dbd", NULL, NULL); dbTestIoc_registerRecordDeviceDriver(pdbbase); /* create two scan lists with one record on each of three priorities */ /* group#, member#, priority */ loadRecord(0, 0, "LOW"); loadRecord(1, 1, "LOW"); loadRecord(0, 2, "MEDIUM"); loadRecord(1, 3, "MEDIUM"); loadRecord(0, 4, "HIGH"); loadRecord(1, 5, "HIGH"); drvs[0] = xdrv_add(0, &testcbmulti, data); drvs[1] = xdrv_add(1, &testcbmulti, data); scanIoSetComplete(drvs[0]->scan, &testcompmulti, &masks[0]); scanIoSetComplete(drvs[1]->scan, &testcompmulti, &masks[1]); /* just enough workers to process all records concurrently */ callbackParallelThreads(2, "LOW"); callbackParallelThreads(2, "MEDIUM"); callbackParallelThreads(2, "HIGH"); eltc(0); testIocInitOk(); eltc(1); testDiag("Scan first list"); testOk1(scanIoRequest(drvs[0]->scan)==0x7); testDiag("Scan second list"); testOk1(scanIoRequest(drvs[1]->scan)==0x7); testDiag("Wait for everything to start"); for(i=0; i<NELEMENTS(data); i++) epicsEventMustWait(data[i].wait); testDiag("Wait one more second"); epicsThreadSleep(1.0); for(i=0; i<NELEMENTS(data); i++) { testOk(data[i].hasprocd==1, "data[%d].hasprocd==1 (%d)", i, data[i].hasprocd); testOk(data[i].getcomplete==0, "data[%d].getcomplete==0 (%d)", i, data[i].getcomplete); } testDiag("Release all and complete"); for(i=0; i<NELEMENTS(data); i++) epicsEventMustTrigger(data[i].wake); testIocShutdownOk(); for(i=0; i<NELEMENTS(data); i++) { testOk(data[i].getcomplete==1, "data[%d].getcomplete==0 (%d)", i, data[i].getcomplete); } testOk1(masks[0]==0x7); testOk1(masks[1]==0x7); testdbCleanup(); xdrv_reset(); for(i=0; i<NELEMENTS(data); i++) { epicsEventDestroy(data[i].wake); epicsEventDestroy(data[i].wait); } }
static void testUDP(void) { caster_t caster; shSocket sender; osiSockAddr dest; union casterUDP buf; shSocketInit(&sender); sender.sd = shCreateSocket(AF_INET, SOCK_DGRAM, 0); if(sender.sd==INVALID_SOCKET) { testAbort("Failed to create socket"); return; } lock = epicsMutexMustCreate(); cycled[0] = epicsEventMustCreate(epicsEventEmpty); cycled[1] = epicsEventMustCreate(epicsEventEmpty); casterInit(&caster); caster.udpport = 0; /* test with random port */ caster.testhook = &testerhook; epicsThreadMustCreate("udptester", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackSmall), &tester, &caster); epicsEventSignal(cycled[1]); /* wait for tester thread to setup socket */ epicsEventMustWait(cycled[0]); epicsMutexMustLock(lock); testOk1(caster.udpport!=0); testDiag("UDP test with port %d", caster.udpport); memset(&dest, 0, sizeof(dest)); dest.ia.sin_family = AF_INET; dest.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK); dest.ia.sin_port = htons(caster.udpport); epicsMutexUnlock(lock); /* allow tester thread to begin recv() */ epicsEventSignal(cycled[1]); testDiag("Test announcement directly from server"); memset(&buf, 0, sizeof(buf)); buf.m_msg.pid = htons(RECAST_MAGIC); buf.m_msg.serverIP = htonl(0xffffffff); buf.m_msg.serverPort = htons(0x1020); buf.m_msg.serverKey = htonl(0x12345678); testOk1(0==shSendTo(&sender, &buf.m_bytes, 0x10, 0, &dest)); /* wait for tester thread to completer recv() and end cycle */ epicsEventMustWait(cycled[0]); epicsMutexMustLock(lock); testOk1(cycles==1); testOk1(result==0); testOk1(caster.haveserv==1); testOk1(caster.nameserv.ia.sin_family==AF_INET); testOk1(caster.nameserv.ia.sin_addr.s_addr==htonl(INADDR_LOOPBACK)); testOk1(caster.nameserv.ia.sin_port==htons(0x1020)); testOk1(caster.servkey==0x12345678); epicsMutexUnlock(lock); testDiag("Test proxied announcement"); /* start next cycle */ epicsEventSignal(cycled[1]); /* wait for tester thread to setup socket */ epicsEventMustWait(cycled[0]); epicsMutexMustLock(lock); dest.ia.sin_port = htons(caster.udpport); epicsMutexUnlock(lock); buf.m_msg.serverIP = htonl(0x50607080); /* allow tester thread to begin recv() */ epicsEventSignal(cycled[1]); testOk1(0==shSendTo(&sender, &buf.m_bytes, 0x10, 0, &dest)); /* wait for tester thread to completer recv() and end cycle */ epicsEventMustWait(cycled[0]); epicsMutexMustLock(lock); testOk1(cycles==2); testOk1(result==0); testOk1(caster.haveserv==1); testOk1(caster.nameserv.ia.sin_family==AF_INET); testOk1(caster.nameserv.ia.sin_addr.s_addr==htonl(0x50607080)); testOk1(caster.nameserv.ia.sin_port==htons(0x1020)); epicsMutexUnlock(lock); /* begin shutdown cycle */ epicsEventSignal(cycled[1]); epicsEventMustWait(cycled[0]); epicsEventSignal(cycled[1]); casterShutdown(&caster); epicsEventDestroy(cycled[0]); epicsEventDestroy(cycled[1]); epicsMutexDestroy(lock); }
/** Constructor for FastCCD driver; most parameters are simply passed to ADDriver::ADDriver. * After calling the base class constructor this method creates a thread to collect the detector data, * and sets reasonable default values the parameters defined in this class, asynNDArrayDriver, and ADDriver. * \param[in] portName The name of the asyn port driver to be created. * \param[in] maxBuffers The maximum number of NDArray buffers that the NDArrayPool for this driver is * allowed to allocate. Set this to -1 to allow an unlimited number of buffers. * \param[in] maxMemory The maximum amount of memory that the NDArrayPool for this driver is * allowed to allocate. Set this to -1 to allow an unlimited amount of memory. * \param[in] priority The thread priority for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags. * \param[in] stackSize The stack size for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags. */ FastCCD::FastCCD(const char *portName, int maxBuffers, size_t maxMemory, int priority, int stackSize, int packetBuffer, int imageBuffer, const char *baseIP, const char *fabricIP, const char *fabricMAC) : ADDriver(portName, 1, NUM_FastCCD_DET_PARAMS, maxBuffers, maxMemory, asynUInt32DigitalMask, asynUInt32DigitalMask, ASYN_CANBLOCK, 1, priority, stackSize) { int status = asynSuccess; int sizeX, sizeY; static const char *functionName = "FastCCD"; /* Write the packet and frame buffer sizes */ cinPacketBuffer = packetBuffer; cinImageBuffer = imageBuffer; /* Store the network information */ strncpy(cinBaseIP, baseIP, 20); strncpy(cinFabricIP, fabricIP, 20); strncpy(cinFabricMAC, fabricMAC, 20); //Define the polling periods for the status thread. statusPollingPeriod = 20; //seconds dataStatsPollingPeriod = 0.1; //seconds // Assume we are in continuous mode framesRemaining = -1; /* Create an EPICS exit handler */ epicsAtExit(exitHandler, this); createParam(FastCCDPollingPeriodString, asynParamFloat64, &FastCCDPollingPeriod); createParam(FastCCDMux1String, asynParamInt32, &FastCCDMux1); createParam(FastCCDMux2String, asynParamInt32, &FastCCDMux2); createParam(FastCCDFirmwarePathString, asynParamOctet, &FastCCDFirmwarePath); createParam(FastCCDBiasPathString, asynParamOctet, &FastCCDBiasPath); createParam(FastCCDClockPathString, asynParamOctet, &FastCCDClockPath); createParam(FastCCDFCRICPathString, asynParamOctet, &FastCCDFCRICPath); createParam(FastCCDFirmwareUploadString, asynParamInt32, &FastCCDFirmwareUpload); createParam(FastCCDBiasUploadString, asynParamInt32, &FastCCDBiasUpload); createParam(FastCCDClockUploadString, asynParamInt32, &FastCCDClockUpload); createParam(FastCCDFCRICUploadString, asynParamInt32, &FastCCDFCRICUpload); createParam(FastCCDPowerString, asynParamInt32, &FastCCDPower); createParam(FastCCDFPPowerString, asynParamInt32, &FastCCDFPPower); createParam(FastCCDCameraPowerString, asynParamInt32, &FastCCDCameraPower); createParam(FastCCDBiasString, asynParamInt32, &FastCCDBias); createParam(FastCCDClocksString, asynParamInt32, &FastCCDClocks); createParam(FastCCDFPGAStatusString, asynParamUInt32Digital, &FastCCDFPGAStatus); createParam(FastCCDDCMStatusString, asynParamUInt32Digital, &FastCCDDCMStatus); createParam(FastCCDOverscanString, asynParamInt32, &FastCCDOverscan); createParam(FastCCDFclkString, asynParamInt32, &FastCCDFclk); createParam(FastCCDFCRICGainString, asynParamInt32, &FastCCDFCRICGain); createParam(FastCCDVBus12V0String, asynParamFloat64, &FastCCDVBus12V0); createParam(FastCCDVMgmt3v3String, asynParamFloat64, &FastCCDVMgmt3v3); createParam(FastCCDVMgmt2v5String, asynParamFloat64, &FastCCDVMgmt2v5); createParam(FastCCDVMgmt1v2String, asynParamFloat64, &FastCCDVMgmt1v2); createParam(FastCCDVEnet1v0String, asynParamFloat64, &FastCCDVEnet1v0); createParam(FastCCDVS3E3v3String, asynParamFloat64, &FastCCDVS3E3v3); createParam(FastCCDVGen3v3String, asynParamFloat64, &FastCCDVGen3v3); createParam(FastCCDVGen2v5String, asynParamFloat64, &FastCCDVGen2v5); createParam(FastCCDV60v9String, asynParamFloat64, &FastCCDV60v9); createParam(FastCCDV61v0String, asynParamFloat64, &FastCCDV61v0); createParam(FastCCDV62v5String, asynParamFloat64, &FastCCDV62v5); createParam(FastCCDVFpString, asynParamFloat64, &FastCCDVFp); createParam(FastCCDIBus12V0String, asynParamFloat64, &FastCCDIBus12V0); createParam(FastCCDIMgmt3v3String, asynParamFloat64, &FastCCDIMgmt3v3); createParam(FastCCDIMgmt2v5String, asynParamFloat64, &FastCCDIMgmt2v5); createParam(FastCCDIMgmt1v2String, asynParamFloat64, &FastCCDIMgmt1v2); createParam(FastCCDIEnet1v0String, asynParamFloat64, &FastCCDIEnet1v0); createParam(FastCCDIS3E3v3String, asynParamFloat64, &FastCCDIS3E3v3); createParam(FastCCDIGen3v3String, asynParamFloat64, &FastCCDIGen3v3); createParam(FastCCDIGen2v5String, asynParamFloat64, &FastCCDIGen2v5); createParam(FastCCDI60v9String, asynParamFloat64, &FastCCDI60v9); createParam(FastCCDI61v0String, asynParamFloat64, &FastCCDI61v0); createParam(FastCCDI62v5String, asynParamFloat64, &FastCCDI62v5); createParam(FastCCDIFpString, asynParamFloat64, &FastCCDIFp); createParam(FastCCDLibCinVersionString, asynParamOctet, &FastCCDLibCinVersion); createParam(FastCCDBoardIDString, asynParamInt32, &FastCCDBoardID); createParam(FastCCDSerialNumString, asynParamInt32, &FastCCDSerialNum); createParam(FastCCDFPGAVersionString, asynParamInt32, &FastCCDFPGAVersion); createParam(FastCCDStatusHBString, asynParamInt32, &FastCCDStatusHB); createParam(FastCCDBadPckString, asynParamInt32, &FastCCDBadPck); createParam(FastCCDDroppedPckString, asynParamInt32, &FastCCDDroppedPck); createParam(FastCCDLastFrameString, asynParamInt32, &FastCCDLastFrame); createParam(FastCCDResetStatsString, asynParamInt32, &FastCCDResetStats); createParam(FastCCDPacketBufferString, asynParamInt32, &FastCCDPacketBuffer); createParam(FastCCDFrameBufferString, asynParamInt32, &FastCCDFrameBuffer); createParam(FastCCDImageBufferString, asynParamInt32, &FastCCDImageBuffer); // Create the epicsEvent for signaling to the status task when parameters should have changed. // This will cause it to do a poll immediately, rather than wait for the poll time period. this->statusEvent = epicsEventMustCreate(epicsEventEmpty); if (!this->statusEvent) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to create event for status task.\n", driverName, functionName); return; } this->dataStatsEvent = epicsEventMustCreate(epicsEventEmpty); if (!this->dataStatsEvent) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to create event for data stats task.\n", driverName, functionName); return; } try { this->lock(); connectCamera(); this->unlock(); setStringParam(ADStatusMessage, "Initialized"); callParamCallbacks(); } catch (const std::string &e) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: %s\n", driverName, functionName, e.c_str()); return; } sizeX = CIN_DATA_MAX_FRAME_X; sizeY = CIN_DATA_MAX_FRAME_Y; /* Set some default values for parameters */ status = asynSuccess; status |= setDoubleParam(FastCCDPollingPeriod, statusPollingPeriod); status |= setStringParam(ADManufacturer, "Berkeley Laboratory"); status |= setStringParam(ADModel, "1k x 2k FastCCD"); status |= setIntegerParam(ADSizeX, sizeX); status |= setIntegerParam(ADSizeY, sizeY); status |= setIntegerParam(ADBinX, 1); status |= setIntegerParam(ADBinY, 1); status |= setIntegerParam(ADMinX, 0); status |= setIntegerParam(ADMinY, 0); status |= setIntegerParam(ADMaxSizeX, sizeX); status |= setIntegerParam(ADMaxSizeY, sizeY); status |= setIntegerParam(ADReverseX, 0); status |= setIntegerParam(ADReverseY, 0); status |= setIntegerParam(ADImageMode, ADImageSingle); status |= setIntegerParam(ADTriggerMode, 1); status |= setDoubleParam(ADAcquireTime, 0.005); status |= setDoubleParam(ADAcquirePeriod, 1.0); status |= setIntegerParam(ADNumImages, 1); status |= setIntegerParam(ADNumExposures, 1); status |= setIntegerParam(NDArraySizeX, sizeX); status |= setIntegerParam(NDArraySizeY, sizeY); status |= setIntegerParam(NDDataType, NDUInt16); status |= setIntegerParam(NDArraySize, sizeX*sizeY*sizeof(epicsUInt16)); status |= setDoubleParam(ADShutterOpenDelay, 0.); status |= setDoubleParam(ADShutterCloseDelay, 0.); status |= setIntegerParam(FastCCDFirmwareUpload, 0); status |= setIntegerParam(FastCCDClockUpload, 0); status |= setIntegerParam(FastCCDBiasUpload, 0); status |= setIntegerParam(FastCCDPower, 0); status |= setIntegerParam(FastCCDFPPower, 0); status |= setIntegerParam(FastCCDCameraPower, 0); status |= setIntegerParam(FastCCDBias, 0); status |= setIntegerParam(FastCCDClocks, 0); status |= setUIntDigitalParam(FastCCDFPGAStatus, 0x0, 0xFFFF); status |= setUIntDigitalParam(FastCCDDCMStatus, 0x0, 0xFFFF); status |= setIntegerParam(FastCCDMux1, 0); status |= setIntegerParam(FastCCDMux2, 0); status |= setStringParam(FastCCDFirmwarePath, ""); status |= setStringParam(FastCCDBiasPath, ""); status |= setStringParam(FastCCDClockPath, ""); status |= setStringParam(FastCCDFCRICPath, ""); status |= setIntegerParam(FastCCDOverscan, 2); status |= setIntegerParam(FastCCDFclk, 0); status |= setIntegerParam(FastCCDFCRICGain, 0); status |= setDoubleParam(FastCCDVBus12V0, 0); status |= setDoubleParam(FastCCDVMgmt3v3, 0); status |= setDoubleParam(FastCCDVMgmt2v5, 0); status |= setDoubleParam(FastCCDVMgmt1v2, 0); status |= setDoubleParam(FastCCDVEnet1v0, 0); status |= setDoubleParam(FastCCDVS3E3v3, 0); status |= setDoubleParam(FastCCDVGen3v3, 0); status |= setDoubleParam(FastCCDVGen2v5, 0); status |= setDoubleParam(FastCCDV60v9, 0); status |= setDoubleParam(FastCCDV61v0, 0); status |= setDoubleParam(FastCCDV62v5, 0); status |= setDoubleParam(FastCCDVFp, 0); status |= setDoubleParam(FastCCDIBus12V0, 0); status |= setDoubleParam(FastCCDIMgmt3v3, 0); status |= setDoubleParam(FastCCDIMgmt2v5, 0); status |= setDoubleParam(FastCCDIMgmt1v2, 0); status |= setDoubleParam(FastCCDIEnet1v0, 0); status |= setDoubleParam(FastCCDIS3E3v3, 0); status |= setDoubleParam(FastCCDIGen3v3, 0); status |= setDoubleParam(FastCCDIGen2v5, 0); status |= setDoubleParam(FastCCDI60v9, 0); status |= setDoubleParam(FastCCDI61v0, 0); status |= setDoubleParam(FastCCDI62v5, 0); status |= setDoubleParam(FastCCDIFp, 0); status |= setStringParam(FastCCDLibCinVersion, (char *)cin_build_version); callParamCallbacks(); // Signal the status thread to poll the detector epicsEventSignal(statusEvent); epicsEventSignal(dataStatsEvent); if (stackSize == 0) { stackSize = epicsThreadGetStackSize(epicsThreadStackMedium); } /* Create the thread that updates the detector status */ status = (epicsThreadCreate("FastCCDStatusTask", epicsThreadPriorityMedium, stackSize, (EPICSTHREADFUNC)FastCCDStatusTaskC, this) == NULL); if(status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to create status task.\n", driverName, functionName); return; } /* Create the thread that updates the data stats */ status = (epicsThreadCreate("FastCCDDataStatsTask", epicsThreadPriorityMedium, stackSize, (EPICSTHREADFUNC)FastCCDDataStatsTaskC, this) == NULL); if(status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: Failed to create data stats task.\n", driverName, functionName); return; } }
int ni1014Config(char *portNameA,char *portNameB, int base, int vector, int level, int priority, int noAutoConnect) { niport *pniportArray[2] = {0,0}; int size; int indPort,nports; long status; if(nloopsPerMicrosecond==0) initAuxmrWait(); nports = (portNameB==0 || strlen(portNameB)==0) ? 1 : 2; for(indPort=0; indPort<nports; indPort++) { niport *pniport; size = sizeof(niport); size += (indPort==0) ? strlen(portNameA) : strlen(portNameB); size += 1; pniport = callocMustSucceed(size,sizeof(char),"ni1014Config"); pniportArray[indPort] = pniport; pniport->portName = (char *)(pniport+1); strcpy(pniport->portName,((indPort==0) ? portNameA : portNameB)); pniport->base = base; pniport->vector = vector; pniport->level = level; pniport->eos = -1; pniport->waitForInterrupt = epicsEventMustCreate(epicsEventEmpty); callbackSetCallback(srqCallback,&pniport->callback); callbackSetUser(pniport,&pniport->callback); status = devRegisterAddress("drvNi1014", atVMEA16, pniport->base, PORT_REGISTER_SIZE/2,(volatile void **)&pniport->registers); if(status) { printf("%s ni1014Config devRegisterAddress failed\n",pniport->portName); return(-1); } /* attach the interrupt handler routines */ status = devConnectInterrupt(intVME,pniport->vector, ni1014,(void *)pniport); if(status) { errMessage(status,"ni1014: devConnectInterrupt"); return -1; } status = devConnectInterrupt(intVME,pniport->vector+1, ni1014Err,(void *)pniport); if(status) { errMessage(status,"ni1014: devConnectInterrupt"); return -1; } status = devEnableInterruptLevel(intVME,pniport->level); if(status) { errMessage(status,"ni1014: devEnableInterruptLevel"); return -1; } pniport->isPortA = (indPort==0) ? 1 : 0; pniport->asynGpibPvt = pasynGpib->registerPort(pniport->portName, ASYN_MULTIDEVICE|ASYN_CANBLOCK, !noAutoConnect,&gpibPort,pniport,priority,0); base = base + PORT_REGISTER_SIZE; vector += 2; } return 0; }