diff --git a/src/db/dbConvert.c b/src/db/dbConvert.c index 1e6f0a497..4e4849a65 100644 --- a/src/db/dbConvert.c +++ b/src/db/dbConvert.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include "dbDefs.h" #include "errlog.h" @@ -47,6 +49,19 @@ #include "recSup.h" #include "recGbl.h" +/*safe double to float conversion*/ +static void safeDoubleToFloat(double *pd,float *pf) +{ + double abs = fabs(*pd); + if(abs>=FLT_MAX) { + if(*pd>0.0) *pf = FLT_MAX; else *pf = -FLT_MAX; + } else if(abs<=FLT_MIN) { + if(*pd>0.0) *pf = FLT_MIN; else *pf = -FLT_MIN; + } else { + *pf = *pd; + } +} + /* DATABASE ACCESS GET CONVERSION SUPPORT */ static long getStringString ( @@ -1896,12 +1911,13 @@ static long getDoubleFloat( double *psrc=(double *)(paddr->pfield); if(nRequest==1 && offset==0) { - *pbuffer = *psrc; + safeDoubleToFloat(psrc,pbuffer); return(0); } psrc += offset; while (nRequest) { - *pbuffer++ = *psrc++; + safeDoubleToFloat(psrc,pbuffer); + ++psrc; ++pbuffer; if(++offset==no_elements) psrc=(double *)paddr->pfield; nRequest--; } @@ -4105,12 +4121,13 @@ static long putDoubleFloat( float *pdest=(float *)(paddr->pfield); if(nRequest==1 && offset==0) { - *pdest = *pbuffer; + safeDoubleToFloat(pbuffer,pdest); return(0); } pdest += offset; while (nRequest) { - *pdest++ = *pbuffer++; + safeDoubleToFloat(pbuffer,pdest); + ++pbuffer; ++pdest; if(++offset==no_elements) pdest=(float *)paddr->pfield; nRequest--; } diff --git a/src/db/dbFastLinkConv.c b/src/db/dbFastLinkConv.c index e9ee8b112..efeea1f61 100644 --- a/src/db/dbFastLinkConv.c +++ b/src/db/dbFastLinkConv.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include "dbDefs.h" #include "errlog.h" @@ -937,7 +939,17 @@ static long cvt_d_f( double *from, float *to, struct dbAddr *paddr) - { *to=*from; return(0); } +{ + double abs = fabs(*from); + if(abs>=FLT_MAX) { + if(*from>0.0) *to = FLT_MAX; else *to = -FLT_MAX; + } else if(abs<=FLT_MIN) { + if(*from>0.0) *to = FLT_MIN; else *to = -FLT_MIN; + } else { + *to = *from; + } + return(0); +} /* Convert Double to Double */ static long cvt_d_d( diff --git a/src/db/dbNotify.c b/src/db/dbNotify.c index 4687b92ce..c98b26d47 100644 --- a/src/db/dbNotify.c +++ b/src/db/dbNotify.c @@ -220,10 +220,11 @@ static void notifyCallback(CALLBACK *pcallback) precord = ppn->paddr->precord; dbScanLock(precord); if(ppn->callbackState==callbackCanceled) { - dbScanUnlock(precord); ppn->restart = FALSE; ppn->callbackState = callbackNotActive; - semGive((SEM_ID)ppn->waitForCallback); + if(ppn->waitForCallback) + semGive((SEM_ID)ppn->waitForCallback); + dbScanUnlock(precord); return; } if(ppn->callbackState==callbackActive) { @@ -234,6 +235,8 @@ static void notifyCallback(CALLBACK *pcallback) dbScanUnlock(precord); (ppn->userCallback)(ppn); } + } else { + dbScanUnlock(precord); } } @@ -251,14 +254,17 @@ void dbNotifyCancel(PUTNOTIFY *ppn) dbScanLock(precord); notifyCancel(ppn); if(ppn->callbackState == callbackActive) { - ppn->waitForCallback = (void *)semBCreate(SEM_Q_FIFO,SEM_FULL); + ppn->waitForCallback = (void *)semBCreate(SEM_Q_FIFO,SEM_EMPTY); ppn->callbackState = callbackCanceled; dbScanUnlock(precord); if(semTake((SEM_ID)ppn->waitForCallback,sysClkRateGet()*10)!=OK) { errMessage(0,"dbNotifyCancel had semTake timeout"); ppn->callbackState = callbackNotActive; } + dbScanLock(precord); semDelete((SEM_ID)ppn->waitForCallback); + ppn->waitForCallback = 0; + dbScanUnlock(precord); } else { dbScanUnlock(precord); } diff --git a/src/db/db_access.c b/src/db/db_access.c index 42b1733b3..692e202d7 100644 --- a/src/db/db_access.c +++ b/src/db/db_access.c @@ -52,6 +52,8 @@ #include #include #include +#include +#include #include "dbDefs.h" #include "errlog.h" @@ -60,7 +62,6 @@ #include "dbCommon.h" #include "errMdef.h" #include "recSup.h" - #include "alarm.h" extern struct dbBase *pdbbase; @@ -483,9 +484,18 @@ struct dbr_ctrl_double{ double value; /* current value */ }; - - - +/*safe double to float conversion*/ +static void safeDoubleToFloat(double *pd,float *pf) +{ + double abs = fabs(*pd); + if(abs>=FLT_MAX) { + if(*pd>0.0) *pf = FLT_MAX; else *pf = -FLT_MAX; + } else if(abs<=FLT_MIN) { + if(*pd>0.0) *pf = FLT_MIN; else *pf = -FLT_MIN; + } else { + *pf = *pd; + } +} /* From $cs/dblib/src/dbiocsubs.c * subroutines @@ -1059,12 +1069,12 @@ void *pfl pold->precision = new.precision; strncpy(pold->units,new.units,MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; - pold->upper_disp_limit = new.upper_disp_limit; - pold->lower_disp_limit = new.lower_disp_limit; - pold->upper_alarm_limit = new.upper_alarm_limit; - pold->upper_warning_limit = new.upper_warning_limit; - pold->lower_warning_limit = new.lower_warning_limit; - pold->lower_alarm_limit = new.lower_alarm_limit; + safeDoubleToFloat(&new.upper_disp_limit,&pold->upper_disp_limit); + safeDoubleToFloat(&new.lower_disp_limit,&pold->lower_disp_limit); + safeDoubleToFloat(&new.upper_alarm_limit,&pold->upper_alarm_limit); + safeDoubleToFloat(&new.upper_warning_limit,&pold->upper_warning_limit); + safeDoubleToFloat(&new.lower_warning_limit,&pold->lower_warning_limit); + safeDoubleToFloat(&new.lower_alarm_limit,&pold->lower_alarm_limit); options=0; nRequest=no_elements; status = dbGetField(paddr,DBR_FLOAT,&(pold->value),&options, @@ -1232,14 +1242,14 @@ void *pfl pold->precision = new.precision; strncpy(pold->units,new.units,MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; - pold->upper_disp_limit = new.upper_disp_limit; - pold->lower_disp_limit = new.lower_disp_limit; - pold->upper_alarm_limit = new.upper_alarm_limit; - pold->upper_warning_limit = new.upper_warning_limit; - pold->lower_warning_limit = new.lower_warning_limit; - pold->lower_alarm_limit = new.lower_alarm_limit; - pold->upper_ctrl_limit = new.upper_ctrl_limit; - pold->lower_ctrl_limit = new.lower_ctrl_limit; + safeDoubleToFloat(&new.upper_disp_limit,&pold->upper_disp_limit); + safeDoubleToFloat(&new.lower_disp_limit,&pold->lower_disp_limit); + safeDoubleToFloat(&new.upper_alarm_limit,&pold->upper_alarm_limit); + safeDoubleToFloat(&new.upper_warning_limit,&pold->upper_warning_limit); + safeDoubleToFloat(&new.lower_warning_limit,&pold->lower_warning_limit); + safeDoubleToFloat(&new.lower_alarm_limit,&pold->lower_alarm_limit); + safeDoubleToFloat(&new.upper_ctrl_limit,&pold->upper_ctrl_limit); + safeDoubleToFloat(&new.lower_ctrl_limit,&pold->lower_ctrl_limit); options=0; nRequest=no_elements; status = dbGetField(paddr,DBR_FLOAT,&(pold->value),&options, diff --git a/src/db/iocInit.c b/src/db/iocInit.c index e0ee80483..f61be4f65 100644 --- a/src/db/iocInit.c +++ b/src/db/iocInit.c @@ -227,6 +227,7 @@ int iocInit(char * pResourceFilename) * Process all records that have their "process at initialization" * field set (pini). */ + taskDelay(sysClkRateGet()); if (initialProcess() != 0) epicsPrintf("iocInit: initialProcess Failed\n");