/*************************************************************************\ * Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2013 Helmholtz-Zentrum Berlin * für Materialien und Energie GmbH. * SPDX-License-Identifier: EPICS * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* * Author: Ralph Lange */ #include #include #include #include "epicsEvent.h" #include "epicsMessageQueue.h" #include "epicsPrint.h" #include "epicsMath.h" #include "alarm.h" #include "menuPriority.h" #include "dbChannel.h" #include "dbStaticLib.h" #include "dbAccessDefs.h" #include "dbScan.h" #include "dbLock.h" #include "dbUnitTest.h" #include "dbCommon.h" #include "recSup.h" #include "devSup.h" #include "iocInit.h" #include "callback.h" #include "ellLib.h" #include "epicsUnitTest.h" #include "testMain.h" #include "osiFileName.h" #include "epicsExport.h" #include "devx.h" #include "xRecord.h" STATIC_ASSERT(NUM_CALLBACK_PRIORITIES==3); void dbTestIoc_registerRecordDeviceDriver(struct dbBase *); static void loadRecord(int group, int member, const char *prio) { char buf[40]; sprintf(buf, "GROUP=%d,MEMBER=%d,PRIO=%s", group, member, prio); testdbReadDatabase("scanIoTest.db", NULL, buf); } typedef struct { int hasprocd[NUM_CALLBACK_PRIORITIES]; int getcomplete[NUM_CALLBACK_PRIORITIES]; epicsEventId wait[NUM_CALLBACK_PRIORITIES]; epicsEventId wake[NUM_CALLBACK_PRIORITIES]; } testsingle; static void testcb(xpriv *priv, void *raw) { testsingle *td = raw; int prio = priv->prec->prio; testOk1(td->hasprocd[prio]==0); td->hasprocd[prio] = 1; } static void testcomp(void *raw, IOSCANPVT scan, int prio) { testsingle *td = raw; testOk1(td->hasprocd[prio]==1); testOk1(td->getcomplete[prio]==0); td->getcomplete[prio] = 1; epicsEventMustTrigger(td->wait[prio]); epicsEventMustWait(td->wake[prio]); } 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; pscan, &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; imember; testOk1(td->hasprocd==0); td->hasprocd = 1; epicsEventMustTrigger(td->wait); epicsEventMustWait(td->wake); td->getcomplete = 1; } static void testcompmulti(void *raw, IOSCANPVT scan, int prio) { int *mask = raw; testOk(((*mask)&(1<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