From 5eafdfd398dbd4c012c927cd2177fbdfbf0db806 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Wed, 7 Mar 2001 16:03:56 +0000 Subject: [PATCH] many changes --- src/ca/access.cpp | 103 ++++++++++++------------- src/ca/cac.cpp | 193 ++++++++++++++++++---------------------------- 2 files changed, 126 insertions(+), 170 deletions(-) diff --git a/src/ca/access.cpp b/src/ca/access.cpp index 35bd77717..1b6e60832 100644 --- a/src/ca/access.cpp +++ b/src/ca/access.cpp @@ -30,8 +30,6 @@ epicsThreadPrivateId caClientContextId; -epicsThreadPrivateId cacRecursionLock; - static epicsThreadOnceId caClientContextIdOnce = EPICS_THREAD_ONCE_INIT; extern "C" void ca_client_exit_handler () @@ -56,8 +54,6 @@ extern "C" void ca_init_client_context ( void * ) */ int fetchClientContext ( cac **ppcac ) { - int status; - if ( caClientContextId == 0 ) { epicsThreadOnce ( &caClientContextIdOnce, ca_init_client_context, 0 ); if ( caClientContextId == 0 ) { @@ -65,6 +61,7 @@ int fetchClientContext ( cac **ppcac ) } } + int status; *ppcac = ( cac * ) epicsThreadPrivateGet ( caClientContextId ); if ( *ppcac ) { status = ECA_NORMAL; @@ -229,10 +226,8 @@ extern "C" int epicsShareAPI ca_search_and_connect ( const char *name_str, chid *chanptr, caCh *conn_func, void *puser ) { - int caStatus; cac *pcac; - - caStatus = fetchClientContext ( &pcac ); + int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; } @@ -267,7 +262,23 @@ extern "C" int epicsShareAPI ca_search_and_connect ( extern "C" int epicsShareAPI ca_array_get ( chtype type, unsigned long count, chid pChan, void *pValue ) { - return pChan->read ( type, count, pValue ); + cac *pcac; + int caStatus = fetchClientContext ( &pcac ); + if ( caStatus != ECA_NORMAL ) { + return caStatus; + } + + getCopy *pNotify = new getCopy ( *pcac, type, count, pValue ); + if ( ! pNotify ) { + return ECA_ALLOCMEM; + } + + int status = pChan->read ( type, count, *pNotify ); + if ( status != ECA_NORMAL ) { + pNotify->release (); + } + + return status; } /* @@ -352,9 +363,7 @@ extern "C" int epicsShareAPI ca_replace_access_rights_event ( chid pChan, caArh extern "C" int epicsShareAPI ca_add_exception_event ( caExceptionHandler *pfunc, void *arg ) { cac *pcac; - int caStatus; - - caStatus = fetchClientContext ( &pcac ); + int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; } @@ -425,23 +434,11 @@ extern "C" int epicsShareAPI ca_add_masked_array_event ( } /* - * * ca_clear_event () - * - * Cancel an outstanding event for a channel. - * - * NOTE: returns before operation completes in the server - * (and the client). - * This is a good reason not to allow them to make the monix - * block as part of a larger structure. - * Nevertheless the caller is gauranteed that his specified - * event is disabled and therefore will not run (from this source) - * after leaving this routine. - * */ extern "C" int epicsShareAPI ca_clear_event ( evid pMon ) { - pMon->destroy (); + pMon->cancel (); return ECA_NORMAL; } @@ -455,24 +452,36 @@ extern "C" chid epicsShareAPI ca_evid_to_chid ( evid pMon ) */ extern "C" int epicsShareAPI ca_clear_channel ( chid pChan ) { - pChan->destroy (); + delete pChan; return ECA_NORMAL; } /* - * ca_pend () + * ca_pend_event () */ -extern "C" int epicsShareAPI ca_pend (ca_real timeout, int early) +extern "C" int epicsShareAPI ca_pend_event (ca_real timeout) { cac *pcac; - int status; - - status = fetchClientContext ( &pcac ); + int status = fetchClientContext ( &pcac ); if ( status != ECA_NORMAL ) { return status; } - return pcac->pend ( timeout, early ); + return pcac->pendEvent ( timeout ); +} + +/* + * ca_pend_io () + */ +extern "C" int epicsShareAPI ca_pend_io (ca_real timeout) +{ + cac *pcac; + int status = fetchClientContext ( &pcac ); + if ( status != ECA_NORMAL ) { + return status; + } + + return pcac->pendIO ( timeout ); } /* @@ -480,10 +489,8 @@ extern "C" int epicsShareAPI ca_pend (ca_real timeout, int early) */ extern "C" int epicsShareAPI ca_flush_io () { - int caStatus; cac *pcac; - - caStatus = fetchClientContext (&pcac); + int caStatus = fetchClientContext (&pcac); if ( caStatus != ECA_NORMAL ) { return caStatus; } @@ -498,10 +505,8 @@ extern "C" int epicsShareAPI ca_flush_io () */ extern "C" int epicsShareAPI ca_test_io () { - int caStatus; cac *pcac; - - caStatus = fetchClientContext ( &pcac ); + int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; } @@ -622,9 +627,7 @@ extern "C" void epicsShareAPI ca_signal_formated ( long ca_status, const char *p extern "C" int epicsShareAPI ca_add_fd_registration (CAFDHANDLER *func, void *arg) { cac *pcac; - int caStatus; - - caStatus = fetchClientContext ( &pcac ); + int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; } @@ -672,10 +675,8 @@ extern "C" const char * epicsShareAPI ca_version() */ extern "C" int epicsShareAPI ca_replace_printf_handler (caPrintfFunc *ca_printf_func) { - cac *pcac; - int caStatus; - - caStatus = fetchClientContext (&pcac); + cac *pcac; + int caStatus = fetchClientContext (&pcac); if ( caStatus != ECA_NORMAL ) { return caStatus; } @@ -769,8 +770,7 @@ extern "C" epicsShareFunc void * epicsShareAPI ca_puser (chid pChan) */ extern "C" epicsShareFunc unsigned epicsShareAPI ca_read_access (chid pChan) { - caar ar = pChan->accessRights (); - if ( ar.read_access ) { + if ( pChan->accessRights ().read_access ) { return true; } else { @@ -783,8 +783,7 @@ extern "C" epicsShareFunc unsigned epicsShareAPI ca_read_access (chid pChan) */ extern "C" epicsShareFunc unsigned epicsShareAPI ca_write_access (chid pChan) { - caar ar = pChan->accessRights (); - if ( ar.write_access ) { + if ( pChan->accessRights ().write_access ) { return true; } else { @@ -819,9 +818,7 @@ extern "C" epicsShareFunc double epicsShareAPI ca_beacon_period ( chid pChan ) extern "C" unsigned epicsShareAPI ca_get_ioc_connection_count () { cac *pcac; - int caStatus; - - caStatus = fetchClientContext (&pcac); + int caStatus = fetchClientContext (&pcac); if ( caStatus != ECA_NORMAL ) { return caStatus; } @@ -839,9 +836,7 @@ extern "C" epicsShareFunc int epicsShareAPI ca_channel_status ( epicsThreadId /* extern "C" epicsShareFunc int epicsShareAPI ca_client_status ( unsigned level ) { cac *pcac; - int caStatus; - - caStatus = fetchClientContext ( &pcac ); + int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; } diff --git a/src/ca/cac.cpp b/src/ca/cac.cpp index bcbf98437..b7beafcee 100644 --- a/src/ca/cac.cpp +++ b/src/ca/cac.cpp @@ -19,25 +19,9 @@ #include "bhe_IL.h" #include "tcpiiu_IL.h" #include "nciu_IL.h" -#include "ioCounter_IL.h" #include "comQueSend_IL.h" #include "recvProcessThread_IL.h" - -extern "C" void cacRecursionLockExitHandler () -{ - if ( cacRecursionLock ) { - epicsThreadPrivateDelete ( cacRecursionLock ); - cacRecursionLock = 0; - } -} - -extern "C" void cacInitRecursionLock ( void * ) -{ - cacRecursionLock = epicsThreadPrivateCreate (); - if ( cacRecursionLock ) { - atexit ( cacRecursionLockExitHandler ); - } -} +#include "netiiu_IL.h" // // cac::cac () @@ -59,12 +43,6 @@ cac::cac ( bool enablePreemptiveCallbackIn ) : static epicsThreadOnceId once = EPICS_THREAD_ONCE_INIT; unsigned abovePriority; - epicsThreadOnce ( &once, cacInitRecursionLock, 0 ); - - if ( cacRecursionLock == 0 ) { - throwWithLocation ( caErrorCode (ECA_ALLOCMEM) ); - } - if ( ! osiSockAttach () ) { throwWithLocation ( caErrorCode (ECA_INTERNAL) ); } @@ -312,7 +290,7 @@ void cac::show ( unsigned level ) const if ( this->pudpiiu ) { this->pudpiiu->show ( level - 2u ); } - this->showOutstandingIO ( level - 2u ); + this->ioCounter.show ( level - 2u ); } if ( level > 2u ) { @@ -437,103 +415,78 @@ void cac::beaconNotify ( const inetAddrID &addr ) # endif } -int cac::pend ( double timeout, int early ) +int cac::pendIO ( const double &timeout ) { - int status; - void *p; - - /* - * dont allow recursion - */ - p = epicsThreadPrivateGet ( cacRecursionLock ); - if ( p ) { + // prevent recursion nightmares by disabling calls to + // pendIO () from within a CA callback + if ( this->pRecvProcThread->isCurrentThread () ) { return ECA_EVDISALLOW; } - epicsThreadPrivateSet ( cacRecursionLock, &cacRecursionLock ); - this->enableCallbackPreemption (); - status = this->pendPrivate ( timeout, early ); + this->flush (); + + int status = ECA_NORMAL; + epicsTime beg_time = epicsTime::getCurrent (); + double remaining; + if ( timeout == 0.0 ) { + remaining = 60.0; + } + else{ + remaining = timeout; + } + while ( this->ioCounter.currentCount () > 0 ) { + if ( remaining < CAC_SIGNIFICANT_SELECT_DELAY ) { + status = ECA_TIMEOUT; + break; + } + this->ioCounter.waitForCompletion ( remaining ); + if ( timeout != 0.0 ) { + double delay = epicsTime::getCurrent () - beg_time; + remaining = timeout - delay; + } + } + + this->ioCounter.cleanUp (); + if ( this->pudpiiu ) { + this->pudpiiu->connectTimeoutNotify (); + } this->disableCallbackPreemption (); - epicsThreadPrivateSet ( cacRecursionLock, NULL ); - return status; } -/* - * cac::pendPrivate () - */ -int cac::pendPrivate (double timeout, int early) +int cac::pendEvent ( const double &timeout ) { - epicsTime cur_time; - epicsTime beg_time; - double delay; + // prevent recursion nightmares by disabling calls to + // pendIO () from within a CA callback + if ( this->pRecvProcThread->isCurrentThread () ) { + return ECA_EVDISALLOW; + } + + this->enableCallbackPreemption (); this->flush (); - if ( this->currentOutstandingIOCount () == 0u && early ) { - return ECA_NORMAL; - } - - if ( timeout < 0.0 ) { - if ( early ) { - this->cleanUpOutstandingIO (); - if ( this->pudpiiu ) { - this->pudpiiu->connectTimeoutNotify (); - } - } - return ECA_TIMEOUT; - } - - beg_time = cur_time = epicsTime::getCurrent (); - - delay = 0.0; - while ( true ) { - ca_real remaining; - - if ( timeout == 0.0 ) { - remaining = 60.0; - } - else{ - remaining = timeout - delay; - - /* - * If we are not waiting for any significant delay - * then force the delay to zero so that we avoid - * scheduling delays (which can be substantial - * on some os) - */ - if ( remaining <= CAC_SIGNIFICANT_SELECT_DELAY ) { - if ( early ) { - this->cleanUpOutstandingIO (); - if ( this->pudpiiu ) { - this->pudpiiu->connectTimeoutNotify (); - } - } - return ECA_TIMEOUT; - } - } - - this->waitForCompletionOfIO ( remaining ); - - if ( this->currentOutstandingIOCount () == 0 && early ) { - return ECA_NORMAL; - } - - cur_time = epicsTime::getCurrent (); - - if ( timeout != 0.0 ) { - delay = cur_time - beg_time; + if ( timeout == 0.0 ) { + while ( true ) { + epicsThreadSleep ( 60.0 ); } } + else if ( timeout >= CAC_SIGNIFICANT_SELECT_DELAY ) { + epicsThreadSleep ( timeout ); + } + + this->disableCallbackPreemption (); + + return ECA_TIMEOUT; } bool cac::ioComplete () const { - if ( this->currentOutstandingIOCount () == 0u ) { + if ( this->ioCounter.currentCount () == 0u ) { return true; } else{ @@ -550,7 +503,7 @@ void cac::accessRightsNotify ( unsigned id, const caar &ar ) } } -void cac::connectChannel ( bool v44Ok, unsigned id, +bool cac::connectChannel ( bool v44Ok, unsigned id, unsigned nativeType, unsigned long nativeCount, unsigned sid ) { epicsAutoMutex autoMutex ( this->defaultMutex ); @@ -564,16 +517,24 @@ void cac::connectChannel ( bool v44Ok, unsigned id, sidTmp = pChan->getSID (); } pChan->connect ( nativeType, nativeCount, sidTmp ); + return true; + } + else { + return false; } } // this is to only be used by early protocol revisions -void cac::connectChannel ( unsigned id ) +bool cac::connectChannel ( unsigned id ) { epicsAutoMutex autoMutex ( this->defaultMutex ); nciu * pChan = this->chanTable.lookup ( id ); if ( pChan ) { pChan->connect (); + return true; + } + else { + return false; } } @@ -635,9 +596,9 @@ cacChannelIO * cac::createChannelIO ( const char *pName, cacChannelNotify &chan { cacChannelIO *pIO; - pIO = this->services.createChannelIO ( pName, *this, chan ); + pIO = this->services.createChannelIO ( pName, chan ); if ( ! pIO ) { - pIO = cacGlobalServiceList.createChannelIO ( pName, *this, chan ); + pIO = cacGlobalServiceList.createChannelIO ( pName, chan ); if ( ! pIO ) { if ( ! this->pudpiiu || ! this->pSearchTmr ) { if ( ! this->setupUDP () ) { @@ -647,7 +608,7 @@ cacChannelIO * cac::createChannelIO ( const char *pName, cacChannelNotify &chan nciu *pNetChan = new nciu ( *this, limboIIU, chan, pName ); if ( pNetChan ) { if ( ! pNetChan->fullyConstructed () ) { - pNetChan->destroy (); + delete static_cast < cacChannelIO * > ( pNetChan ); return 0; } else { @@ -662,7 +623,7 @@ cacChannelIO * cac::createChannelIO ( const char *pName, cacChannelNotify &chan return pIO; } -void cac::installNetworkChannel ( nciu &chan, netiiu *&piiu ) +void cac::installNetworkChannel ( nciu & chan, netiiu * & piiu ) { epicsAutoMutex autoMutex ( this->defaultMutex ); this->chanTable.add ( chan ); @@ -787,14 +748,14 @@ void cac::replaceErrLogHandler ( caPrintfFunc *ca_printf_func ) } } -void cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, +bool cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, unsigned typeCode, unsigned long count, unsigned minorVersionNumber, const osiSockAddr &addr ) { unsigned retrySeqNumber; if ( addr.sa.sa_family != AF_INET ) { - return; + return false; } { @@ -808,7 +769,7 @@ void cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, */ chan = this->chanTable.lookup ( cid ); if ( ! chan ) { - return; + return true; } retrySeqNumber = chan->getRetrySeqNo (); @@ -817,7 +778,7 @@ void cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, * Ignore duplicate search replies */ if ( chan->isAttachedToVirtaulCircuit ( addr ) ) { - return; + return true; } /* @@ -829,7 +790,7 @@ void cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, piiu = pBHE->getIIU (); if ( piiu ) { if ( ! piiu->alive () ) { - return; + return true; } } } @@ -838,11 +799,11 @@ void cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, if ( pBHE ) { if ( this->beaconTable.add ( *pBHE ) < 0 ) { pBHE->destroy (); - return; + return true; } } else { - return; + return true; } piiu = 0; } @@ -852,7 +813,7 @@ void cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, if ( ! piiu ) { piiu = new tcpiiu ( *this, this->connTMO, *this->pTimerQueue ); if ( ! piiu ) { - return; + return true; } } if ( piiu->fullyConstructed () ) { @@ -861,12 +822,12 @@ void cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, *pBHE, this->ipToAEngine ) ) { this->iiuList.remove ( *piiu ); this->iiuListLimbo.add ( *piiu ); - return; + return true; } } else { delete piiu; - return; + return true; } } @@ -888,7 +849,7 @@ void cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, this->pSearchTmr->notifySearchResponse ( retrySeqNumber ); } - return; + return true; } void cac::uninstallChannel ( nciu & chan )