From f6025d2a1f63f31d6cbe7c9fef76c39eebc1fda5 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Thu, 30 Mar 1995 19:04:34 +0000 Subject: [PATCH] Fixed bugs in dnNotify code. Move code to dbNotify.c from dbLink and dbAccess --- src/db/Makefile.Vx | 10 +- src/db/dbAccess.c | 52 +--------- src/db/dbLink.c | 138 --------------------------- src/db/dbNotify.c | 229 +++++++++++++++++++++++++++++++++++++++++++++ src/db/recGbl.c | 1 - 5 files changed, 238 insertions(+), 192 deletions(-) create mode 100644 src/db/dbNotify.c diff --git a/src/db/Makefile.Vx b/src/db/Makefile.Vx index fdbcb62e5..305926b35 100644 --- a/src/db/Makefile.Vx +++ b/src/db/Makefile.Vx @@ -4,16 +4,16 @@ include $(EPICS)/config/CONFIG_BASE SRCS.c = \ ../dbAccess.c ../dbBkpt.c ../dbFastLinkConv.c ../dbLink.c \ - ../dbStaticLib.c ../iocInit.c ../drvTS.c ../dbScan.c \ + ../dbNotify.c ../dbStaticLib.c ../iocInit.c ../drvTS.c ../dbScan.c \ ../dbEvent.c ../dbTest.c ../dbls.c ../db_access.c \ ../db_test.c ../recGbl.c ../callback.c ../taskwd.c \ ../dbCaLink.c ../dbCaDblink.c ../devLib.c ../initHooks.c OBJSdbLib = \ - dbAccess.o dbBkpt.o dbFastLinkConv.o dbLink.o dbStaticLib.o \ - iocInit.o drvTS.o dbScan.o dbEvent.o dbTest.o dbls.o db_access.o \ - db_test.o recGbl.o callback.o taskwd.o dbCaLink.o dbCaDblink.o \ - devLib.o + dbAccess.o dbBkpt.o dbFastLinkConv.o dbLink.o dbNotify.o \ + dbStaticLib.o iocInit.o drvTS.o dbScan.o dbEvent.o dbTest.o dbls.o \ + db_access.o db_test.o recGbl.o callback.o taskwd.o dbCaLink.o \ + dbCaDblink.o devLib.o PROD = initHooks.o dbLib diff --git a/src/db/dbAccess.c b/src/db/dbAccess.c index 3fd1b86e7..cd61e2e23 100644 --- a/src/db/dbAccess.c +++ b/src/db/dbAccess.c @@ -261,64 +261,20 @@ long dbScanPassive(struct dbCommon *pfrom, struct dbCommon *pto) long status; /* if not passive just return success */ - if (pto->scan != 0) return(0); + if(pto->scan != 0) return(0); - if (pfrom && pfrom->ppn) { - PUTNOTIFY *ppn = pfrom->ppn; - - if (pto->ppn) { /*already being used. Abandon request*/ - ppn->status = S_db_Blocked; - dbNotifyCompletion(ppn); - } else { - ppn->nwaiting++; - pto->ppn = pfrom->ppn; - /*If already active must redo*/ - if(pto->pact) ppn->rescan = TRUE; - } - } + if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto); status = dbProcess(pto); - if (pfrom && pfrom->ppn) { - PUTNOTIFY *ppn = pfrom->ppn; - - if (!pto->pact) { - pto->ppn = NULL; - } else { /*add to list of records for which to wait*/ - pto->ppnn = ppn->list; - ppn->list = pto; - } - } return(status); } - + /*KLUDGE: Following needed so that dbPutLink to PROC field works correctly*/ long dbScanLink(struct dbCommon *pfrom, struct dbCommon *pto) { long status; - if(pfrom && pfrom->ppn) { - PUTNOTIFY *ppn = pfrom->ppn; - - if(pto->ppn) { /*already being used. Abandon request*/ - ppn->status = S_db_Blocked; - dbNotifyCompletion(ppn); - } else { - ppn->nwaiting++; - pto->ppn = pfrom->ppn; - /*If already active must redo*/ - if(pto->pact) ppn->rescan = TRUE; - } - } + if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto); status = dbProcess(pto); - if(pfrom && pfrom->ppn) { - PUTNOTIFY *ppn = pfrom->ppn; - - if(!pto->pact) { - pto->ppn = NULL; - } else { /*add to list of records for which to wait*/ - pto->ppnn = ppn->list; - ppn->list = pto; - } - } return(status); } diff --git a/src/db/dbLink.c b/src/db/dbLink.c index f59d609a5..3d808c56b 100644 --- a/src/db/dbLink.c +++ b/src/db/dbLink.c @@ -198,144 +198,6 @@ long dbPutField( return(status); } -static void notifyCallback(CALLBACK *pcallback) -{ - PUTNOTIFY *ppn=NULL; - long status; - - callbackGetUser(ppn,pcallback); - if(ppn->cmd==notifyCmdRepeat) { - status = dbPutNotify(ppn); - } else if(ppn->cmd==notifyCmdCallUser) { - (ppn->userCallback)(ppn); - } else {/*illegal request*/ - recGblRecordError(-1,ppn->paddr->precord,"dbNotifyCompletion: illegal callback request"); - } -} - -static void notifyCancel(PUTNOTIFY *ppn) -{ - struct dbCommon *precord = ppn->list; - - while(precord) { - void *pnext; - - if(precord->rpro) { - precord->rpro = FALSE; - scanOnce(precord); - } - precord->ppn = NULL; - pnext = precord->ppnn; - precord->ppnn = NULL; - precord = pnext; - } - ppn->list = NULL; -} - -void dbNotifyCancel(PUTNOTIFY *ppn) -{ - struct dbCommon *precord = ppn->list; - - dbScanLock(precord); - notifyCancel(ppn); - dbScanUnlock(precord); -} - -long dbPutNotify(PUTNOTIFY *ppn) -{ - struct dbAddr *paddr = ppn->paddr; - short dbrType = ppn->dbrType; - void *pbuffer = ppn->pbuffer; - long nRequest = ppn->nRequest; - long status=0; - struct fldDes *pfldDes=(struct fldDes *)(paddr->pfldDes); - struct dbCommon *precord = (struct dbCommon *)(paddr->precord); - - callbackSetCallback(notifyCallback,&ppn->callback); - callbackSetUser(ppn,&ppn->callback); - callbackSetPriority(priorityLow,&ppn->callback); - /*check for putField disabled*/ - if(precord->disp) { - if((void *)(&precord->disp) != paddr->pfield) { - ppn->cmd = notifyCmdCallUser; - ppn->status = S_db_putDisabled; - notifyCallback(&ppn->callback); - return(S_db_putDisabled); - } - } - dbScanLock(precord); - status=dbPut(paddr,dbrType,pbuffer,nRequest); - ppn->status = status; - if(status==0){ - if((paddr->pfield==(void *)&precord->proc) - ||(pfldDes->process_passive && precord->scan==0)) { - if(precord->ppn) { - /*record already has attached ppn. Blocked*/ - - ppn->status = status = S_db_Blocked; - return(status); - } - ppn->nwaiting = 1; - ppn->rescan = FALSE; - ppn->list = NULL; - precord->ppn = ppn; - precord->ppnn = NULL; - if(precord->pact) {/*blocked wait for dbNotifyCompletion*/ - ppn->rescan = TRUE; - ppn->status = status = S_db_Pending; - return(status); - } - status=dbProcess(precord); - if(status==0) { - if(!precord->pact) { - precord->ppn = NULL; - } else { - precord->ppnn = ppn->list; - ppn->list = precord; - } - ppn->status = status = ((ppn->nwaiting == 0) ? 0 : S_db_Pending); - } else { - ppn->status = status; - notifyCancel(ppn); - } - } else { /*Make callback immediately*/ - ppn->cmd = notifyCmdCallUser; - ppn->status = 0; - notifyCallback(&ppn->callback); - } - } - dbScanUnlock(precord); - return(status); -} - -void dbNotifyCompletion(PUTNOTIFY *ppn) -{ - - if(ppn->status!=0 && ppn->status!=S_db_Pending) { - ppn->cmd = notifyCmdCallUser; - notifyCancel(ppn); - callbackRequest(&ppn->callback); - return; - } - /*decrement number of records being waited on*/ - if(ppn->nwaiting<=0) { - recGblRecordError(-1,ppn->paddr->precord,"dbNotifyCompletion: nwaiting<-0 LOGIC"); - return; - } - if(--ppn->nwaiting == 0) {/*original request completed*/ - notifyCancel(ppn); - if(ppn->rescan) { - ppn->cmd = notifyCmdRepeat; - callbackRequest(&ppn->callback); - } else { - /*issue completion callback*/ - ppn->cmd = notifyCmdCallUser; - if(ppn->status==S_db_Pending) ppn->status = 0; - callbackRequest(&ppn->callback); - } - } -} - long dbValueSize( short dbr_type ) diff --git a/src/db/dbNotify.c b/src/db/dbNotify.c new file mode 100644 index 000000000..c2dab8cd0 --- /dev/null +++ b/src/db/dbNotify.c @@ -0,0 +1,229 @@ +/* dbNotify.c */ +/* base/src/db $Id$ */ +/* + * Author: Marty Kraimer + * Date: 03-30-95 + * Extracted from dbLink.c + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * Modification Log: + * ----------------- + * .01 03-30-95 mrk Extracted from dbLink.c + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static void notifyCallback(CALLBACK *pcallback) +{ + PUTNOTIFY *ppn=NULL; + long status; + + callbackGetUser(ppn,pcallback); + if(ppn->cmd==notifyCmdRepeat) { + status = dbPutNotify(ppn); + } else if(ppn->cmd==notifyCmdCallUser) { + ppn->cmd = notifyUserCalled; + (ppn->userCallback)(ppn); + } else {/*illegal request*/ + recGblRecordError(-1,ppn->paddr->precord, + "dbNotifyCompletion: illegal callback request"); + } +} + +static void notifyCancel(PUTNOTIFY *ppn) +{ + struct dbCommon *precord = ppn->list; + + while(precord) { + void *pnext; + + if(precord->rpro) { + precord->rpro = FALSE; + scanOnce(precord); + } + precord->ppn = NULL; + pnext = precord->ppnn; + precord->ppnn = NULL; + precord = pnext; + } + ppn->list = NULL; +} + +void dbNotifyCancel(PUTNOTIFY *ppn) +{ + struct dbCommon *precord = ppn->list; + + if(!precord) return; + dbScanLock(precord); + notifyCancel(ppn); + if(ppn->cmd!=notifyCmdNull && ppn->cmd!=notifyUserCalled) { + /*Bad lets try one time to wait*/ + dbScanUnlock(precord); + taskDelay(10); + dbScanLock(precord); + } + if(ppn->cmd!=notifyCmdNull && ppn->cmd!=notifyUserCalled) { + epicsPrintf("dbNotifyCancel called while callback requested" + " but not called\n"); + } + dbScanUnlock(precord); +} + +static void issueCallback(PUTNOTIFY *ppn, notifyCmd cmd) +{ + if(ppn->cmd!=notifyCmdNull) return; + ppn->cmd = cmd; + notifyCancel(ppn); + callbackRequest(&ppn->callback); +} + +long dbPutNotify(PUTNOTIFY *ppn) +{ + struct dbAddr *paddr = ppn->paddr; + short dbrType = ppn->dbrType; + void *pbuffer = ppn->pbuffer; + long nRequest = ppn->nRequest; + long status=0; + struct fldDes *pfldDes=(struct fldDes *)(paddr->pfldDes); + struct dbCommon *precord = (struct dbCommon *)(paddr->precord); + + callbackSetCallback(notifyCallback,&ppn->callback); + callbackSetUser(ppn,&ppn->callback); + callbackSetPriority(priorityLow,&ppn->callback); + /*check for putField disabled*/ + if(precord->disp) { + if((void *)(&precord->disp) != paddr->pfield) { + ppn->status = S_db_putDisabled; + issueCallback(ppn,notifyCmdCallUser); + return(S_db_putDisabled); + } + } + ppn->status = 0; + ppn->cmd = notifyCmdNull; + ppn->nwaiting = 1; + ppn->rescan = FALSE; + dbScanLock(precord); + status=dbPut(paddr,dbrType,pbuffer,nRequest); + ppn->status = status; + if(status==0){ + if((paddr->pfield==(void *)&precord->proc) + ||(pfldDes->process_passive && precord->scan==0)) { + if(precord->ppn) { + /*record already has attached ppn. Blocked*/ + + ppn->status = status = S_db_Blocked; + dbScanUnlock(precord); + return(status); + } + precord->ppn = ppn; + precord->ppnn = NULL; + ppn->list = precord; + if(precord->pact) {/*blocked wait for dbNotifyCompletion*/ + ppn->rescan = TRUE; + dbScanUnlock(precord); + return(S_db_Pending); + } + status=dbProcess(precord); + if(status!=0) { + ppn->status = status; + issueCallback(ppn,notifyCmdCallUser); + } + } else { /*Make callback immediately*/ + issueCallback(ppn,notifyCmdCallUser); + } + } + dbScanUnlock(precord); + return(S_db_Pending); +} + +void dbNotifyCompletion(PUTNOTIFY *ppn) +{ + + if(ppn->status!=0) { + issueCallback(ppn,notifyCmdCallUser); + return; + } + /*decrement number of records being waited on*/ + if(ppn->nwaiting<=0) { + recGblRecordError(-1,ppn->paddr->precord,"dbNotifyCompletion: nwaiting<-0 LOGIC"); + return; + } + if(--ppn->nwaiting == 0) {/*original request completed*/ + if(ppn->rescan) { + issueCallback(ppn,notifyCmdRepeat); + } else { + issueCallback(ppn,notifyCmdCallUser); + } + } +} + +/*Remove all nonactive records from put notify list*/ +void cleanPpList(PUTNOTIFY *ppn) +{ + struct dbCommon *precord = ppn->list; + struct dbCommon *pnext; + struct dbCommon *pprev=NULL; + + while(precord) { + pnext = precord->ppnn; + if(!precord->pact) { + if(!pprev) ppn->list = pnext; else pprev->ppnn = pnext; + precord->ppn = NULL; + precord->ppnn = NULL; + } else { + pprev = precord; + } + precord = pnext; + } +} + +void dbNotifyAdd(struct dbCommon *pfrom, struct dbCommon *pto) +{ + PUTNOTIFY *ppn = pfrom->ppn; + + if(pto->ppn) cleanPpList(pto->ppn); /* clean list before giving up*/ + if (pto->ppn) { /*already being used. Abandon request*/ + ppn->status = S_db_Blocked; + dbNotifyCompletion(ppn); + } else { + ppn->nwaiting++; + pto->ppn = pfrom->ppn; + pto->ppnn = ppn->list; + ppn->list = pto; + /*If already active must redo*/ + if(pto->pact) ppn->rescan = TRUE; + } +} diff --git a/src/db/recGbl.c b/src/db/recGbl.c index cae0f837e..97bcb12fe 100644 --- a/src/db/recGbl.c +++ b/src/db/recGbl.c @@ -109,7 +109,6 @@ void recGblRecordError(long status,void *pdbc,char *pcaller_name) strcat(buffer," "); } if(pcaller_name) { - strcat(buffer,"error detected in routine: "); strcat(buffer,pcaller_name); } errMessage(status,buffer);