Beispiel #1
0
void dbNotifyCompletion(dbCommon *precord)
{
    processNotify *ppn = precord->ppn;
    notifyPvt *pnotifyPvt;

    epicsMutexMustLock(pnotifyGlobal->lock);
    assert(ppn);
    assert(precord->ppnr);
    pnotifyPvt = (notifyPvt *) ppn->pnotifyPvt;
    if (pnotifyPvt->state != notifyRestartInProgress &&
        pnotifyPvt->state != notifyProcessInProgress) {
        epicsMutexUnlock(pnotifyGlobal->lock);
        return;
    }
    ellSafeDelete(&pnotifyPvt->waitList, &precord->ppnr->waitNode);
    if ((ellCount(&pnotifyPvt->waitList) != 0)) {
        restartCheck(precord->ppnr);
    }
    else if (pnotifyPvt->state == notifyProcessInProgress) {
        pnotifyPvt->state = notifyUserCallbackRequested;
        restartCheck(precord->ppnr);
        callbackRequest(&pnotifyPvt->callback);
    }
    else if(pnotifyPvt->state == notifyRestartInProgress) {
        pnotifyPvt->state = notifyRestartCallbackRequested;
        callbackRequest(&pnotifyPvt->callback);
    } else {
        cantProceed("dbNotifyCompletion illegal state");
    }
    epicsMutexUnlock(pnotifyGlobal->lock);
}
Beispiel #2
0
void dbNotifyCancel(processNotify *ppn)
{
    dbCommon *precord = dbChannelRecord(ppn->chan);
    notifyState state;
    notifyPvt *pnotifyPvt;

    dbScanLock(precord);
    epicsMutexMustLock(pnotifyGlobal->lock);
    ppn->status = notifyCanceled;
    pnotifyPvt = (notifyPvt *) ppn->pnotifyPvt;
    if (!pnotifyPvt || pnotifyPvt->state == notifyNotActive) {
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    }

    state = pnotifyPvt->state;
    switch (state) {
    case notifyUserCallbackRequested:
    case notifyRestartCallbackRequested:
    case notifyUserCallbackActive:
        /* Callback is scheduled or active, wait for it to complete */
        pnotifyPvt->cancelWait = 1;
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        epicsEventWait(pnotifyPvt->cancelEvent);
        epicsMutexMustLock(pnotifyGlobal->lock);
        notifyCleanup(ppn);
        epicsMutexUnlock(pnotifyGlobal->lock);
        return;
    case notifyNotActive:
    	break;
    case notifyWaitForRestart:
        assert(precord->ppn);
        assert(precord->ppn!=ppn);
        ellSafeDelete(&precord->ppnr->restartList,&ppn->restartNode);
        break;
    case notifyRestartInProgress:
    case notifyProcessInProgress:
        { /*Take all records out of wait list */
            processNotifyRecord *ppnrWait;

            while ((ppnrWait = (processNotifyRecord *)
	                       ellFirst(&pnotifyPvt->waitList))) {
                ellSafeDelete(&pnotifyPvt->waitList, &ppnrWait->waitNode);
                restartCheck(ppnrWait);
            }
        }
        if (precord->ppn == ppn)
            restartCheck(precord->ppnr);
        break;
    default:
        printf("dbNotify: illegal state for notifyCallback\n");
    }
    pnotifyPvt->state = notifyNotActive;
    notifyCleanup(ppn);
    epicsMutexUnlock(pnotifyGlobal->lock);
    dbScanUnlock(precord);
}
Beispiel #3
0
void epicsShareAPI dbNotifyCancel(putNotify *ppn)
{
    dbCommon	*precord = ppn->paddr->precord;
    putNotifyState state;
    putNotifyPvt *pputNotifyPvt;

    assert(precord);
    dbScanLock(precord);
    epicsMutexMustLock(pnotifyGlobal->lock);
    pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt;
    if(!pputNotifyPvt || pputNotifyPvt->state==putNotifyNotActive) {
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    }
    state = pputNotifyPvt->state;
    /*If callback is scheduled or active wait for it to complete*/
    if(state==putNotifyUserCallbackRequested
    || state==putNotifyRestartCallbackRequested
    || state==putNotifyUserCallbackActive) {
        pputNotifyPvt->cancelWait = 1;
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        epicsEventWait(pputNotifyPvt->cancelEvent);
        epicsMutexMustLock(pnotifyGlobal->lock);
        putNotifyCleanup(ppn);
        epicsMutexUnlock(pnotifyGlobal->lock);
        return;
    }
    switch(state) {
    case putNotifyNotActive: break;
    case putNotifyWaitForRestart:
        assert(precord->ppn);
        assert(precord->ppn!=ppn);
        ellSafeDelete(&precord->ppnr->restartList,&ppn->restartNode);
        break;
    case putNotifyRestartInProgress:
    case putNotifyPutInProgress:
        { /*Take all records out of wait list */
            putNotifyRecord *ppnrWait;

            while((ppnrWait = (putNotifyRecord *)ellFirst(&pputNotifyPvt->waitList))){
                ellSafeDelete(&pputNotifyPvt->waitList,&ppnrWait->waitNode);
                restartCheck(ppnrWait);
            }
        }
        if(precord->ppn==ppn) restartCheck(precord->ppnr);
        break;
    default:
        printf("dbNotify: illegal state for notifyCallback\n");
    }
    pputNotifyPvt->state = putNotifyNotActive;
    putNotifyCleanup(ppn);
    epicsMutexUnlock(pnotifyGlobal->lock);
    dbScanUnlock(precord);
}
Beispiel #4
0
static void notifyCallback(CALLBACK *pcallback)
{
    processNotify *ppn = NULL;
    dbCommon  *precord;
    notifyPvt *pnotifyPvt;

    callbackGetUser(ppn,pcallback);
    pnotifyPvt = (notifyPvt *) ppn->pnotifyPvt;
    precord = dbChannelRecord(ppn->chan);
    dbScanLock(precord);
    epicsMutexMustLock(pnotifyGlobal->lock);
    assert(precord->ppnr);
    assert(pnotifyPvt->state == notifyRestartCallbackRequested ||
           pnotifyPvt->state == notifyUserCallbackRequested);
    assert(ellCount(&pnotifyPvt->waitList) == 0);
    if (pnotifyPvt->cancelWait) {
        if (pnotifyPvt->state == notifyRestartCallbackRequested) {
            restartCheck(precord->ppnr);
        }
        epicsEventSignal(pnotifyPvt->cancelEvent);
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    }
    if(pnotifyPvt->state == notifyRestartCallbackRequested) {
        processNotifyCommon(ppn, precord);
        return;
    }
    /* All done. Clean up and call userCallback */
    pnotifyPvt->state = notifyUserCallbackActive;
    assert(precord->ppn!=ppn);
    callDone(precord, ppn);
}
Beispiel #5
0
static void putNotifyCommon(putNotify *ppn,dbCommon *precord)
{
    long	status=0;
    dbFldDes	*pfldDes = ppn->paddr->pfldDes;
    putNotifyPvt *pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt;

    if(precord->ppn && pputNotifyPvt->state!=putNotifyRestartCallbackRequested)
    { /*another putNotify owns the record */
        pputNotifyPvt->state = putNotifyWaitForRestart; 
        ellSafeAdd(&precord->ppnr->restartList,&ppn->restartNode);
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    } else if(precord->ppn){
        assert(precord->ppn==ppn);
        assert(pputNotifyPvt->state==putNotifyRestartCallbackRequested);
    }
    if(precord->pact) {
        precord->ppn = ppn;
        ellSafeAdd(&pputNotifyPvt->waitList,&precord->ppnr->waitNode);
        pputNotifyPvt->state = putNotifyRestartInProgress; 
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    }
    status=dbPut(ppn->paddr,ppn->dbrType,ppn->pbuffer,ppn->nRequest);
    ppn->status = (status==0) ? putNotifyOK : putNotifyError;
    /* Check to see if dbProcess should not be called */
    if(!status /*dont process if dbPut returned error */
    &&((ppn->paddr->pfield==(void *)&precord->proc) /*If PROC call dbProcess*/
       || (pfldDes->process_passive && precord->scan==0))) {
        precord->ppn = ppn;
        ellSafeAdd(&pputNotifyPvt->waitList,&precord->ppnr->waitNode);
        pputNotifyPvt->state = putNotifyPutInProgress;
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbProcess(precord);
        dbScanUnlock(precord);
        return;
    }
    if(pputNotifyPvt->state==putNotifyRestartCallbackRequested) {
        restartCheck(precord->ppnr);
    }
    pputNotifyPvt->state = putNotifyUserCallbackActive;
    assert(precord->ppn!=ppn);
    callUser(precord,ppn);
}
Beispiel #6
0
static void processNotifyCommon(processNotify *ppn,dbCommon *precord)
{
    notifyPvt *pnotifyPvt = (notifyPvt *) ppn->pnotifyPvt;
    int didPut = 0;
    int doProcess = 0;

    if (precord->ppn &&
        pnotifyPvt->state != notifyRestartCallbackRequested) {
        /* Another processNotify owns the record */
        pnotifyPvt->state = notifyWaitForRestart; 
        ellSafeAdd(&precord->ppnr->restartList, &ppn->restartNode);
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    } else if (precord->ppn) {
        assert(precord->ppn == ppn);
        assert(pnotifyPvt->state == notifyRestartCallbackRequested);
    }
    if (precord->pact) {
        precord->ppn = ppn;
        ellSafeAdd(&pnotifyPvt->waitList, &precord->ppnr->waitNode);
        pnotifyPvt->state = notifyRestartInProgress; 
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    }
    if (ppn->requestType == putProcessRequest ||
        ppn->requestType == putProcessGetRequest) {
        /* Check if puts disabled */
        if (precord->disp && (dbChannelField(ppn->chan) != (void *) &precord->disp)) {
            ppn->putCallback(ppn, putDisabledType);
        } else {
            didPut = ppn->putCallback(ppn, putType);
        }
    }
    /* Check if dbProcess should be called */
    if (didPut &&
        ((dbChannelField(ppn->chan) == (void *) &precord->proc) ||
        (dbChannelFldDes(ppn->chan)->process_passive && precord->scan == 0)))
       doProcess = 1;
    else
        if (ppn->requestType == processGetRequest &&
            precord->scan == 0)
            doProcess = 1;

    if (doProcess) {
        ppn->wasProcessed = 1;
        precord->ppn = ppn;
        ellSafeAdd(&pnotifyPvt->waitList, &precord->ppnr->waitNode);
        pnotifyPvt->state = notifyProcessInProgress;
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbProcess(precord);
        dbScanUnlock(precord);
        return;
    }
    if (pnotifyPvt->state == notifyRestartCallbackRequested) {
        restartCheck(precord->ppnr);
    }
    pnotifyPvt->state = notifyUserCallbackActive;
    assert(precord->ppn!=ppn);
    callDone(precord, ppn);
}