diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 5c957e771..cf0f0b674 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -369,6 +369,10 @@ giving correct initial monitor behavior in some circumstances.

Fixed a crash when ALG (algorithm) was changed to Average at runtime.

+

Named Soft Events

+ +

Soft events can now be meaningful strings instead of numbers 1-255. +

configure/RELEASE Enhancements

Variable definitions in a configure/RELEASE file may now use the diff --git a/named-soft-events.patch b/named-soft-events.patch new file mode 100644 index 000000000..372969375 --- /dev/null +++ b/named-soft-events.patch @@ -0,0 +1,575 @@ +=== modified file 'documentation/RELEASE_NOTES.html' +--- documentation/RELEASE_NOTES.html 2010-10-26 15:49:26 +0000 ++++ documentation/RELEASE_NOTES.html 2010-10-27 20:51:01 +0000 +@@ -138,6 +138,10 @@ + +

Fixed crash when ALG (algorithm) was changed to Average at runtime.

+ ++

Named Soft Events

++ ++

Soft events can now be meaningful strings instead of numbers 1-255. ++ +

configure/RELEASE Enhancements

+ +

Variable definitions in a configure/RELEASE file may now use the + +=== modified file 'src/db/dbCommon.dbd' +--- src/db/dbCommon.dbd 2009-04-23 20:35:02 +0000 ++++ src/db/dbCommon.dbd 2010-10-27 20:51:01 +0000 +@@ -43,10 +43,11 @@ + special(SPC_SCAN) + interest(1) + } +- field(EVNT,DBF_SHORT) { +- prompt("Event Number") ++ field(EVNT,DBF_STRING) { ++ prompt("Event Name") + promptgroup(GUI_SCAN) + special(SPC_SCAN) ++ size(40) + interest(1) + } + field(TSE,DBF_SHORT) { + +=== modified file 'src/db/dbIocRegister.c' +--- src/db/dbIocRegister.c 2009-01-16 20:50:40 +0000 ++++ src/db/dbIocRegister.c 2010-10-27 20:51:01 +0000 +@@ -266,11 +266,11 @@ + { scanppl(args[0].dval);} + + /* scanpel */ +-static const iocshArg scanpelArg0 = { "event number",iocshArgInt}; ++static const iocshArg scanpelArg0 = { "event name",iocshArgString}; + static const iocshArg * const scanpelArgs[1] = {&scanpelArg0}; + static const iocshFuncDef scanpelFuncDef = {"scanpel",1,scanpelArgs}; + static void scanpelCallFunc(const iocshArgBuf *args) +-{ scanpel(args[0].ival);} ++{ scanpel(args[0].sval);} + + /* scanpiol */ + static const iocshFuncDef scanpiolFuncDef = {"scanpiol",0}; + +=== modified file 'src/db/dbScan.c' +--- src/db/dbScan.c 2009-04-03 17:46:26 +0000 ++++ src/db/dbScan.c 2010-10-27 20:51:01 +0000 +@@ -101,12 +101,13 @@ + + /* EVENT */ + +-#define MAX_EVENTS 256 +-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]; ++typedef struct event_list { ++ CALLBACK callback[NUM_CALLBACK_PRIORITIES]; ++ scan_list scan_list[NUM_CALLBACK_PRIORITIES]; ++ struct event_list *next; ++ char event_name[MAX_STRING_SIZE]; ++} event_list; ++static event_list * volatile pevent_list[256]; + + + /* IO_EVENT*/ +@@ -204,35 +205,24 @@ + recGblRecordError(-1, (void *)precord, + "scanAdd detected illegal SCAN value"); + } else if (scan == menuScanEvent) { +- int evnt; ++ char* eventname; + int prio; +- event_scan_list *pesl; ++ event_list *pel; + +- evnt = precord->evnt; +- if (evnt < 0 || evnt >= MAX_EVENTS) { ++ eventname = precord->evnt; ++ if (strlen(eventname) >= MAX_STRING_SIZE) { + recGblRecordError(S_db_badField, (void *)precord, +- "scanAdd detected illegal EVNT value"); +- precord->scan = menuScanPassive; ++ "scanAdd: too long EVNT value"); + return; + } + prio = precord->prio; + if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) { + recGblRecordError(-1, (void *)precord, + "scanAdd: illegal prio field"); +- precord->scan = menuScanPassive; + return; + } +- pesl = pevent_list[prio][evnt]; +- if (pesl == NULL) { +- pesl = dbCalloc(1, sizeof(event_scan_list)); +- pevent_list[prio][evnt] = pesl; +- pesl->scan_list.lock = epicsMutexMustCreate(); +- callbackSetCallback(eventCallback, &pesl->callback); +- callbackSetPriority(prio, &pesl->callback); +- callbackSetUser(pesl, &pesl->callback); +- ellInit(&pesl->scan_list.list); +- } +- addToList(precord, &pesl->scan_list); ++ pel = eventNameToHandle(eventname); ++ if (pel) addToList(precord, &pel->scan_list[prio]); + } else if (scan == menuScanI_O_Intr) { + io_scan_list *piosl = NULL; + int prio; +@@ -287,31 +277,25 @@ + recGblRecordError(-1, (void *)precord, + "scanDelete detected illegal SCAN value"); + } else if (scan == menuScanEvent) { +- int evnt; ++ char* eventname; + int prio; +- event_scan_list *pesl; ++ event_list *pel; + scan_list *psl = 0; + +- evnt = precord->evnt; +- if (evnt < 0 || evnt >= MAX_EVENTS) { +- recGblRecordError(S_db_badField, (void *)precord, +- "scanAdd detected illegal EVNT value"); +- precord->scan = menuScanPassive; +- return; +- } ++ eventname = precord->evnt; + prio = precord->prio; + if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) { + recGblRecordError(-1, (void *)precord, +- "scanAdd: illegal prio field"); +- precord->scan = menuScanPassive; ++ "scanDelete detected illegal PRIO field"); + return; + } +- pesl = pevent_list[prio][evnt]; +- if (pesl) psl = &pesl->scan_list; +- if (!pesl || !psl) +- recGblRecordError(-1, (void *)precord, +- "scanDelete for bad evnt"); +- else ++ do /* multithreading: make sure pel is consistent */ ++ pel = pevent_list[0]; ++ while (pel != pevent_list[0]); ++ for (; pel; pel=pel->next) { ++ if (strcmp(pel->event_name, eventname) == 0) break; ++ } ++ if (pel && (psl = &pel->scan_list[prio])) + deleteFromList(precord, psl); + } else if (scan == menuScanI_O_Intr) { + io_scan_list *piosl=NULL; +@@ -372,21 +356,22 @@ + return 0; + } + +-int scanpel(int event_number) /* print event list */ ++int scanpel(char* eventname) /* print event list */ + { + char message[80]; +- int prio, evnt; +- event_scan_list *pesl; +- +- for (evnt = 0; evnt < MAX_EVENTS; evnt++) { +- if (event_number && evntevent_number) break; +- for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { +- pesl = pevent_list[prio][evnt]; +- if (!pesl) continue; +- if (ellCount(&pesl->scan_list.list) == 0) continue; +- sprintf(message, "Event %d Priority %s", evnt, priorityName[prio]); +- printList(&pesl->scan_list, message); ++ int prio; ++ event_list *pel; ++ ++ do /* multithreading: make sure pel is consistent */ ++ pel = pevent_list[0]; ++ while (pel != pevent_list[0]); ++ for (; pel; pel = pel->next) { ++ if (!eventname || strcmp(pel->event_name, eventname) == 0) { ++ for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { ++ if (ellCount(&pel->scan_list[prio].list) == 0) continue; ++ sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]); ++ printList(&pel->scan_list[prio], message); ++ } + } + } + return 0; +@@ -412,39 +397,73 @@ + + static void eventCallback(CALLBACK *pcallback) + { +- event_scan_list *pesl; ++ scan_list *psl; + +- callbackGetUser(pesl, pcallback); +- scanList(&pesl->scan_list); ++ callbackGetUser(psl, pcallback); ++ scanList(psl); + } + + static void initEvent(void) + { +- int evnt, prio; +- ++} ++ ++event_list *eventNameToHandle(char *eventname) ++{ ++ int prio; ++ event_list *pel; ++ static epicsMutexId lock = NULL; ++ ++ if (!lock) lock = epicsMutexMustCreate(); ++ if (!eventname || eventname[0] == 0) return NULL; ++ epicsMutexMustLock(lock); ++ for (pel = pevent_list[0]; pel; pel=pel->next) { ++ if (strcmp(pel->event_name, eventname) == 0) break; ++ } ++ if (pel == NULL) { ++ pel = dbCalloc(1, sizeof(event_list)); ++ strcpy(pel->event_name, eventname); ++ for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { ++ callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]); ++ callbackSetPriority(prio, &pel->callback[prio]); ++ callbackSetCallback(eventCallback, &pel->callback[prio]); ++ pel->scan_list[prio].lock = epicsMutexMustCreate(); ++ ellInit(&pel->scan_list[prio].list); ++ } ++ pel->next=pevent_list[0]; ++ pevent_list[0]=pel; ++ { /* backward compatibility */ ++ char* p; ++ long e = strtol(eventname, &p, 0); ++ if (*p == 0 && e > 0 && e <= 255) ++ pevent_list[e]=pel; ++ } ++ } ++ epicsMutexUnlock(lock); ++ return pel; ++} ++ ++void postEvent(event_list *pel) ++{ ++ int prio; ++ ++ if (scanCtl != ctlRun) return; ++ if (!pel) return; + for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { +- for (evnt = 0; evnt < MAX_EVENTS; evnt++) { +- pevent_list[prio][evnt] = NULL; +- } ++ if (ellCount(&pel->scan_list[prio].list) >0) ++ callbackRequest(&pel->callback[prio]); + } + } + ++/* backward compatibility */ + void post_event(int event) + { +- int prio; +- event_scan_list *pesl; +- +- if (scanCtl != ctlRun) return; +- if (event < 0 || event >= MAX_EVENTS) { +- errMessage(-1, "illegal event passed to post_event"); +- return; +- } +- for (prio=0; prioscan_list.list) >0) +- callbackRequest((void *)pesl); +- } ++ event_list* pel; ++ ++ if (event <= 0 || event > 255) return; ++ do { /* multithreading: make sure pel is consistent */ ++ pel = pevent_list[event]; ++ } while (pel != pevent_list[event]); ++ postEvent(pel); + } + + void scanIoInit(IOSCANPVT *ppioscanpvt) + +=== modified file 'src/db/dbScan.h' +--- src/db/dbScan.h 2010-10-05 19:27:37 +0000 ++++ src/db/dbScan.h 2010-10-27 20:51:01 +0000 +@@ -19,6 +19,7 @@ + + #include "menuScan.h" + #include "shareLib.h" ++#include "compilerDependencies.h" + + #ifdef __cplusplus + extern "C" { +@@ -36,6 +37,7 @@ + struct io_scan_list; + + typedef struct io_scan_list *IOSCANPVT; ++typedef struct event_list *EVENTPVT; + + struct dbCommon; + +@@ -43,7 +45,9 @@ + epicsShareFunc void scanRun(void); + epicsShareFunc void scanPause(void); + +-epicsShareFunc void post_event(int event); ++epicsShareFunc EVENTPVT eventNameToHandle(char* event); ++epicsShareFunc void postEvent(EVENTPVT epvt); ++epicsShareFunc void post_event(int event) EPICS_DEPRECATED; + epicsShareFunc void scanAdd(struct dbCommon *); + epicsShareFunc void scanDelete(struct dbCommon *); + epicsShareFunc double scanPeriod(int scan); +@@ -54,7 +58,7 @@ + epicsShareFunc int scanppl(double rate); + + /*print event lists*/ +-epicsShareFunc int scanpel(int event_number); ++epicsShareFunc int scanpel(char *event_name); + + /*print io_event list*/ + epicsShareFunc int scanpiol(void); + +=== modified file 'src/dev/softDev/devEventSoft.c' +--- src/dev/softDev/devEventSoft.c 2010-10-05 19:27:37 +0000 ++++ src/dev/softDev/devEventSoft.c 2010-10-27 20:51:01 +0000 +@@ -51,7 +51,7 @@ + /* INP must be CONSTANT, PV_LINK, DB_LINK or CA_LINK*/ + switch (prec->inp.type) { + case CONSTANT: +- if (recGblInitConstantLink(&prec->inp, DBF_USHORT, &prec->val)) ++ if (recGblInitConstantLink(&prec->inp, DBF_STRING, &prec->val)) + prec->udf = FALSE; + break; + case PV_LINK: +@@ -69,13 +69,20 @@ + static long read_event(eventRecord *prec) + { + long status; ++ char newEvent[MAX_STRING_SIZE]; + +- status = dbGetLink(&prec->inp, DBR_USHORT, &prec->val, 0, 0); +- if (!status) { +- prec->udf = FALSE; +- if (prec->tsel.type == CONSTANT && +- prec->tse == epicsTimeEventDeviceTime) +- dbGetTimeStamp(&prec->inp, &prec->time); ++ if (prec->inp.type != CONSTANT) ++ { ++ status = dbGetLinkValue(&prec->inp, DBR_STRING, newEvent, 0, 0); ++ if (status) return status; ++ if (strcmp(newEvent, prec->val) != 0) { ++ strcpy(prec->val, newEvent); ++ prec->epvt = eventNameToHandle(prec->val); ++ } + } +- return status; ++ prec->udf = FALSE; ++ if (prec->tsel.type == CONSTANT && ++ prec->tse == epicsTimeEventDeviceTime) ++ dbGetTimeStamp(&prec->inp, &prec->time); ++ return 0; + } + +=== modified file 'src/rec/calcoutRecord.c' +--- src/rec/calcoutRecord.c 2010-04-05 18:49:18 +0000 ++++ src/rec/calcoutRecord.c 2010-10-27 20:51:01 +0000 +@@ -197,6 +197,8 @@ + callbackSetUser(prec, &prpvt->checkLinkCb); + prpvt->cbScheduled = 0; + ++ prec->epvt = eventNameToHandle(prec->oevt); ++ + if (pcalcoutDSET->init_record) pcalcoutDSET->init_record(prec); + prec->pval = prec->val; + prec->mlst = prec->val; +@@ -357,6 +359,9 @@ + } + db_post_events(prec, plinkValid, DBE_VALUE); + return 0; ++ case(calcoutRecordOEVT): ++ prec->epvt = eventNameToHandle(prec->oevt); ++ return 0; + default: + recGblDbaddrError(S_db_badChoice, paddr, "calc: special"); + return(S_db_badChoice); +@@ -539,27 +544,21 @@ + if (prec->nsev < INVALID_ALARM ) { + /* Output the value */ + status = writeValue(prec); +- /* post event if output event != 0 */ +- if (prec->oevt > 0) { +- post_event((int)prec->oevt); +- } ++ /* post output event if set */ ++ if (prec->epvt) postEvent(prec->epvt); + } else switch (prec->ivoa) { + case menuIvoaContinue_normally: + status = writeValue(prec); +- /* post event if output event != 0 */ +- if (prec->oevt > 0) { +- post_event((int)prec->oevt); +- } ++ /* post output event if set */ ++ if (prec->epvt) postEvent(prec->epvt); + break; + case menuIvoaDon_t_drive_outputs: + break; + case menuIvoaSet_output_to_IVOV: + prec->oval = prec->ivov; + status = writeValue(prec); +- /* post event if output event != 0 */ +- if (prec->oevt > 0) { +- post_event((int)prec->oevt); +- } ++ /* post output event if set */ ++ if (prec->epvt) postEvent(prec->epvt); + break; + default: + status = -1; + +=== modified file 'src/rec/calcoutRecord.dbd' +--- src/rec/calcoutRecord.dbd 2010-10-04 18:46:09 +0000 ++++ src/rec/calcoutRecord.dbd 2010-10-27 20:51:01 +0000 +@@ -255,10 +255,19 @@ + prompt("OCAL Valid") + interest(1) + } +- field(OEVT,DBF_USHORT) { ++ field(OEVT,DBF_STRING) { + prompt("Event To Issue") + promptgroup(GUI_CLOCK) ++ special(SPC_MOD) + asl(ASL0) ++ size(40) ++ } ++ %#include "dbScan.h" ++ field(EPVT, DBF_NOACCESS) { ++ prompt("Event private") ++ special(SPC_NOMOD) ++ interest(4) ++ extra("EVENTPVT epvt") + } + field(IVOA,DBF_MENU) { + prompt("INVALID output action") + +=== modified file 'src/rec/eventRecord.c' +--- src/rec/eventRecord.c 2010-10-05 19:27:37 +0000 ++++ src/rec/eventRecord.c 2010-10-27 20:51:01 +0000 +@@ -32,6 +32,7 @@ + #include "errMdef.h" + #include "recSup.h" + #include "recGbl.h" ++#include "special.h" + #include "menuYesNo.h" + #define GEN_SIZE_OFFSET + #include "eventRecord.h" +@@ -43,7 +44,7 @@ + #define initialize NULL + static long init_record(eventRecord *, int); + static long process(eventRecord *); +-#define special NULL ++static long special(DBADDR *, int); + static long get_value(eventRecord *, struct valueDes *); + #define cvt_dbaddr NULL + #define get_array_info NULL +@@ -103,9 +104,11 @@ + } + + if (prec->siol.type == CONSTANT) { +- recGblInitConstantLink(&prec->siol,DBF_USHORT,&prec->sval); ++ recGblInitConstantLink(&prec->siol,DBF_STRING,&prec->sval); + } + ++ prec->epvt = eventNameToHandle(prec->val); ++ + if( (pdset=(struct eventdset *)(prec->dset)) && (pdset->init_record) ) + status=(*pdset->init_record)(prec); + return(status); +@@ -123,7 +126,7 @@ + if ( !pact && prec->pact ) return(0); + prec->pact = TRUE; + +- if(prec->val>0) post_event((int)prec->val); ++ postEvent(prec->epvt); + + recGblGetTimeStamp(prec); + +@@ -137,10 +140,21 @@ + return(status); + } + ++ ++static long special(DBADDR *paddr, int after) ++{ ++ eventRecord *prec = (eventRecord *)paddr->precord; ++ ++ if (!after) return 0; ++ if (dbGetFieldIndex(paddr) == eventRecordVAL) { ++ prec->epvt = eventNameToHandle(prec->val); ++ } ++} + ++ + static long get_value(eventRecord *prec, struct valueDes *pvdes) + { +- pvdes->field_type = DBF_USHORT; ++ pvdes->field_type = DBF_STRING; + pvdes->no_elements=1; + pvdes->pvalue = (void *)(&prec->val); + return(0); +@@ -177,10 +191,13 @@ + return(status); + } + if (prec->simm == menuYesNoYES){ +- status=dbGetLink(&(prec->siol),DBR_USHORT, ++ status=dbGetLink(&(prec->siol),DBR_STRING, + &(prec->sval),0,0); + if (status==0) { +- prec->val=prec->sval; ++ if (strcmp(prec->sval, prec->val) != 0) { ++ strcpy(prec->val, prec->sval); ++ prec->epvt = eventNameToHandle(prec->val); ++ } + prec->udf=FALSE; + } + } else { + +=== modified file 'src/rec/eventRecord.dbd' +--- src/rec/eventRecord.dbd 2002-07-12 21:35:43 +0000 ++++ src/rec/eventRecord.dbd 2010-10-27 20:51:01 +0000 +@@ -9,10 +9,19 @@ + #************************************************************************* + recordtype(event) { + include "dbCommon.dbd" +- field(VAL,DBF_USHORT) { +- prompt("Event Number To Post") ++ field(VAL,DBF_STRING) { ++ prompt("Event Name To Post") + promptgroup(GUI_INPUTS) ++ special(SPC_MOD) + asl(ASL0) ++ size(40) ++ } ++ %#include "dbScan.h" ++ field(EPVT, DBF_NOACCESS) { ++ prompt("Event private") ++ special(SPC_NOMOD) ++ interest(4) ++ extra("EVENTPVT epvt") + } + field(INP,DBF_INLINK) { + prompt("Input Specification") +@@ -24,8 +33,9 @@ + promptgroup(GUI_INPUTS) + interest(1) + } +- field(SVAL,DBF_USHORT) { ++ field(SVAL,DBF_STRING) { + prompt("Simulation Value") ++ size(40) + } + field(SIML,DBF_INLINK) { + prompt("Sim Mode Location") + diff --git a/src/db/dbCommon.dbd b/src/db/dbCommon.dbd index eb8e7bf35..94128ca35 100644 --- a/src/db/dbCommon.dbd +++ b/src/db/dbCommon.dbd @@ -43,10 +43,11 @@ special(SPC_SCAN) interest(1) } - field(EVNT,DBF_SHORT) { - prompt("Event Number") + field(EVNT,DBF_STRING) { + prompt("Event Name") promptgroup(GUI_SCAN) special(SPC_SCAN) + size(40) interest(1) } field(TSE,DBF_SHORT) { diff --git a/src/db/dbIocRegister.c b/src/db/dbIocRegister.c index a82337f03..c64738bbd 100644 --- a/src/db/dbIocRegister.c +++ b/src/db/dbIocRegister.c @@ -266,11 +266,11 @@ static void scanpplCallFunc(const iocshArgBuf *args) { scanppl(args[0].dval);} /* scanpel */ -static const iocshArg scanpelArg0 = { "event number",iocshArgInt}; +static const iocshArg scanpelArg0 = { "event name",iocshArgString}; static const iocshArg * const scanpelArgs[1] = {&scanpelArg0}; static const iocshFuncDef scanpelFuncDef = {"scanpel",1,scanpelArgs}; static void scanpelCallFunc(const iocshArgBuf *args) -{ scanpel(args[0].ival);} +{ scanpel(args[0].sval);} /* scanpiol */ static const iocshFuncDef scanpiolFuncDef = {"scanpiol",0}; diff --git a/src/db/dbScan.c b/src/db/dbScan.c index 5a372d6a9..1720a5d85 100644 --- a/src/db/dbScan.c +++ b/src/db/dbScan.c @@ -101,12 +101,13 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = { /* EVENT */ -#define MAX_EVENTS 256 -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]; +typedef struct event_list { + CALLBACK callback[NUM_CALLBACK_PRIORITIES]; + scan_list scan_list[NUM_CALLBACK_PRIORITIES]; + struct event_list *next; + char event_name[MAX_STRING_SIZE]; +} event_list; +static event_list * volatile pevent_list[256]; /* IO_EVENT*/ @@ -204,35 +205,24 @@ void scanAdd(struct dbCommon *precord) recGblRecordError(-1, (void *)precord, "scanAdd detected illegal SCAN value"); } else if (scan == menuScanEvent) { - int evnt; + char* eventname; int prio; - event_scan_list *pesl; + event_list *pel; - evnt = precord->evnt; - if (evnt < 0 || evnt >= MAX_EVENTS) { + eventname = precord->evnt; + if (strlen(eventname) >= MAX_STRING_SIZE) { recGblRecordError(S_db_badField, (void *)precord, - "scanAdd detected illegal EVNT value"); - precord->scan = menuScanPassive; + "scanAdd: too long EVNT value"); return; } prio = precord->prio; if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) { recGblRecordError(-1, (void *)precord, "scanAdd: illegal prio field"); - precord->scan = menuScanPassive; return; } - pesl = pevent_list[prio][evnt]; - if (pesl == NULL) { - pesl = dbCalloc(1, sizeof(event_scan_list)); - pevent_list[prio][evnt] = pesl; - pesl->scan_list.lock = epicsMutexMustCreate(); - callbackSetCallback(eventCallback, &pesl->callback); - callbackSetPriority(prio, &pesl->callback); - callbackSetUser(pesl, &pesl->callback); - ellInit(&pesl->scan_list.list); - } - addToList(precord, &pesl->scan_list); + pel = eventNameToHandle(eventname); + if (pel) addToList(precord, &pel->scan_list[prio]); } else if (scan == menuScanI_O_Intr) { io_scan_list *piosl = NULL; int prio; @@ -287,31 +277,25 @@ void scanDelete(struct dbCommon *precord) recGblRecordError(-1, (void *)precord, "scanDelete detected illegal SCAN value"); } else if (scan == menuScanEvent) { - int evnt; + char* eventname; int prio; - event_scan_list *pesl; + event_list *pel; scan_list *psl = 0; - evnt = precord->evnt; - if (evnt < 0 || evnt >= MAX_EVENTS) { - recGblRecordError(S_db_badField, (void *)precord, - "scanAdd detected illegal EVNT value"); - precord->scan = menuScanPassive; - return; - } + eventname = precord->evnt; prio = precord->prio; if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) { recGblRecordError(-1, (void *)precord, - "scanAdd: illegal prio field"); - precord->scan = menuScanPassive; + "scanDelete detected illegal PRIO field"); return; } - pesl = pevent_list[prio][evnt]; - if (pesl) psl = &pesl->scan_list; - if (!pesl || !psl) - recGblRecordError(-1, (void *)precord, - "scanDelete for bad evnt"); - else + do /* multithreading: make sure pel is consistent */ + pel = pevent_list[0]; + while (pel != pevent_list[0]); + for (; pel; pel=pel->next) { + if (strcmp(pel->event_name, eventname) == 0) break; + } + if (pel && (psl = &pel->scan_list[prio])) deleteFromList(precord, psl); } else if (scan == menuScanI_O_Intr) { io_scan_list *piosl=NULL; @@ -372,21 +356,22 @@ int scanppl(double period) /* print periodic list */ return 0; } -int scanpel(int event_number) /* print event list */ +int scanpel(char* eventname) /* print event list */ { char message[80]; - int prio, evnt; - event_scan_list *pesl; - - for (evnt = 0; evnt < MAX_EVENTS; evnt++) { - if (event_number && evntevent_number) break; - for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { - pesl = pevent_list[prio][evnt]; - if (!pesl) continue; - if (ellCount(&pesl->scan_list.list) == 0) continue; - sprintf(message, "Event %d Priority %s", evnt, priorityName[prio]); - printList(&pesl->scan_list, message); + int prio; + event_list *pel; + + do /* multithreading: make sure pel is consistent */ + pel = pevent_list[0]; + while (pel != pevent_list[0]); + for (; pel; pel = pel->next) { + if (!eventname || strcmp(pel->event_name, eventname) == 0) { + for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { + if (ellCount(&pel->scan_list[prio].list) == 0) continue; + sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]); + printList(&pel->scan_list[prio], message); + } } } return 0; @@ -412,39 +397,73 @@ int scanpiol(void) /* print io_event list */ static void eventCallback(CALLBACK *pcallback) { - event_scan_list *pesl; + scan_list *psl; - callbackGetUser(pesl, pcallback); - scanList(&pesl->scan_list); + callbackGetUser(psl, pcallback); + scanList(psl); } static void initEvent(void) { - int evnt, prio; +} - for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { - for (evnt = 0; evnt < MAX_EVENTS; evnt++) { - pevent_list[prio][evnt] = NULL; +event_list *eventNameToHandle(char *eventname) +{ + int prio; + event_list *pel; + static epicsMutexId lock = NULL; + + if (!lock) lock = epicsMutexMustCreate(); + if (!eventname || eventname[0] == 0) return NULL; + epicsMutexMustLock(lock); + for (pel = pevent_list[0]; pel; pel=pel->next) { + if (strcmp(pel->event_name, eventname) == 0) break; + } + if (pel == NULL) { + pel = dbCalloc(1, sizeof(event_list)); + strcpy(pel->event_name, eventname); + for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { + callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]); + callbackSetPriority(prio, &pel->callback[prio]); + callbackSetCallback(eventCallback, &pel->callback[prio]); + pel->scan_list[prio].lock = epicsMutexMustCreate(); + ellInit(&pel->scan_list[prio].list); } + pel->next=pevent_list[0]; + pevent_list[0]=pel; + { /* backward compatibility */ + char* p; + long e = strtol(eventname, &p, 0); + if (*p == 0 && e > 0 && e <= 255) + pevent_list[e]=pel; + } + } + epicsMutexUnlock(lock); + return pel; +} + +void postEvent(event_list *pel) +{ + int prio; + + if (scanCtl != ctlRun) return; + if (!pel) return; + for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) { + if (ellCount(&pel->scan_list[prio].list) >0) + callbackRequest(&pel->callback[prio]); } } +/* backward compatibility */ void post_event(int event) { - int prio; - event_scan_list *pesl; - - if (scanCtl != ctlRun) return; - if (event < 0 || event >= MAX_EVENTS) { - errMessage(-1, "illegal event passed to post_event"); - return; - } - for (prio=0; prioscan_list.list) >0) - callbackRequest((void *)pesl); - } + event_list* pel; + + if (event <= 0 || event > 255) return; + do { /* multithreading: make sure pel is consistent */ + pel = pevent_list[event]; + } while (pel != pevent_list[event]); + postEvent(pel); } void scanIoInit(IOSCANPVT *ppioscanpvt) diff --git a/src/db/dbScan.h b/src/db/dbScan.h index e046235ca..c2d8818e1 100644 --- a/src/db/dbScan.h +++ b/src/db/dbScan.h @@ -19,6 +19,7 @@ #include "menuScan.h" #include "shareLib.h" +#include "compilerDependencies.h" #ifdef __cplusplus extern "C" { @@ -36,6 +37,7 @@ extern "C" { struct io_scan_list; typedef struct io_scan_list *IOSCANPVT; +typedef struct event_list *EVENTPVT; struct dbCommon; @@ -43,7 +45,9 @@ epicsShareFunc long scanInit(void); epicsShareFunc void scanRun(void); epicsShareFunc void scanPause(void); -epicsShareFunc void post_event(int event); +epicsShareFunc EVENTPVT eventNameToHandle(char* event); +epicsShareFunc void postEvent(EVENTPVT epvt); +epicsShareFunc void post_event(int event) EPICS_DEPRECATED; epicsShareFunc void scanAdd(struct dbCommon *); epicsShareFunc void scanDelete(struct dbCommon *); epicsShareFunc double scanPeriod(int scan); @@ -54,7 +58,7 @@ epicsShareFunc int scanOnceSetQueueSize(int size); epicsShareFunc int scanppl(double rate); /*print event lists*/ -epicsShareFunc int scanpel(int event_number); +epicsShareFunc int scanpel(char *event_name); /*print io_event list*/ epicsShareFunc int scanpiol(void); diff --git a/src/dev/softDev/devEventSoft.c b/src/dev/softDev/devEventSoft.c index e276e0b82..d7a61172a 100644 --- a/src/dev/softDev/devEventSoft.c +++ b/src/dev/softDev/devEventSoft.c @@ -51,7 +51,7 @@ static long init_record(eventRecord *prec) /* INP must be CONSTANT, PV_LINK, DB_LINK or CA_LINK*/ switch (prec->inp.type) { case CONSTANT: - if (recGblInitConstantLink(&prec->inp, DBF_USHORT, &prec->val)) + if (recGblInitConstantLink(&prec->inp, DBF_STRING, &prec->val)) prec->udf = FALSE; break; case PV_LINK: @@ -69,13 +69,20 @@ static long init_record(eventRecord *prec) static long read_event(eventRecord *prec) { long status; + char newEvent[MAX_STRING_SIZE]; - status = dbGetLink(&prec->inp, DBR_USHORT, &prec->val, 0, 0); - if (!status) { - prec->udf = FALSE; - if (prec->tsel.type == CONSTANT && - prec->tse == epicsTimeEventDeviceTime) - dbGetTimeStamp(&prec->inp, &prec->time); + if (prec->inp.type != CONSTANT) + { + status = dbGetLinkValue(&prec->inp, DBR_STRING, newEvent, 0, 0); + if (status) return status; + if (strcmp(newEvent, prec->val) != 0) { + strcpy(prec->val, newEvent); + prec->epvt = eventNameToHandle(prec->val); + } } - return status; + prec->udf = FALSE; + if (prec->tsel.type == CONSTANT && + prec->tse == epicsTimeEventDeviceTime) + dbGetTimeStamp(&prec->inp, &prec->time); + return 0; } diff --git a/src/rec/calcoutRecord.c b/src/rec/calcoutRecord.c index 062580c76..95b7c0d10 100644 --- a/src/rec/calcoutRecord.c +++ b/src/rec/calcoutRecord.c @@ -197,6 +197,8 @@ static long init_record(calcoutRecord *prec, int pass) callbackSetUser(prec, &prpvt->checkLinkCb); prpvt->cbScheduled = 0; + prec->epvt = eventNameToHandle(prec->oevt); + if (pcalcoutDSET->init_record) pcalcoutDSET->init_record(prec); prec->pval = prec->val; prec->mlst = prec->val; @@ -357,6 +359,9 @@ static long special(DBADDR *paddr, int after) } db_post_events(prec, plinkValid, DBE_VALUE); return 0; + case(calcoutRecordOEVT): + prec->epvt = eventNameToHandle(prec->oevt); + return 0; default: recGblDbaddrError(S_db_badChoice, paddr, "calc: special"); return(S_db_badChoice); @@ -540,27 +545,21 @@ static void execOutput(calcoutRecord *prec) if (prec->nsev < INVALID_ALARM ) { /* Output the value */ status = writeValue(prec); - /* post event if output event != 0 */ - if (prec->oevt > 0) { - post_event((int)prec->oevt); - } + /* post output event if set */ + if (prec->epvt) postEvent(prec->epvt); } else switch (prec->ivoa) { case menuIvoaContinue_normally: status = writeValue(prec); - /* post event if output event != 0 */ - if (prec->oevt > 0) { - post_event((int)prec->oevt); - } + /* post output event if set */ + if (prec->epvt) postEvent(prec->epvt); break; case menuIvoaDon_t_drive_outputs: break; case menuIvoaSet_output_to_IVOV: prec->oval = prec->ivov; status = writeValue(prec); - /* post event if output event != 0 */ - if (prec->oevt > 0) { - post_event((int)prec->oevt); - } + /* post output event if set */ + if (prec->epvt) postEvent(prec->epvt); break; default: status = -1; diff --git a/src/rec/calcoutRecord.dbd b/src/rec/calcoutRecord.dbd index fc393a782..8b80094d1 100644 --- a/src/rec/calcoutRecord.dbd +++ b/src/rec/calcoutRecord.dbd @@ -255,10 +255,19 @@ recordtype(calcout) { prompt("OCAL Valid") interest(1) } - field(OEVT,DBF_USHORT) { + field(OEVT,DBF_STRING) { prompt("Event To Issue") promptgroup(GUI_CLOCK) + special(SPC_MOD) asl(ASL0) + size(40) + } + %#include "dbScan.h" + field(EPVT, DBF_NOACCESS) { + prompt("Event private") + special(SPC_NOMOD) + interest(4) + extra("EVENTPVT epvt") } field(IVOA,DBF_MENU) { prompt("INVALID output action") diff --git a/src/rec/eventRecord.c b/src/rec/eventRecord.c index 01a71daa4..18b0fbcd9 100644 --- a/src/rec/eventRecord.c +++ b/src/rec/eventRecord.c @@ -32,6 +32,7 @@ #include "errMdef.h" #include "recSup.h" #include "recGbl.h" +#include "special.h" #include "menuYesNo.h" #define GEN_SIZE_OFFSET #include "eventRecord.h" @@ -43,7 +44,7 @@ #define initialize NULL static long init_record(eventRecord *, int); static long process(eventRecord *); -#define special NULL +static long special(DBADDR *, int); static long get_value(eventRecord *, struct valueDes *); #define cvt_dbaddr NULL #define get_array_info NULL @@ -103,9 +104,11 @@ static long init_record(eventRecord *prec, int pass) } if (prec->siol.type == CONSTANT) { - recGblInitConstantLink(&prec->siol,DBF_USHORT,&prec->sval); + recGblInitConstantLink(&prec->siol,DBF_STRING,&prec->sval); } + prec->epvt = eventNameToHandle(prec->val); + if( (pdset=(struct eventdset *)(prec->dset)) && (pdset->init_record) ) status=(*pdset->init_record)(prec); return(status); @@ -123,7 +126,7 @@ static long process(eventRecord *prec) if ( !pact && prec->pact ) return(0); prec->pact = TRUE; - if(prec->val>0) post_event((int)prec->val); + postEvent(prec->epvt); recGblGetTimeStamp(prec); @@ -137,10 +140,21 @@ static long process(eventRecord *prec) return(status); } + +static long special(DBADDR *paddr, int after) +{ + eventRecord *prec = (eventRecord *)paddr->precord; + + if (!after) return 0; + if (dbGetFieldIndex(paddr) == eventRecordVAL) { + prec->epvt = eventNameToHandle(prec->val); + } +} + static long get_value(eventRecord *prec, struct valueDes *pvdes) { - pvdes->field_type = DBF_USHORT; + pvdes->field_type = DBF_STRING; pvdes->no_elements=1; pvdes->pvalue = (void *)(&prec->val); return(0); @@ -177,10 +191,13 @@ static long readValue(eventRecord *prec) return(status); } if (prec->simm == menuYesNoYES){ - status=dbGetLink(&(prec->siol),DBR_USHORT, + status=dbGetLink(&(prec->siol),DBR_STRING, &(prec->sval),0,0); if (status==0) { - prec->val=prec->sval; + if (strcmp(prec->sval, prec->val) != 0) { + strcpy(prec->val, prec->sval); + prec->epvt = eventNameToHandle(prec->val); + } prec->udf=FALSE; } } else { diff --git a/src/rec/eventRecord.dbd b/src/rec/eventRecord.dbd index f63355900..f7bbb7ee7 100644 --- a/src/rec/eventRecord.dbd +++ b/src/rec/eventRecord.dbd @@ -9,10 +9,19 @@ #************************************************************************* recordtype(event) { include "dbCommon.dbd" - field(VAL,DBF_USHORT) { - prompt("Event Number To Post") + field(VAL,DBF_STRING) { + prompt("Event Name To Post") promptgroup(GUI_INPUTS) + special(SPC_MOD) asl(ASL0) + size(40) + } + %#include "dbScan.h" + field(EPVT, DBF_NOACCESS) { + prompt("Event private") + special(SPC_NOMOD) + interest(4) + extra("EVENTPVT epvt") } field(INP,DBF_INLINK) { prompt("Input Specification") @@ -24,8 +33,9 @@ recordtype(event) { promptgroup(GUI_INPUTS) interest(1) } - field(SVAL,DBF_USHORT) { + field(SVAL,DBF_STRING) { prompt("Simulation Value") + size(40) } field(SIML,DBF_INLINK) { prompt("Sim Mode Location")