Merged dbCa bug-fix from 3.14 branch, revno 12595

This commit is contained in:
Andrew Johnson
2015-07-23 18:02:54 -05:00
2 changed files with 15 additions and 22 deletions
+15 -21
View File
@@ -100,7 +100,7 @@ static int dbca_chan_count;
* that has been deleted.
*
* Just a few words about handling dbCaRemoveLink because this is when
* it is essential that nothing trys to use a caLink that has been freed.
* it is essential that nothing tries to use a caLink that has been freed.
*
* dbCaRemoveLink is called when links are being modified. This is only
* done with the dbScan mechanism guranteeing that nothing from
@@ -119,19 +119,16 @@ static int dbca_chan_count;
* dbCaTask issues a ca_clear_channel and then frees the caLink.
*
* If any channel access callback gets called before the ca_clear_channel
* it finds pca->plink=0 and does nothing. Once ca_clear_channel
* it finds pca->plink==0 and does nothing. Once ca_clear_channel
* is called no other callback for this caLink will be called.
*
* dbCaPutLinkCallback causes an additional complication because
* when dbCaRemoveLink is called the callback may not have occured.
* What is done is the following:
* If callback has not occured dbCaRemoveLink sets plinkPutCallback=plink
* If putCallback is called before dbCaTask calls ca_clear_channel
* it does NOT call the users callback.
* dbCaTask calls the users callback passing plinkPutCallback AFTER
* it has called ca_clear_channel
* Thus the users callback will get called exactly once.
*/
* If putComplete sees plink==0 it will not call the user's code.
* If pca->putCallback is non-zero, dbCaTask will call the
* user's callback AFTER it has called ca_clear_channel.
* Thus the user's callback will get called exactly once.
*/
static void addAction(caLink *pca, short link_action)
{
@@ -168,7 +165,7 @@ static void addAction(caLink *pca, short link_action)
static void dbCaLinkFree(caLink *pca)
{
dbCaCallback callback;
struct link *plinkPutCallback = 0;
void *userPvt = 0;
if (pca->chid) {
ca_clear_channel(pca->chid);
@@ -176,8 +173,7 @@ static void dbCaLinkFree(caLink *pca)
}
callback = pca->putCallback;
if (callback) {
plinkPutCallback = pca->plinkPutCallback;
pca->plinkPutCallback = 0;
userPvt = pca->putUserPvt;
pca->putCallback = 0;
pca->putType = 0;
}
@@ -188,12 +184,12 @@ static void dbCaLinkFree(caLink *pca)
free(pca->pvname);
epicsMutexDestroy(pca->lock);
free(pca);
if (callback) callback(plinkPutCallback);
if (callback) callback(userPvt);
}
void dbCaCallbackProcess(void *usrPvt)
void dbCaCallbackProcess(void *userPvt)
{
struct link *plink = (struct link *)usrPvt;
struct link *plink = (struct link *)userPvt;
dbCommon *pdbCommon = plink->value.pv_link.precord;
dbScanLock(pdbCommon);
@@ -291,8 +287,6 @@ void dbCaRemoveLink(struct link *plink)
epicsMutexMustLock(pca->lock);
pca->plink = 0;
plink->value.pv_link.pvt = 0;
if (pca->putCallback)
pca->plinkPutCallback = plink;
/* Unlock before addAction or dbCaTask might free first */
epicsMutexUnlock(pca->lock);
addAction(pca, CA_CLEAR_CHANNEL);
@@ -794,7 +788,7 @@ static void exceptionCallback(struct exception_handler_args args)
}
}
static void putCallback(struct event_handler_args arg)
static void putComplete(struct event_handler_args arg)
{
caLink *pca = (caLink *)arg.usr;
struct link *plink;
@@ -957,7 +951,7 @@ static void dbCaTask(void *arg)
status = ca_array_put_callback(
pca->dbrType, pca->nelements,
pca->chid, pca->pputNative,
putCallback, pca);
putComplete, pca);
} else {
status = ECA_PUTFAIL;
}
@@ -980,7 +974,7 @@ static void dbCaTask(void *arg)
status = ca_array_put_callback(
DBR_STRING, 1,
pca->chid, pca->pputString,
putCallback, pca);
putComplete, pca);
} else {
status = ECA_PUTFAIL;
}
-1
View File
@@ -63,7 +63,6 @@ typedef struct caLink
short putType;
dbCaCallback putCallback;
void *putUserPvt;
struct link *plinkPutCallback;
/* The following are for access to additional attributes*/
char gotAttributes;
dbCaCallback getAttributes;