From 3e0445f2adcc873dc658f4576eee94da62e41b15 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Fri, 3 May 1996 14:11:06 +0000 Subject: [PATCH] Fixed many bugs --- src/db/dbAccess.c | 19 ++- src/db/dbCa.c | 76 ++++++--- src/db/dbConvert.c | 153 +++++++++++------- src/db/dbFastLinkConv.c | 49 +++++- src/db/dbScan.c | 336 ++++++++++++++++++---------------------- 5 files changed, 360 insertions(+), 273 deletions(-) diff --git a/src/db/dbAccess.c b/src/db/dbAccess.c index 96aae52a1..72fc054fe 100644 --- a/src/db/dbAccess.c +++ b/src/db/dbAccess.c @@ -385,7 +385,10 @@ static void getOptions(DBADDR *paddr,void **poriginal,long *options,void *pflin) struct rset *dbGetRset(struct dbAddr *paddr) { - return(((struct dbFldDes *)paddr->pfldDes)->pdbRecDes->prset); + struct dbFldDes *pfldDes = (struct dbFldDes *)paddr->pfldDes; + + if(!pfldDes) return(0); + return(pfldDes->pdbRecDes->prset); } int dbIsValueField(struct dbFldDes *pdbFldDes) @@ -422,10 +425,14 @@ long dbScanPassive(dbCommon *pfrom, dbCommon *pto) /*KLUDGE: Following needed so that dbPutLink to PROC field works correctly*/ long dbScanLink(dbCommon *pfrom, dbCommon *pto) { - long status; + long status; + unsigned char pact; if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto); + pact = pfrom->pact; + pfrom->pact = TRUE; status = dbProcess(pto); + pfrom->pact = pact; return(status); } @@ -846,7 +853,7 @@ long dbGet(DBADDR *paddr,short dbrType,void *pbuffer,long *options, if(nRequest) { if(no_elements<(*nRequest)) *nRequest = no_elements; - n = no_elements; + n = *nRequest; } else { n = 1; } @@ -858,7 +865,9 @@ long dbGet(DBADDR *paddr,short dbrType,void *pbuffer,long *options, return(S_db_badDbrtype); } /* convert database field and place it in the buffer */ - if(pfl!=NULL) { + if(n<=0) { + ;/*do nothing*/ + } else if(pfl!=NULL) { DBADDR localAddr; localAddr = *paddr; /*Structure copy*/ @@ -1069,7 +1078,7 @@ long dbPut(DBADDR *paddr,short dbrType,void *pbuffer,long nRequest) status = putSpecial(paddr,0); if(status) return(status); } - if(no_elements<=1) { + if((no_elements<=1) && (!prset || !(prset->put_array_info))) { status = (*dbFastPutConvertRoutine[dbrType][field_type]) (pbuffer,paddr->pfield, paddr); } else { diff --git a/src/db/dbCa.c b/src/db/dbCa.c index 80b7748b8..2a57d0b4d 100644 --- a/src/db/dbCa.c +++ b/src/db/dbCa.c @@ -89,10 +89,10 @@ void dbCaRemoveLink( struct link *plink) if(!pca) return; semTake(caListSem,WAIT_FOREVER); + pca->link_action = CA_DELETE; if(!pca->link_action){/*If not on work list add it*/ ellAdd(&caList,&pca->node); } - pca->link_action = CA_DELETE; plink->value.pv_link.pvt = 0; pca->plink = 0; semGive(caListSem); @@ -133,7 +133,10 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest, pca->pgetString = dbCalloc(MAX_STRING_SIZE,sizeof(char)); semGive(pca->lock); semTake(caListSem,WAIT_FOREVER); - pca->link_action = CA_MONITOR_STRING; + if(!pca->link_action){/*If not on work list add it*/ + pca->link_action = CA_MONITOR_STRING; + ellAdd(&caList,&pca->node); + } semGive(caListSem); semGive(caWakeupSem); semStatus = semTake(pca->lock,WAIT_FOREVER); @@ -158,7 +161,8 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest, if(!nelements || *nelements == 1){ pconvert= dbFastGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType]; - status = (*(pconvert))(pca->pgetNative, pdest, 0); + /*Ignore error routine*/ + (*(pconvert))(pca->pgetNative, pdest, 0); }else{ unsigned long ntoget = *nelements; struct db_addr dbAddr; @@ -170,7 +174,8 @@ long dbCaGetLink(struct link *plink,short dbrType, char *pdest, dbAddr.pfield = pca->pgetNative; /*Following will only be used for pca->dbrType == DBR_STRING*/ dbAddr.field_size = MAX_STRING_SIZE; - status = (*(pconvert))(&dbAddr,pdest,nelements,ntoget,0); + /*Ignore error routine*/ + (*(pconvert))(&dbAddr,pdest,ntoget,ntoget,0); } done: if(psevr) *psevr = pca->sevr; @@ -242,16 +247,15 @@ long dbCaPutLink(struct link *plink,short dbrType, semGive(caWakeupSem); return(status); } - -static void caEventHandler(struct event_handler_args arg) +static void eventCallback(struct event_handler_args arg) { caLink *pca = (caLink *)arg.usr; struct link *plink; long size; if(!pca) { - epicsPrintf("caEventHandler why was arg.usr NULL\n"); + epicsPrintf("eventCallback why was arg.usr NULL\n"); return; } plink = pca->plink; @@ -259,16 +263,18 @@ static void caEventHandler(struct event_handler_args arg) dbCommon *precord = 0; if(plink) precord = (dbCommon *)plink->value.pv_link.precord; - if(precord) - epicsPrintf("dbCa: caEventHandler record %s error %s\n", + if(precord) { + if(arg.status!=ECA_NORDACCESS) + epicsPrintf("dbCa: eventCallback record %s error %s\n", precord->name,ca_message(arg.status)); - else - epicsPrintf("dbCa: caEventHandler error %s\n", + } else { + epicsPrintf("dbCa: eventCallback error %s\n", ca_message(arg.status)); + } return; } if(!arg.dbr) { - epicsPrintf("caEventHandler why was arg.dbr NULL\n"); + epicsPrintf("eventCallback why was arg.dbr NULL\n"); return; } semTake(pca->lock,WAIT_FOREVER); @@ -289,7 +295,7 @@ static void caEventHandler(struct event_handler_args arg) pca->gotInNative = TRUE; break; default: - errMessage(-1,"dbCa: caEventHandler Logic Error\n"); + errMessage(-1,"dbCa: eventCallback Logic Error\n"); break; } pca->sevr=(unsigned short)((struct dbr_sts_double *)arg.dbr)->severity; @@ -301,13 +307,36 @@ static void caEventHandler(struct event_handler_args arg) if(precord) { if((ppv_link->pvlMask&pvlOptCP) || ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0))) - scanOnce(ppv_link->precord); + scanOnce(precord); } } semGive(pca->lock); } -static void dbCaLinkConnectionHandler(struct connection_handler_args arg) +static void accessRightsCallback(struct access_rights_handler_args arg) +{ + caLink *pca = (caLink *)ca_puser(arg.chid); + struct link *plink; + + if(!pca) { + epicsPrintf("accessRightsCallback why was arg.usr NULL\n"); + return; + } + if(ca_read_access(arg.chid) || ca_write_access(arg.chid)) return; + plink = pca->plink; + if(plink) { + struct pv_link *ppv_link = &(plink->value.pv_link); + dbCommon *precord = ppv_link->precord; + + if(precord) { + if((ppv_link->pvlMask&pvlOptCP) + || ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0))) + scanOnce(precord); + } + } +} + +static void connectionCallback(struct connection_handler_args arg) { caLink *pca; int status; @@ -342,13 +371,13 @@ static void dbCaLinkConnectionHandler(struct connection_handler_args arg) pca->pputNative = dbCalloc(pca->nelements,element_size); status = ca_add_array_event( ca_field_type(arg.chid)+DBR_STS_STRING, ca_element_count(arg.chid), - arg.chid, caEventHandler,pca,0.0,0.0,0.0,0); + arg.chid, eventCallback,pca,0.0,0.0,0.0,0); if(status!=ECA_NORMAL) epicsPrintf("dbCaTask ca_search_and_connect %s\n", ca_message(status)); if(pca->pgetString) { status = ca_add_array_event(DBR_STS_STRING,1, - arg.chid, caEventHandler,pca,0.0,0.0,0.0,0); + arg.chid, eventCallback,pca,0.0,0.0,0.0,0); if(status!=ECA_NORMAL) epicsPrintf("dbCaTask ca_search_and_connect %s\n", ca_message(status)); @@ -385,10 +414,17 @@ void dbCaTask() status = ca_search_and_connect( pca->plink->value.pv_link.pvname, &(pca->chid), - dbCaLinkConnectionHandler,(void *)pca); - if(status!=ECA_NORMAL) + connectionCallback,(void *)pca); + if(status!=ECA_NORMAL) { epicsPrintf("dbCaTask ca_search_and_connect %s\n", ca_message(status)); + break; + } + status = ca_replace_access_rights_event(pca->chid, + accessRightsCallback); + if(status!=ECA_NORMAL) + epicsPrintf("dbCaTask ca_replace_access_rights_event %s\n", + ca_message(status)); break; case CA_DELETE: if(pca->chid) ca_clear_channel(pca->chid); @@ -422,7 +458,7 @@ void dbCaTask() case CA_MONITOR_STRING: if(ca_state(pca->chid) == cs_conn){ status = ca_add_array_event(DBR_STS_STRING,1, - pca->chid, caEventHandler,pca,0.0,0.0,0.0,0); + pca->chid, eventCallback,pca,0.0,0.0,0.0,0); if(status!=ECA_NORMAL) epicsPrintf("dbCaTask ca_add_array_event %s\n", ca_message(status)); diff --git a/src/db/dbConvert.c b/src/db/dbConvert.c index 82ce733c8..fa94b1bc4 100644 --- a/src/db/dbConvert.c +++ b/src/db/dbConvert.c @@ -45,9 +45,8 @@ #include #include - /* DATABASE ACCESS GET CONVERSION SUPPORT */ - + static long getStringString ( DBADDR *paddr, void *pto, long nRequest, long no_elements, long offset) { @@ -90,15 +89,21 @@ static long getStringChar( if(sscanf(psrc,"%hd",&value) == 1) { *pbuffer = (char)value; return(0); + } else if(strlen(psrc) == 0) { + *pbuffer = '0'; + return(0); + } else { + return(-1); } - else return(-1); } psrc += MAX_STRING_SIZE*offset; while (nRequest) { if(sscanf(psrc,"%hd",&value) == 1) { *pbuffer = (char)value; + } else if(strlen(psrc) == 0) { + *pbuffer = '0'; } else { - return(-1); + return(-1); } pbuffer++; if(++offset==no_elements) @@ -121,15 +126,21 @@ static long getStringUchar( if(sscanf(psrc,"%hu",&value) == 1) { *pbuffer = (unsigned char)value; return(0); + } else if(strlen(psrc) == 0) { + *pbuffer = '0'; + return(0); + } else { + return(-1); } - else return(-1); } psrc += MAX_STRING_SIZE*offset; while (nRequest) { if(sscanf(psrc,"%hu",&value) == 1) { *pbuffer = (unsigned char)value; + } else if(strlen(psrc) == 0) { + *pbuffer = '0'; } else { - return(-1); + return(-1); } pbuffer++; if(++offset==no_elements) @@ -152,15 +163,21 @@ static long getStringShort( if(sscanf(psrc,"%hd",&value) == 1) { *pbuffer = value; return(0); + } else if(strlen(psrc) == 0) { + *pbuffer = 0; + return(0); + } else { + return(-1); } - else return(-1); } psrc += MAX_STRING_SIZE*offset; while (nRequest) { if(sscanf(psrc,"%hd",&value) == 1) { *pbuffer = value; + } else if(strlen(psrc) == 0) { + *pbuffer = 0; } else { - return(-1); + return(-1); } pbuffer++; if(++offset==no_elements) @@ -183,15 +200,21 @@ static long getStringUshort( if(sscanf(psrc,"%hu",&value) == 1) { *pbuffer = value; return(0); + } else if(strlen(psrc) == 0) { + *pbuffer = 0; + return(0); + } else { + return(-1); } - else return(-1); } psrc += MAX_STRING_SIZE*offset; while (nRequest) { if(sscanf(psrc,"%hu",&value) == 1) { *pbuffer = value; + } else if(strlen(psrc) == 0) { + *pbuffer = 0; } else { - return(-1); + return(-1); } pbuffer++; if(++offset==no_elements) @@ -214,15 +237,21 @@ static long getStringLong( if(sscanf(psrc,"%ld",&value) == 1) { *pbuffer = value; return(0); + } else if(strlen(psrc) == 0) { + *pbuffer = 0; + return(0); + } else { + return(-1); } - else return(-1); } psrc += MAX_STRING_SIZE*offset; while (nRequest) { if(sscanf(psrc,"%ld",&value) == 1) { *pbuffer = value; + } else if(strlen(psrc) == 0) { + *pbuffer = 0; } else { - return(-1); + return(-1); } pbuffer++; if(++offset==no_elements) @@ -239,21 +268,29 @@ static long getStringUlong( { unsigned long *pbuffer = (unsigned long *)pto; char *psrc=(char *)paddr->pfield; - unsigned long value; + double value; + /*Convert to double first so that numbers like 1.0e3 convert properly*/ + /*Problem was old database access said to get unsigned long as double*/ if(nRequest==1 && offset==0) { - if(sscanf(psrc,"%lu",&value) == 1) { - *pbuffer = value; + if(sscanf(psrc,"%lf",&value) == 1) { + *pbuffer = (unsigned long)value; return(0); + } else if(strlen(psrc) == 0) { + *pbuffer = 0; + return(0); + } else { + return(-1); } - else return(-1); } psrc += MAX_STRING_SIZE*offset; while (nRequest) { - if(sscanf(psrc,"%lu",&value) == 1) { - *pbuffer = value; + if(sscanf(psrc,"%lf",&value) == 1) { + *pbuffer = (unsigned long)value; + } else if(strlen(psrc) == 0) { + *pbuffer = 0; } else { - return(-1); + return(-1); } pbuffer++; if(++offset==no_elements) @@ -276,16 +313,21 @@ static long getStringFloat( if(sscanf(psrc,"%f",&value) == 1) { *pbuffer = value; return(0); + } else if(strlen(psrc) == 0) { + *pbuffer = 0.0; + return(0); } else { - return(-1); + return(-1); } } psrc += MAX_STRING_SIZE*offset; while (nRequest) { if(sscanf(psrc,"%f",&value) == 1) { *pbuffer = value; + } else if(strlen(psrc) == 0) { + *pbuffer = 0.0; } else { - return(-1); + return(-1); } pbuffer++; if(++offset==no_elements) @@ -308,16 +350,21 @@ static long getStringDouble( if(sscanf(psrc,"%lf",&value) == 1) { *pbuffer = value; return(0); + } else if(strlen(psrc) == 0) { + *pbuffer = 0.0; + return(0); } else { - return(-1); + return(-1); } } psrc += MAX_STRING_SIZE*offset; while (nRequest) { if(sscanf(psrc,"%lf",&value) == 1) { *pbuffer = value; + } else if(strlen(psrc) == 0) { + *pbuffer = 0.0; } else { - return(-1); + return(-1); } pbuffer++; if(++offset==no_elements) @@ -1504,9 +1551,10 @@ static long getFloatString( float *psrc=(float *)(paddr->pfield); long status = 0; int precision = 0; - struct rset *prset; + struct rset *prset = 0; - if((prset=dbGetRset(paddr)) && (prset->get_precision)) + if(paddr) prset = dbGetRset(paddr); + if(prset && (prset->get_precision)) status = (*prset->get_precision)(paddr,&precision); else status=S_db_precision; @@ -1627,17 +1675,14 @@ static long getFloatUlong( { unsigned long *pbuffer = (unsigned long *)pto; float *psrc=(float *)(paddr->pfield); - long ltemp; /*vxWorks does not support float to unsigned long*/ if(nRequest==1 && offset==0) { - ltemp = *psrc; - *pbuffer = ltemp; + *pbuffer = *psrc; return(0); } psrc += offset; while (nRequest) { - ltemp = *psrc++; - *pbuffer++ = ltemp; + *pbuffer++ = *psrc++; if(++offset==no_elements) psrc=(float *)paddr->pfield; nRequest--; } @@ -1708,9 +1753,10 @@ static long getDoubleString( double *psrc=(double *)(paddr->pfield); long status = 0; int precision = 0; - struct rset *prset; + struct rset *prset = 0; - if((prset=dbGetRset(paddr)) && (prset->get_precision)) + if(paddr) prset = dbGetRset(paddr); + if(prset && (prset->get_precision)) status = (*prset->get_precision)(paddr,&precision); else status=S_db_precision; @@ -1831,17 +1877,14 @@ static long getDoubleUlong( { unsigned long *pbuffer = (unsigned long *)pto; double *psrc=(double *)(paddr->pfield); - long ltemp; /*vxWorks does not support double to unsigned long*/ if(nRequest==1 && offset==0) { - ltemp = *psrc; - *pbuffer = ltemp; + *pbuffer = *psrc; return(0); } psrc += offset; while (nRequest) { - ltemp = *psrc++; - *pbuffer++ = ltemp; + *pbuffer++ = *psrc++; if(++offset==no_elements) psrc=(double *)paddr->pfield; nRequest--; } @@ -2268,21 +2311,19 @@ static long putStringUshort( { char *pbuffer = (char *)pfrom; unsigned short *pdest=(unsigned short *)paddr->pfield; - float value; + unsigned short value; - /*Convert to float first so that numbers like 1.0e3 convert properly*/ - /*Problem was old database access said to get unsigned short as float*/ if(nRequest==1 && offset==0) { - if(sscanf(pbuffer,"%f",&value) == 1) { - *pdest = (unsigned short)value; + if(sscanf(pbuffer,"%hu",&value) == 1) { + *pdest = value; return(0); } else return(-1); } pdest += offset; while (nRequest) { - if(sscanf(pbuffer,"%f",&value) == 1) { - *pdest = (unsigned short)value; + if(sscanf(pbuffer,"%hu",&value) == 1) { + *pdest = value; } else { return(-1); } @@ -3721,10 +3762,11 @@ static long putFloatString( char *pdest=(char *)(paddr->pfield); long status = 0; int precision = 0; - struct rset *prset; + struct rset *prset = 0; short size=paddr->field_size; - if((prset=dbGetRset(paddr)) && (prset->get_precision)) + if(paddr) prset = dbGetRset(paddr); + if(prset && (prset->get_precision)) status = (*prset->get_precision)(paddr,&precision); else status=S_db_precision; @@ -3846,17 +3888,14 @@ static long putFloatUlong( { float *pbuffer = (float *)pfrom; unsigned long *pdest=(unsigned long *)(paddr->pfield); - long ltemp;/*vxWorks does not support float to unsigned long*/ if(nRequest==1 && offset==0) { - ltemp = *pbuffer; - *pdest = ltemp; + *pdest = *pbuffer; return(0); } pdest += offset; while (nRequest) { - ltemp = *pbuffer++; - *pdest++ = ltemp; + *pdest++ = *pbuffer++; if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; nRequest--; } @@ -3927,10 +3966,11 @@ static long putDoubleString( char *pdest=(char *)(paddr->pfield); long status = 0; int precision = 0; - struct rset *prset; + struct rset *prset = 0; short size=paddr->field_size; - if((prset=dbGetRset(paddr)) && (prset->get_precision)) + if(paddr) prset = dbGetRset(paddr); + if(prset && (prset->get_precision)) status = (*prset->get_precision)(paddr,&precision); else status=S_db_precision; @@ -4052,17 +4092,14 @@ static long putDoubleUlong( { double *pbuffer = (double *)pfrom; unsigned long *pdest=(unsigned long *)(paddr->pfield); - long ltemp;/*vxWorks does not support double to unsigned long*/ if(nRequest==1 && offset==0) { - ltemp = *pbuffer; - *pdest = ltemp; + *pdest = *pbuffer; return(0); } pdest += offset; while (nRequest) { - ltemp = *pbuffer++; - *pdest++ = ltemp; + *pdest++ = *pbuffer++; if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; nRequest--; } diff --git a/src/db/dbFastLinkConv.c b/src/db/dbFastLinkConv.c index 49b5952b8..eccd90808 100644 --- a/src/db/dbFastLinkConv.c +++ b/src/db/dbFastLinkConv.c @@ -115,7 +115,10 @@ static long cvt_st_c( *to = (char) value; return(0); } - + if(strlen(from) == 0) { + *to = '0'; + return(0); + } return(-1); /* Change to SYMBOL */ } @@ -125,10 +128,14 @@ static long cvt_st_uc( unsigned char *to, struct dbAddr *paddr) { - short value; + unsigned short value; if (sscanf(from, "%hu", &value) == 1) { - *to = (unsigned char) value; + *to = value; + return(0); + } + if(strlen(from) == 0) { + *to = '0'; return(0); } @@ -147,6 +154,10 @@ static long cvt_st_s( *to = value; return(0); } + if(strlen(from) == 0) { + *to = 0; + return(0); + } return(-1); /* Change to SYMBOL */ } @@ -157,12 +168,16 @@ static long cvt_st_us( unsigned short *to, struct dbAddr *paddr) { - short value; + unsigned short value; if (sscanf(from, "%hu", &value) == 1) { - *to = (unsigned short) value; + *to = value; return(0); } + if(strlen(from) == 0) { + *to = 0; + return(0); + } return(-1); /* Change to SYMBOL */ } @@ -179,6 +194,10 @@ static long cvt_st_l( *to = value; return(0); } + if(strlen(from) == 0) { + *to = 0; + return(0); + } return(-1); /* Change to SYMBOL */ } @@ -189,10 +208,16 @@ static long cvt_st_ul( unsigned long *to, struct dbAddr *paddr) { - unsigned long value; + double value; - if (sscanf(from, "%lu", &value) == 1) { - *to = value; + /*Convert to double first so that numbers like 1.0e3 convert properly*/ + /*Problem was old database access said to get unsigned long as double*/ + if (sscanf(from, "%lf", &value) == 1) { + *to = (unsigned long)value; + return(0); + } + if(strlen(from) == 0) { + *to = 0; return(0); } @@ -211,6 +236,10 @@ static long cvt_st_f( *to = value; return(0); } + if(strlen(from) == 0) { + *to = 0.0; + return(0); + } return(-1); /* Change to SYMBOL */ } @@ -227,6 +256,10 @@ static long cvt_st_d( *to = value; return(0); } + if(strlen(from) == 0) { + *to = 0.0; + return(0); + } return(-1); /* Change to SYMBOL */ } diff --git a/src/db/dbScan.c b/src/db/dbScan.c index 3564bdbc3..a50dd58f9 100644 --- a/src/db/dbScan.c +++ b/src/db/dbScan.c @@ -1,5 +1,4 @@ /* dbScan.c */ -/* base/src/db $Id$ */ /* tasks and subroutines to scan the database */ /* * Original Author: Bob Dalesio @@ -40,6 +39,7 @@ * .09 02-03-94 mrk If scanAdd fails set precord->scan=SCAN_PASSIVE * .10 02-22-94 mrk Make init work if 1st record has 28 char name * .11 05-04-94 mrk Call taskwdRemove only if spawing again + * .12 05-02-96 mrk Allow multiple priority event scan */ #include @@ -73,66 +73,65 @@ extern struct dbBase *pdbbase; /* SCAN ONCE */ -int onceQueueSize = 256; +int onceQueueSize = 1000; static SEM_ID onceSem; static RING_ID onceQ; static int onceTaskId; /*all other scan types */ -struct scan_list{ +typedef struct scan_list{ FAST_LOCK lock; ELLLIST list; short modified;/*has list been modified?*/ long ticks; /*ticks per period for periodic*/ -}; +}scan_list; /*scan_elements are allocated and the address stored in dbCommon.spvt*/ -struct scan_element{ +typedef struct scan_element{ ELLNODE node; - struct scan_list *pscan_list; + scan_list *pscan_list; struct dbCommon *precord; -}; +}scan_element; int volatile scanRestart=FALSE; - -/* PERIODIC SCANNER */ -static int nPeriodic=0; -static struct scan_list **papPeriodic; /* pointer to array of pointers*/ -static int *periodicTaskId; /*array of integers after allocation*/ +static char *priorityName[NUM_CALLBACK_PRIORITIES] = { + "Low","Medium","High"}; /* EVENT */ #define MAX_EVENTS 256 -#define EVENT_QUEUE_SIZE 1000 -static struct scan_list *papEvent[MAX_EVENTS];/*array of pointers*/ -static SEM_ID eventSem; -static RING_ID eventQ; -static int eventTaskId; +typedef struct event_scan_list { + CALLBACK callback; + scan_list scan_list; +}event_scan_list; +static event_scan_list *pevent_list[NUM_CALLBACK_PRIORITIES][MAX_EVENTS]; /* IO_EVENT*/ -struct io_scan_list { +typedef struct io_scan_list { CALLBACK callback; - struct scan_list scan_list; + scan_list scan_list; struct io_scan_list *next; -}; +}io_scan_list; +static io_scan_list *iosl_head[NUM_CALLBACK_PRIORITIES]={NULL,NULL,NULL}; -static struct io_scan_list *iosl_head[NUM_CALLBACK_PRIORITIES]={NULL,NULL,NULL}; +/* PERIODIC SCANNER */ +static int nPeriodic=0; +static scan_list **papPeriodic; /* pointer to array of pointers*/ +static int *periodicTaskId; /*array of integers after allocation*/ /* Private routines */ static void onceTask(void); static void initOnce(void); -static void periodicTask(struct scan_list *psl); +static void periodicTask(scan_list *psl); static void initPeriodic(void); static void spawnPeriodic(int ind); static void wdPeriodic(long ind); -static void eventTask(void); static void initEvent(void); -static void spawnEvent(void); -static void wdEvent(void); -static void ioeventCallback(struct io_scan_list *piosl); -static void printList(struct scan_list *psl,char *message); -static void scanList(struct scan_list *psl); +static void eventCallback(event_scan_list *pevent_scan_list); +static void ioeventCallback(io_scan_list *piosl); +static void printList(scan_list *psl,char *message); +static void scanList(scan_list *psl); static void buildScanLists(void); -static void addToList(struct dbCommon *precord,struct scan_list *psl); -static void deleteFromList(struct dbCommon *precord,struct scan_list *psl); +static void addToList(struct dbCommon *precord,scan_list *psl); +static void deleteFromList(struct dbCommon *precord,scan_list *psl); long scanInit() { @@ -143,38 +142,13 @@ long scanInit() initEvent(); buildScanLists(); for (i=0;i=MAX_EVENTS) { - errMessage(-1,"illegal event passed to post_event"); - return; - } - evnt = (unsigned)event; - /*multiple writers can exist. Thus if evnt is ever changed to use*/ - /*something bigger than a character interrupts will have to be blocked*/ - if(rngBufPut(eventQ,(void *)&evnt,sizeof(unsigned char)) - !=sizeof(unsigned char)) { - if(newOverflow) errMessage(0,"rngBufPut overflow in post_event"); - newOverflow = FALSE; - } else { - newOverflow = TRUE; - } - semGive(eventSem); -} - - void scanAdd(struct dbCommon *precord) { short scan; - struct scan_list *psl; + scan_list *psl; /* get the list on which this record belongs */ scan = precord->scan; @@ -183,7 +157,9 @@ void scanAdd(struct dbCommon *precord) recGblRecordError(-1,(void *)precord, "scanAdd detected illegal SCAN value"); }else if(scan==SCAN_EVENT) { - unsigned char evnt; + unsigned char evnt; + int priority; + event_scan_list *pevent_scan_list; if(precord->evnt<0 || precord->evnt>=MAX_EVENTS) { recGblRecordError(S_db_badField,(void *)precord, @@ -192,16 +168,25 @@ void scanAdd(struct dbCommon *precord) return; } evnt = (signed)precord->evnt; - psl = papEvent[evnt]; - if(psl==NULL) { - psl = dbCalloc(1,sizeof(struct scan_list)); - papEvent[precord->evnt] = psl; - FASTLOCKINIT(&psl->lock); - ellInit(&psl->list); + priority = precord->prio; + if(priority<0 || priority>=NUM_CALLBACK_PRIORITIES) { + recGblRecordError(-1,(void *)precord, + "scanAdd: illegal prio field"); + precord->scan = SCAN_PASSIVE; + return; } + pevent_scan_list = pevent_list[priority][evnt]; + if(!pevent_scan_list ) { + pevent_scan_list = dbCalloc(1,sizeof(event_scan_list)); + pevent_list[priority][evnt] = pevent_scan_list; + pevent_scan_list->callback.callback = eventCallback; + pevent_scan_list->callback.priority = priority; + ellInit(&pevent_scan_list->scan_list.list); + } + psl = &pevent_scan_list->scan_list; addToList(precord,psl); } else if(scan==SCAN_IO_EVENT) { - struct io_scan_list *piosl=NULL; + io_scan_list *piosl=NULL; int priority; DEVSUPFUN get_ioint_info; @@ -250,7 +235,7 @@ void scanAdd(struct dbCommon *precord) void scanDelete(struct dbCommon *precord) { short scan; - struct scan_list *psl; + scan_list *psl; /* get the list on which this record belongs */ scan = precord->scan; @@ -259,22 +244,33 @@ void scanDelete(struct dbCommon *precord) recGblRecordError(-1,(void *)precord, "scanDelete detected illegal SCAN value"); }else if(scan==SCAN_EVENT) { - unsigned char evnt; + unsigned char evnt; + int priority; + event_scan_list *pevent_scan_list; if(precord->evnt<0 || precord->evnt>=MAX_EVENTS) { recGblRecordError(S_db_badField,(void *)precord, - "scanDelete detected illegal EVNT value"); + "scanAdd detected illegal EVNT value"); + precord->scan = SCAN_PASSIVE; return; } evnt = (signed)precord->evnt; - psl = papEvent[evnt]; - if(psl==NULL) + priority = precord->prio; + if(priority<0 || priority>=NUM_CALLBACK_PRIORITIES) { + recGblRecordError(-1,(void *)precord, + "scanAdd: illegal prio field"); + precord->scan = SCAN_PASSIVE; + return; + } + pevent_scan_list = pevent_list[priority][evnt]; + if(pevent_scan_list) psl = &pevent_scan_list->scan_list; + if(!pevent_scan_list || !psl) recGblRecordError(-1,(void *)precord, "scanDelete for bad evnt"); - else + else deleteFromList(precord,psl); } else if(scan==SCAN_IO_EVENT) { - struct io_scan_list *piosl=NULL; + io_scan_list *piosl=NULL; int priority; DEVSUPFUN get_ioint_info; @@ -315,7 +311,7 @@ void scanDelete(struct dbCommon *precord) int scanppl() /*print periodic list*/ { - struct scan_list *psl; + scan_list *psl; char message[80]; double period; int i; @@ -325,7 +321,7 @@ int scanppl() /*print periodic list*/ if(psl==NULL) continue; period = psl->ticks; period /= vxTicksPerSecond; - sprintf(message,"Scan Period= %f seconds\n",period); + sprintf(message,"Scan Period= %f seconds ",period); printList(psl,message); } return(0); @@ -333,22 +329,25 @@ int scanppl() /*print periodic list*/ int scanpel() /*print event list */ { - struct scan_list *psl; - char message[80]; - int i; + char message[80]; + int priority,evnt; + event_scan_list *pevent_scan_list; - for (i=0; iscan_list) ==0) continue; + sprintf(message,"Event %d Priority %s",evnt,priorityName[priority]); + printList(&pevent_scan_list->scan_list,message); + } } return(0); } int scanpiol() /* print io_event list */ { - struct io_scan_list *piosl; + io_scan_list *piosl; int priority; char message[80]; @@ -364,14 +363,50 @@ int scanpiol() /* print io_event list */ return(0); } +static void eventCallback(event_scan_list *pevent_scan_list) +{ + scanList(&pevent_scan_list->scan_list); +} + +static void initEvent(void) +{ + int evnt,priority; + + for(priority=0; priority=MAX_EVENTS) { + errMessage(-1,"illegal event passed to post_event"); + return; + } + evnt = (unsigned)event; + for(priority=0; priorityscan_list) >0) + callbackRequest((void *)pevent_scan_list); + } +} + void scanIoInit(IOSCANPVT *ppioscanpvt) { - struct io_scan_list *piosl; + io_scan_list *piosl; int priority; /* allocate an array of io_scan_lists. One for each priority */ /* IOSCANPVT will hold the address of this array of structures */ - *ppioscanpvt=dbCalloc(NUM_CALLBACK_PRIORITIES,sizeof(struct io_scan_list)); + *ppioscanpvt=dbCalloc(NUM_CALLBACK_PRIORITIES,sizeof(io_scan_list)); for(priority=0, piosl=*ppioscanpvt; prioritycallback.callback = ioeventCallback; @@ -387,7 +422,7 @@ void scanIoInit(IOSCANPVT *ppioscanpvt) void scanIoRequest(IOSCANPVT pioscanpvt) { - struct io_scan_list *piosl; + io_scan_list *piosl; int priority; if(!interruptAccept) return; @@ -447,7 +482,7 @@ static void initOnce(void) taskwdInsert(onceTaskId,NULL,0L); } -static void periodicTask(struct scan_list *psl) +static void periodicTask(scan_list *psl) { unsigned long start_time,end_time; @@ -468,7 +503,7 @@ static void periodicTask(struct scan_list *psl) static void initPeriodic() { dbMenu *pmenu; - struct scan_list *psl; + scan_list *psl; float temp; int i; @@ -478,10 +513,10 @@ static void initPeriodic() return; } nPeriodic = pmenu->nChoice - SCAN_1ST_PERIODIC; - papPeriodic = dbCalloc(nPeriodic,sizeof(struct scan_list*)); + papPeriodic = dbCalloc(nPeriodic,sizeof(scan_list*)); periodicTaskId = dbCalloc(nPeriodic,sizeof(int)); for(i=0; ilock); ellInit(&psl->list); @@ -492,7 +527,7 @@ static void initPeriodic() static void spawnPeriodic(int ind) { - struct scan_list *psl; + scan_list *psl; char taskName[20]; psl = papPeriodic[ind]; @@ -506,7 +541,7 @@ static void spawnPeriodic(int ind) static void wdPeriodic(long ind) { - struct scan_list *psl; + scan_list *psl; if(!scanRestart)return; psl = papPeriodic[ind]; @@ -516,83 +551,20 @@ static void wdPeriodic(long ind) spawnPeriodic(ind); } -static void eventTask(void) +static void ioeventCallback(io_scan_list *piosl) { - unsigned char event; - struct scan_list *psl; - - while(TRUE) { - if(semTake(eventSem,WAIT_FOREVER)!=OK) - errMessage(0,"semTake returned error in eventTask"); - while (rngNBytes(eventQ)>=sizeof(unsigned char)){ - if(rngBufGet(eventQ,(void *)&event,sizeof(unsigned char))!=sizeof(unsigned char)) - errMessage(0,"rngBufGet returned error in eventTask"); - if(event>MAX_EVENTS-1) { - errMessage(-1,"eventTask received an illegal event"); - continue; - } - if(papEvent[event]==NULL) continue; - psl = papEvent[event]; - if(psl) scanList(psl); - } - } -} - -static void initEvent(void) -{ - int i; - - for(i=0; ilock); - } - spawnEvent(); -} - -static void ioeventCallback(struct io_scan_list *piosl) -{ - struct scan_list *psl=&piosl->scan_list; + scan_list *psl=&piosl->scan_list; scanList(psl); } -static void printList(struct scan_list *psl,char *message) +static void printList(scan_list *psl,char *message) { - struct scan_element *pse; + scan_element *pse; FASTLOCK(&psl->lock); - pse = (struct scan_element *)ellFirst(&psl->list); + pse = (scan_element *)ellFirst(&psl->list); FASTUNLOCK(&psl->lock); if(pse==NULL) return; printf("%s\n",message); @@ -604,23 +576,23 @@ static void printList(struct scan_list *psl,char *message) printf("Returning because list changed while processing."); return; } - pse = (struct scan_element *)ellNext((void *)pse); + pse = (scan_element *)ellNext((void *)pse); FASTUNLOCK(&psl->lock); } } -static void scanList(struct scan_list *psl) +static void scanList(scan_list *psl) { /*In reading this code remember that the call to dbProcess can result*/ /*in the SCAN field being changed in an arbitrary number of records */ - struct scan_element *pse,*prev,*next; + scan_element *pse,*prev,*next; FASTLOCK(&psl->lock); psl->modified = FALSE; - pse = (struct scan_element *)ellFirst(&psl->list); + pse = (scan_element *)ellFirst(&psl->list); prev = NULL; - next = (struct scan_element *)ellNext((void *)pse); + next = (scan_element *)ellNext((void *)pse); FASTUNLOCK(&psl->lock); while(pse!=NULL) { struct dbCommon *precord = pse->precord; @@ -631,27 +603,27 @@ static void scanList(struct scan_list *psl) FASTLOCK(&psl->lock); if(!psl->modified) { prev = pse; - pse = (struct scan_element *)ellNext((void *)pse); - if(pse!=NULL)next = (struct scan_element *)ellNext((void *)pse); + pse = (scan_element *)ellNext((void *)pse); + if(pse!=NULL)next = (scan_element *)ellNext((void *)pse); } else if (pse->pscan_list==psl) { /*This scan element is still in same scan list*/ prev = pse; - pse = (struct scan_element *)ellNext((void *)pse); - if(pse!=NULL)next = (struct scan_element *)ellNext((void *)pse); + pse = (scan_element *)ellNext((void *)pse); + if(pse!=NULL)next = (scan_element *)ellNext((void *)pse); psl->modified = FALSE; } else if (prev!=NULL && prev->pscan_list==psl) { /*Previous scan element is still in same scan list*/ - pse = (struct scan_element *)ellNext((void *)prev); + pse = (scan_element *)ellNext((void *)prev); if(pse!=NULL) { - prev = (struct scan_element *)ellPrevious((void *)pse); - next = (struct scan_element *)ellNext((void *)pse); + prev = (scan_element *)ellPrevious((void *)pse); + next = (scan_element *)ellNext((void *)pse); } psl->modified = FALSE; } else if (next!=NULL && next->pscan_list==psl) { /*Next scan element is still in same scan list*/ pse = next; - prev = (struct scan_element *)ellPrevious((void *)pse); - next = (struct scan_element *)ellNext((void *)pse); + prev = (scan_element *)ellPrevious((void *)pse); + next = (scan_element *)ellNext((void *)pse); psl->modified = FALSE; } else { /*Too many changes. Just wait till next period*/ @@ -681,26 +653,26 @@ static void buildScanLists(void) } } -static void addToList(struct dbCommon *precord,struct scan_list *psl) +static void addToList(struct dbCommon *precord,scan_list *psl) { - struct scan_element *pse,*ptemp; + scan_element *pse,*ptemp; FASTLOCK(&psl->lock); - pse = (struct scan_element *)(precord->spvt); + pse = (scan_element *)(precord->spvt); if(pse==NULL) { - pse = dbCalloc(1,sizeof(struct scan_element)); + pse = dbCalloc(1,sizeof(scan_element)); precord->spvt = (void *)pse; pse->precord = precord; } pse ->pscan_list = psl; - ptemp = (struct scan_element *)ellFirst(&psl->list); + ptemp = (scan_element *)ellFirst(&psl->list); while(ptemp!=NULL) { if(ptemp->precord->phas>precord->phas) { ellInsert(&psl->list, ellPrevious((void *)ptemp),(void *)pse); break; } - ptemp = (struct scan_element *)ellNext((void *)ptemp); + ptemp = (scan_element *)ellNext((void *)ptemp); } if(ptemp==NULL) ellAdd(&psl->list,(void *)pse); psl->modified = TRUE; @@ -708,16 +680,16 @@ static void addToList(struct dbCommon *precord,struct scan_list *psl) return; } -static void deleteFromList(struct dbCommon *precord,struct scan_list *psl) +static void deleteFromList(struct dbCommon *precord,scan_list *psl) { - struct scan_element *pse; + scan_element *pse; FASTLOCK(&psl->lock); if(precord->spvt==NULL) { FASTUNLOCK(&psl->lock); return; } - pse = (struct scan_element *)(precord->spvt); + pse = (scan_element *)(precord->spvt); if(pse==NULL || pse->pscan_list!=psl) { FASTUNLOCK(&psl->lock); errMessage(-1,"deleteFromList failed");