diff --git a/src/ca/legacy/pcas/generic/casPVI.cc b/src/ca/legacy/pcas/generic/casPVI.cc index 7f862a044..8702614be 100644 --- a/src/ca/legacy/pcas/generic/casPVI.cc +++ b/src/ca/legacy/pcas/generic/casPVI.cc @@ -211,9 +211,10 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp ) } } else { - errMessage ( S_cas_badType, + errPrintf ( S_cas_badType, __FILE__, __LINE__, "application type \"enums\" string conversion" - " table for enumerated PV isnt a string type?" ); + " table for enumerated PV \"%s\" isnt a string type?", + getName() ); } } else if ( resp.dimension() == 1 ) { diff --git a/src/libCom/bucketLib/bucketLib.c b/src/libCom/bucketLib/bucketLib.c index 1f68e1d97..188a04226 100644 --- a/src/libCom/bucketLib/bucketLib.c +++ b/src/libCom/bucketLib/bucketLib.c @@ -144,7 +144,7 @@ static ITEM **bucketStringCompare (ITEM **ppi, const void *pId) */ static BUCKETID bucketUnsignedHash (BUCKET *pb, const void *pId) { - const unsigned *pUId = pId; + const unsigned *pUId = (const unsigned *) pId; unsigned src; BUCKETID hashid; @@ -194,7 +194,7 @@ static BUCKETID bucketPointerHash (BUCKET *pb, const void *pId) */ static BUCKETID bucketStringHash (BUCKET *pb, const void *pId) { - const char *pStr = pId; + const char *pStr = (const char *) pId; BUCKETID hashid; unsigned i; diff --git a/src/libCom/cxxTemplates/README b/src/libCom/cxxTemplates/README index ba9a29bb8..786c598b3 100644 --- a/src/libCom/cxxTemplates/README +++ b/src/libCom/cxxTemplates/README @@ -30,28 +30,6 @@ class "T" (the type stored in the hash table) must derive from class "ID" (the hash table key type) and also derive from tsSLNode. -So far, the only confusion I have run into with templates has been: - -1) strange compiler messages - unrelated to cause of course - -when I get the class declaration order wrong (so that the -compiler has trouble instantiating the template). - -2) sun pro/dec/att compilers use a template database and -gnu/msvc++ compilers use explicit template instantiation. -Therefore blocks of code of this sort are required: - -#include "resourceLib.h" // template def -#include "resourceLib.cc" // template functions (that are not inline) -#if defined (EXPL_TEMPL) - // - // From Stroustrups's "The C++ Programming Language" - // Appendix A: r.14.9 - // - // This explicitly instantiates the template class's member - // functions into "templInst.o" - // - template class resTable; - template class resTable; -#endif + diff --git a/src/libCom/fdmgr/fdManager.cpp b/src/libCom/fdmgr/fdManager.cpp index 113cc138d..8beafe8db 100644 --- a/src/libCom/fdmgr/fdManager.cpp +++ b/src/libCom/fdmgr/fdManager.cpp @@ -21,20 +21,17 @@ // 1) This library is not thread safe // -// -// ANSI C -// -#include -#include +#include #define instantiateRecourceLib #define epicsExportSharedSymbols #include "epicsAssert.h" #include "epicsThread.h" -#include "tsMinMax.h" #include "fdManager.h" #include "locationException.h" +using std :: max; + epicsShareDef fdManager fileDescriptorManager; const unsigned mSecPerSec = 1000u; @@ -261,9 +258,9 @@ void fdRegId::show ( unsigned level ) const // // fdManager::installReg () // -epicsShareFunc void fdManager::installReg (fdReg ®) +void fdManager::installReg (fdReg ®) { - this->maxFD = tsMax ( this->maxFD, reg.getFD()+1 ); + this->maxFD = max ( this->maxFD, reg.getFD()+1 ); // Most applications will find that its important to push here to // the front of the list so that transient writes get executed // first allowing incoming read protocol to find that outgoing diff --git a/src/libCom/fdmgr/fdManager.h b/src/libCom/fdmgr/fdManager.h index 694749448..621a004bc 100644 --- a/src/libCom/fdmgr/fdManager.h +++ b/src/libCom/fdmgr/fdManager.h @@ -104,8 +104,8 @@ private: fdReg * pCBReg; void reschedule (); double quantum (); - epicsShareFunc void installReg (fdReg ®); - epicsShareFunc void removeReg (fdReg ®); + void installReg (fdReg ®); + void removeReg (fdReg ®); void lazyInitTimerQueue (); fdManager ( const fdManager & ); fdManager & operator = ( const fdManager & ); diff --git a/src/libCom/misc/aToIPAddr.c b/src/libCom/misc/aToIPAddr.c index 104418fc1..c21b574f6 100644 --- a/src/libCom/misc/aToIPAddr.c +++ b/src/libCom/misc/aToIPAddr.c @@ -1,8 +1,8 @@ /*************************************************************************\ +* Copyright (c) 2013 LANS LLC, as Operator of +* Los Alamos National Laboratory. * Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ @@ -15,21 +15,52 @@ #include #define epicsExportSharedSymbols +#include "epicsTypes.h" #include "osiSock.h" -#include "epicsStdlib.h" + +#ifndef NELEMENTS +#define NELEMENTS(A) (sizeof(A)/sizeof(A[0])) +#endif /*NELEMENTS*/ + +/* + * addrArrayToUL () + */ +static int addrArrayToUL ( const unsigned *pAddr, + unsigned nElements, struct in_addr *pIpAddr ) +{ + unsigned i; + epicsUInt32 addr = 0ul; + + for ( i=0u; i < nElements; i++ ) { + if ( pAddr[i] > 0xff ) { + return -1; + } + addr <<= 8; + addr |= ( epicsUInt32 ) pAddr[i]; + } + pIpAddr->s_addr = htonl ( addr ); + + return 0; +} /* * initIPAddr() * !! ipAddr should be passed in in network byte order !! * !! port is passed in in host byte order !! */ -static int initIPAddr (struct in_addr ipAddr, unsigned short port, - struct sockaddr_in *pIP) +static int initIPAddr ( struct in_addr ipAddr, unsigned port, + struct sockaddr_in *pIP ) { - memset(pIP, '\0', sizeof(*pIP)); - pIP->sin_family = AF_INET; - pIP->sin_port = htons(port); - pIP->sin_addr = ipAddr; + if ( port > 0xffff ) { + return -1; + } + { + epicsUInt16 port_16 = (epicsUInt16) port; + memset (pIP, '\0', sizeof(*pIP)); + pIP->sin_family = AF_INET; + pIP->sin_port = htons(port_16); + pIP->sin_addr = ipAddr; + } return 0; } @@ -42,47 +73,121 @@ static int initIPAddr (struct in_addr ipAddr, unsigned short port, * * Sets the port number to "defaultPort" only if * "pAddrString" does not contain an address of the form - * "n.n.n.n:p" + * "n.n.n.n:p or host:p" */ -epicsShareFunc int epicsShareAPI -aToIPAddr(const char *pAddrString, unsigned short defaultPort, - struct sockaddr_in *pIP) +epicsShareFunc int epicsShareAPI +aToIPAddr( const char *pAddrString, unsigned short defaultPort, + struct sockaddr_in *pIP ) { int status; - char hostName[512]; /* !! change n elements here requires change in format below !! */ - unsigned int port; - unsigned long numaddr; + unsigned addr[4]; + unsigned long rawAddr; + /* + * !! change n elements here requires change in format below !! + */ + char hostName[512]; + char dummy[8]; + unsigned port; struct in_addr ina; /* - * Scan for a port number + * dotted ip addresses */ - status = sscanf( pAddrString, " %511[^:]:%u", hostName, &port ); - if ( status == 0 ) { - return -1; + status = sscanf ( pAddrString, " %u . %u . %u . %u %7s ", + addr, addr+1u, addr+2u, addr+3u, dummy ); + if ( status == 4 ) { + if ( addrArrayToUL ( addr, NELEMENTS ( addr ), & ina ) < 0 ) { + return -1; + } + port = defaultPort; + return initIPAddr ( ina, port, pIP ); } + + /* + * dotted ip addresses and port + */ + status = sscanf ( pAddrString, " %u . %u . %u . %u : %u %7s", + addr, addr+1u, addr+2u, addr+3u, &port, dummy ); + if ( status >= 5 ) { + if ( status > 5 ) { + /* + * valid at the start but detritus on the end + */ + return -1; + } + if ( addrArrayToUL ( addr, NELEMENTS ( addr ), &ina ) < 0 ) { + return -1; + } + return initIPAddr ( ina, port, pIP ); + } + + /* + * IP address as a raw number + */ + status = sscanf ( pAddrString, " %lu %7s ", &rawAddr, dummy ); + if ( status == 1 ) { + if ( rawAddr > 0xffffffff ) { + return -1; + } + port = defaultPort; + { + epicsUInt32 rawAddr_32 = ( epicsUInt32 ) rawAddr; + ina.s_addr = htonl ( rawAddr_32 ); + return initIPAddr ( ina, port, pIP ); + } + } + + /* + * IP address as a raw number, and port + */ + status = sscanf ( pAddrString, " %lu : %u %7s ", &rawAddr, &port, dummy ); + if ( status >= 2 ) { + if ( status > 2 ) { + /* + * valid at the start but detritus on the end + */ + return -1; + } + if ( rawAddr > 0xffffffff ) { + return -1; + } + { + epicsUInt32 rawAddr_32 = ( epicsUInt32 ) rawAddr; + ina.s_addr = htonl ( rawAddr_32 ); + return initIPAddr ( ina, port, pIP ); + } + } + + + /* + * host name string + */ + status = sscanf ( pAddrString, " %511[^:] %s ", hostName, dummy ); if ( status == 1 ) { port = defaultPort; + status = hostToIPAddr ( hostName, &ina ); + if ( status == 0 ) { + return initIPAddr ( ina, port, pIP ); + } } - else if (status == 2 && port > 65535) { - return -1; - } - + /* - * Look for a valid host name or dotted quad + * host name string, and port */ - status = hostToIPAddr( hostName, &ina ); - if ( status == 0 ) { - return initIPAddr( ina, port, pIP ); + status = sscanf ( pAddrString, " %511[^:] : %u %s ", hostName, + &port, dummy ); + if ( status >= 2 ) { + if ( status > 2 ) { + /* + * valid at the start but detritus on the end + */ + return -1; + } + status = hostToIPAddr ( hostName, &ina ); + if ( status == 0 ) { + return initIPAddr ( ina, port, pIP ); + } } - /* - * Try the IP address as a decimal integer - */ - if ( epicsParseULong( hostName, &numaddr, 10, NULL ) ) { - return -1; - } - - ina.s_addr = htonl( numaddr ); - return initIPAddr( ina, port, pIP ); + return -1; } diff --git a/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp b/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp index 3f87fd59a..e0dfd0c4d 100644 --- a/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp +++ b/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #define epicsExportSharedSymbols #include "ipAddrToAsciiAsynchronous.h" @@ -206,7 +206,7 @@ ipAddrToAsciiEnginePrivate::~ipAddrToAsciiEnginePrivate () this->thread.exitWait (); } -// for now its probably sufficent to allocate one +// for now its probably sufficient to allocate one // DNS transaction thread for all codes sharing // the same process that need DNS services but we // leave our options open for the future diff --git a/src/libCom/osi/epicsTime.cpp b/src/libCom/osi/epicsTime.cpp index 4370f4a27..b85b67b8e 100644 --- a/src/libCom/osi/epicsTime.cpp +++ b/src/libCom/osi/epicsTime.cpp @@ -1,8 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne -* National Laboratory. +* Copyright (c) 2011 LANS LLC, as Operator of +* Los Alamos National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. +* Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ @@ -58,8 +60,12 @@ static const unsigned long NTP_TIME_AT_EPICS_EPOCH = // // epicsTime (const unsigned long secIn, const unsigned long nSecIn) // -inline epicsTime::epicsTime (const unsigned long secIn, const unsigned long nSecIn) : - secPastEpoch ( nSecIn / nSecPerSec + secIn ), nSec ( nSecIn % nSecPerSec ) {} +inline epicsTime::epicsTime (const unsigned long secIn, + const unsigned long nSecIn) : + secPastEpoch ( nSecIn / nSecPerSec + secIn ), + nSec ( nSecIn % nSecPerSec ) +{ +} // // epicsTimeLoadTimeInit @@ -109,51 +115,45 @@ epicsTimeLoadTimeInit::epicsTimeLoadTimeInit () // // epicsTime::addNanoSec () // -// many of the UNIX timestamp formats have nano sec stored as a long +// The nano-second field of several of the the UNIX time stamp formats +// field is stored in the C type "long". // -void epicsTime::addNanoSec (long nSecAdj) +void epicsTime :: addNanoSec ( long nSecAdj ) { - // After optimizing this function we now have a larger - // code which uses only unsigned integer arithmetic. - // This is for the benefit of embedded cpu's lacking - // a hardware floating point coprocessor at the - // expense of some additional code to maintain. - // joh 14-11-2012 + // + // After optimizing this function we now have a larger code which + // uses only unsigned integer, and not floating point, arithmetic. + // This change benefits embedded CPU's lacking a floating point + // co-processor at the expense of some additional code to maintain. + // + // We hope that all CPU's we run on provide at least an integer + // divide instruction which should enable this implementation + // to be more efficient than implementations based on branching; + // this is presuming that we will run on pipelined architectures. + // + // Overflow and underflow is expected; in the future we might + // operate close to, the modulo of, the EPICS epic. + // + // We are depending on the normalize operation in the private + // constructor used below. + // + // joh 11-04-2012 + // if ( nSecAdj >= 0 ) { - unsigned long nSecOffsetLong = - static_cast < unsigned long > ( nSecAdj ); - while ( nSecOffsetLong >= nSecPerSec ) { - this->secPastEpoch++; // overflow expected - nSecOffsetLong -= nSecPerSec; - } - const epicsUInt32 nSecOffset = - static_cast < epicsUInt32 > ( nSecOffsetLong ); - epicsUInt32 nSecPerSecRemaining = nSecPerSec - nSecOffset; - if ( this->nSec >= nSecPerSecRemaining ) { - this->secPastEpoch++; // overflow expected - this->nSec -= nSecPerSecRemaining; - } - else { - this->nSec += nSecOffset; - } + const unsigned long nSecPlus = + static_cast ( nSecAdj ); + const unsigned long nSecPlusAdj = nSecPlus % nSecPerSec; + const unsigned long secPlusAdj = nSecPlus / nSecPerSec; + *this = epicsTime ( this->secPastEpoch+secPlusAdj, + this->nSec+nSecPlusAdj ); } else { - unsigned long nSecOffsetLong = - static_cast ( -nSecAdj ); - while ( nSecOffsetLong >= nSecPerSec ) { - this->secPastEpoch--; // underflow expected - nSecOffsetLong -= nSecPerSec; - } - const epicsUInt32 nSecOffset = - static_cast < epicsUInt32 > ( nSecOffsetLong ); - if ( this->nSec >= nSecOffset ) { - this->nSec -= nSecOffset; - } - else { - // borrow - this->secPastEpoch--; // underflow expected - this->nSec += nSecPerSec - nSecOffset; - } + const unsigned long nSecMinus = + static_cast ( -nSecAdj ); + const unsigned long nSecMinusAdj = nSecMinus % nSecPerSec; + const unsigned long secMinusAdj = nSecMinus / nSecPerSec; + *this = epicsTime ( this->secPastEpoch - secMinusAdj - 1u, + this->nSec + nSecPerSec - nSecMinusAdj ); } } @@ -368,8 +368,8 @@ epicsTime::operator struct timeval () const time_t_wrapper ansiTimeTicks; ansiTimeTicks = *this; - // On Posix systems timeval :: tv_sec is a time_t so this can be - // a direct assignement. On other systems I dont know that we can + // On Posix systems timeval :: tv_sec is a time_t so this can be + // a direct assignment. On other systems I dont know that we can // guarantee that time_t and timeval :: tv_sec will have the // same epoch or have the same scaling factor to discrete seconds. // For example, on windows time_t changed recently to a 64 bit @@ -387,8 +387,8 @@ epicsTime::operator struct timeval () const epicsTime::epicsTime (const struct timeval &ts) { time_t_wrapper ansiTimeTicks; - // On Posix systems timeval :: tv_sec is a time_t so this can be - // a direct assignement. On other systems I dont know that we can + // On Posix systems timeval :: tv_sec is a time_t so this can be + // a direct assignment. On other systems I dont know that we can // guarantee that time_t and timeval :: tv_sec will have the // same epoch or have the same scaling factor to discrete seconds. // For example, on windows time_t changed recently to a 64 bit @@ -438,11 +438,11 @@ epicsTime::operator epicsTimeStamp () const } epicsTimeStamp ts; // - // trucation by design + // truncation by design // ------------------- - // epicsTime::secPastEpoch is based on ulong and has much greater range - // on 64 bit hosts than the orginal epicsTimeStamp::secPastEpoch. The - // epicsTimeStamp::secPastEpoch is based on epicsUInt32 so that it will + // epicsTime::secPastEpoch is based on ulong and has much greater range + // on 64 bit hosts than the original epicsTimeStamp::secPastEpoch. The + // epicsTimeStamp::secPastEpoch is based on epicsUInt32 so that it will // match the original network protocol. Of course one can anticipate // that eventually, a epicsUInt64 based network time stamp will be // introduced when 64 bit architectures are more ubiquitous. @@ -655,7 +655,7 @@ void epicsTime::show ( unsigned level ) const } if ( level > 1 ) { - // this also supresses the "defined, but not used" + // this also suppresses the "defined, but not used" // warning message printf ( "epicsTime: revision \"%s\"\n", pEpicsTimeVersion ); diff --git a/src/libCom/osi/os/WIN32/osdProcess.c b/src/libCom/osi/os/WIN32/osdProcess.c index fd680307d..fcf1e2feb 100644 --- a/src/libCom/osi/os/WIN32/osdProcess.c +++ b/src/libCom/osi/os/WIN32/osdProcess.c @@ -64,90 +64,76 @@ epicsShareFunc osiSpawnDetachedProcessReturn epicsShareAPI osiSpawnDetachedProce startupInfo.wShowWindow = SW_SHOWMINNOACTIVE; status = CreateProcess ( - NULL, /* pointer to name of executable module (not required if command line is specified) */ - (char *) pBaseExecutableName, /* pointer to command line string */ - NULL, /* pointer to process security attributes */ - NULL, /* pointer to thread security attributes */ - FALSE, /* handle inheritance flag */ - CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, /* creation flags */ - NULL, /* pointer to new environment block (defaults to caller's environement) */ - NULL, /* pointer to current directory name (defaults to caller's current directory) */ - &startupInfo, /* pointer to STARTUPINFO */ - &processInfo /* pointer to PROCESS_INFORMATION */ - ); - if ( status == 0 ) { - DWORD W32status; - LPVOID errStrMsgBuf; - LPVOID complteMsgBuf; + NULL, /* pointer to name of executable module (not required if command line is specified) */ + (char *) pBaseExecutableName, /* pointer to command line string */ + NULL, /* pointer to process security attributes */ + NULL, /* pointer to thread security attributes */ + FALSE, /* handle inheritance flag */ + CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, /* creation flags */ + NULL, /* pointer to new environment block (defaults to caller's environement) */ + NULL, /* pointer to current directory name (defaults to caller's current directory) */ + &startupInfo, /* pointer to STARTUPINFO */ + &processInfo /* pointer to PROCESS_INFORMATION */ + ); + if ( status == 0 ) { + DWORD W32status; + LPVOID errStrMsgBuf; + LPVOID complteMsgBuf; + + W32status = FormatMessage ( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError (), + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + (LPTSTR) &errStrMsgBuf, + 0, + NULL + ); - W32status = FormatMessage ( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - GetLastError (), - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ - (LPTSTR) &errStrMsgBuf, - 0, - NULL - ); - - if ( W32status ) { - char *pFmtArgs[6]; + if ( W32status ) { + char *pFmtArgs[6]; pFmtArgs[0] = "Failed to start executable -"; pFmtArgs[1] = (char *) pBaseExecutableName; pFmtArgs[2] = errStrMsgBuf; pFmtArgs[3] = "Changes may be required in your \"path\" environment variable."; pFmtArgs[4] = "PATH = "; pFmtArgs[5] = getenv ("path"); - if ( pFmtArgs[5] == NULL ) { - pFmtArgs[5] = ""; - } - - W32status = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | - FORMAT_MESSAGE_ARGUMENT_ARRAY | 80, - "%1 \"%2\". %3 %4 %5 \"%6\"", - 0, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ - (LPTSTR) &complteMsgBuf, - 0, - pFmtArgs - ); - if (W32status) { - /* Display the string. */ - MessageBox (NULL, complteMsgBuf, "Configuration Problem", - MB_OK | MB_ICONINFORMATION); - LocalFree (complteMsgBuf); - } - else { - /* Display the string. */ - MessageBox (NULL, errStrMsgBuf, "Failed to start executable", - MB_OK | MB_ICONINFORMATION); - } - - /* Free the buffer. */ - LocalFree (errStrMsgBuf); - } - else { - errlogPrintf ("!!WARNING!!\n"); - errlogPrintf ("Unable to locate executable \"%s\".\n", pBaseExecutableName); - errlogPrintf ("You may need to modify your environment.\n"); - } + if ( pFmtArgs[5] == NULL ) { + pFmtArgs[5] = ""; + } + + W32status = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | + FORMAT_MESSAGE_ARGUMENT_ARRAY | 80, + "%1 \"%2\". %3 %4 %5 \"%6\"", + 0, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + (LPTSTR) &complteMsgBuf, + 0, + pFmtArgs + ); + if (W32status) { + /* Display the string. */ + MessageBox (NULL, complteMsgBuf, "Configuration Problem", + MB_OK | MB_ICONINFORMATION); + LocalFree (complteMsgBuf); + } + else { + /* Display the string. */ + MessageBox (NULL, errStrMsgBuf, "Failed to start executable", + MB_OK | MB_ICONINFORMATION); + } + + /* Free the buffer. */ + LocalFree (errStrMsgBuf); + } + else { + errlogPrintf ("!!WARNING!!\n"); + errlogPrintf ("Unable to locate executable \"%s\".\n", pBaseExecutableName); + errlogPrintf ("You may need to modify your \"path\" environment variable.\n"); + } return osiSpawnDetachedProcessFail; - } + } return osiSpawnDetachedProcessSuccess; - - /* - use of spawn here causes problems when the ca repeater - inherits open files (and sockets) from the spawning - process - - status = _spawnlp (_P_DETACH, pBaseExecutableName, pBaseExecutableName, NULL); - if (status<0) { - errlogPrintf ("!!WARNING!!\n"); - errlogPrintf ("Unable to locate the EPICS executable \"%s\".\n", - pBaseExecutableName); - errlogPrintf ("You may need to modify your environment.\n"); - } - */ } diff --git a/src/libCom/osi/os/WIN32/osdTime.cpp b/src/libCom/osi/os/WIN32/osdTime.cpp index 33a63b873..877311ffa 100644 --- a/src/libCom/osi/os/WIN32/osdTime.cpp +++ b/src/libCom/osi/os/WIN32/osdTime.cpp @@ -17,10 +17,10 @@ // // ANSI C // -#include -#include -#include -#include +#include +#include +#include +#include // // WIN32 @@ -28,6 +28,7 @@ #define VC_EXTRALEAN #define STRICT #include +#include // // EPICS @@ -46,19 +47,26 @@ # define debugPrintf(argsInParen) #endif +extern "C" void setThreadName ( DWORD dwThreadID, LPCSTR szThreadName ); + static int osdTimeGetCurrent ( epicsTimeStamp *pDest ); // for mingw #if !defined ( MAXLONGLONG ) -#define MAXLONGLONG 0x7fffffffffffffffLL +# define MAXLONGLONG 0x7fffffffffffffffLL #endif #if !defined ( MINLONGLONG ) -#define MINLONGLONG (~0x7fffffffffffffffLL) +# define MINLONGLONG ~0x7fffffffffffffffLL +#endif +#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION +# define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000 #endif static const LONGLONG epicsEpochInFileTime = 0x01b41e2a18d64000LL; -class currentTime : public epicsTimerNotify { +static unsigned __stdcall _pllThreadEntry ( void * pCurrentTimeIn ); + +class currentTime { public: currentTime (); ~currentTime (); @@ -72,20 +80,24 @@ private: LONGLONG perfCounterFreqPLL; LONGLONG lastPerfCounterPLL; LONGLONG lastFileTimePLL; - epicsTimerQueueActive * pTimerQueue; - epicsTimer * pTimer; + HANDLE threadHandle; + unsigned threadId; bool perfCtrPresent; + bool threadShutdownCmd; + bool threadHasExited; + void updatePLL (); static const int pllDelay; /* integer seconds */ - epicsTimerNotify::expireStatus expire ( const epicsTime & ); + // cant be static because of diff btw __stdcall and __cdecl + friend unsigned __stdcall _pllThreadEntry ( void * pCurrentTimeIn ); }; +const int currentTime :: pllDelay = 5; + static currentTime * pCurrentTime = 0; static const LONGLONG FILE_TIME_TICKS_PER_SEC = 10000000; static const LONGLONG EPICS_TIME_TICKS_PER_SEC = 1000000000; static const LONGLONG ET_TICKS_PER_FT_TICK = EPICS_TIME_TICKS_PER_SEC / FILE_TIME_TICKS_PER_SEC; - -const int currentTime :: pllDelay = 5; // // Start and register time provider @@ -185,8 +197,8 @@ int epicsShareAPI epicsTime_localtime ( } // - // There are remarkable weaknessess in the FileTimeToLocalFileTime - // interface so we dont use it here. Unfortunately, there is no + // There are remarkable weaknesses in the FileTimeToLocalFileTime + // interface so we don't use it here. Unfortunately, there is no // corresponding function that works on file time. // SYSTEMTIME st; @@ -263,9 +275,11 @@ currentTime::currentTime () : perfCounterFreqPLL ( 0 ), lastPerfCounterPLL ( 0 ), lastFileTimePLL ( 0 ), - pTimerQueue ( 0 ), - pTimer ( 0 ), - perfCtrPresent ( false ) + threadHandle ( 0 ), + threadId ( 0 ), + perfCtrPresent ( false ), + threadShutdownCmd ( false ), + threadHasExited ( false ) { InitializeCriticalSection ( & this->mutex ); @@ -308,15 +322,34 @@ currentTime::currentTime () : this->lastFileTimePLL = liFileTime.QuadPart; } +void currentTime :: startPLL () +{ + // create frequency estimation thread when needed + if ( this->perfCtrPresent && ! this->threadHandle ) { + this->threadHandle = (HANDLE) + _beginthreadex ( 0, 4096, _pllThreadEntry, this, + CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, + & this->threadId ); + assert ( this->threadHandle ); + BOOL bstat = SetThreadPriority ( + this->threadHandle, THREAD_PRIORITY_HIGHEST ); + assert ( bstat ); + DWORD wstat = ResumeThread ( this->threadHandle ); + assert ( wstat != 0xFFFFFFFF ); + } +} + currentTime::~currentTime () { + EnterCriticalSection ( & this->mutex ); + this->threadShutdownCmd = true; + while ( ! this->threadHasExited ) { + LeaveCriticalSection ( & this->mutex ); + Sleep ( 250 /* mS */ ); + EnterCriticalSection ( & this->mutex ); + } + LeaveCriticalSection ( & this->mutex ); DeleteCriticalSection ( & this->mutex ); - if ( this->pTimer ) { - this->pTimer->destroy (); - } - if ( this->pTimerQueue ) { - this->pTimerQueue->release (); - } } void currentTime::getCurrentTime ( epicsTimeStamp & dest ) @@ -386,7 +419,7 @@ void currentTime::getCurrentTime ( epicsTimeStamp & dest ) // Maintain corrected version of the performance counter's frequency using // a phase locked loop. This approach is similar to NTP's. // -epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & ) +void currentTime :: updatePLL () { EnterCriticalSection ( & this->mutex ); @@ -431,7 +464,7 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & ) if ( fileTimeDiff <= 0 ) { LeaveCriticalSection( & this->mutex ); debugPrintf ( ( "currentTime: file time difference in PLL was less than zero\n" ) ); - return expireStatus ( restart, pllDelay /* sec */ ); + return; } LONGLONG freq = ( FILE_TIME_TICKS_PER_SEC * perfCounterDiff ) / fileTimeDiff; @@ -445,7 +478,7 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & ) static_cast < int > ( -bound ), static_cast < int > ( delta ), static_cast < int > ( bound ) ) ); - return expireStatus ( restart, pllDelay /* sec */ ); + return; } // update feedback loop estimating the performance counter's frequency @@ -482,7 +515,7 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & ) debugPrintf ( ( "perf ctr measured delay out of bounds m=%d max=%d\n", static_cast < int > ( perfCounterDiffSinceLastFetch ), static_cast < int > ( expectedDly + bnd ) ) ); - return expireStatus ( restart, pllDelay /* sec */ ); + return; } } @@ -521,9 +554,9 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & ) delta = epicsTimeFromCurrentFileTime - this->epicsTimeLast; if ( delta > EPICS_TIME_TICKS_PER_SEC || delta < -EPICS_TIME_TICKS_PER_SEC ) { - // When there is an abrupt shift in the current computed time vs - // the time derived from the current file time then someone has - // probabably adjusted the real time clock and the best reaction + // When there is an abrupt shift in the current computed time vs + // the time derived from the current file time then someone has + // probably adjusted the real time clock and the best reaction // is to just assume the new time base this->epicsTimeLast = epicsTimeFromCurrentFileTime; this->perfCounterFreq = this->perfCounterFreqPLL; @@ -563,24 +596,31 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & ) ( this->perfCounterFreqPLL - sysFreq.QuadPart ); freqEstDiff /= sysFreq.QuadPart; freqEstDiff *= 100.0; - debugPrintf ( ( "currentTime: freq delta %f %% freq est delta %f %% time delta %f sec\n", - freqDiff, freqEstDiff, static_cast < double > ( delta ) / EPICS_TIME_TICKS_PER_SEC ) ); + debugPrintf ( ( "currentTime: freq delta %f %% freq est " + "delta %f %% time delta %f sec\n", + freqDiff, + freqEstDiff, + static_cast < double > ( delta ) / + EPICS_TIME_TICKS_PER_SEC ) ); # endif } LeaveCriticalSection ( & this->mutex ); - - return expireStatus ( restart, pllDelay /* sec */ ); } -void currentTime::startPLL () +static unsigned __stdcall _pllThreadEntry ( void * pCurrentTimeIn ) { - // create frequency estimation timer when needed - if ( this->perfCtrPresent && ! this->pTimerQueue ) { - this->pTimerQueue = & epicsTimerQueueActive::allocate ( true ); - this->pTimer = & this->pTimerQueue->createTimer (); - this->pTimer->start ( *this, pllDelay ); + currentTime * pCT = + reinterpret_cast < currentTime * > ( pCurrentTimeIn ); + setThreadName ( pCT->threadId, "EPICS Time PLL" ); + while ( ! pCT->threadShutdownCmd ) { + Sleep ( currentTime :: pllDelay * 1000 /* mS */ ); + pCT->updatePLL (); } + EnterCriticalSection ( & pCT->mutex ); + pCT->threadHasExited = true; + LeaveCriticalSection ( & pCT->mutex ); + return 1; } epicsTime::operator FILETIME () const diff --git a/src/libCom/osi/os/vxWorks/osdSock.c b/src/libCom/osi/os/vxWorks/osdSock.c index 13798803b..a0f5e8ec5 100644 --- a/src/libCom/osi/os/vxWorks/osdSock.c +++ b/src/libCom/osi/os/vxWorks/osdSock.c @@ -115,18 +115,11 @@ epicsShareFunc unsigned epicsShareAPI ipAddrToHostName epicsShareFunc int epicsShareAPI hostToIPAddr(const char *pHostName, struct in_addr *pIPA) { - int addr; - - addr = hostGetByName((char *)pHostName); - if (addr != ERROR) { - pIPA->s_addr = (unsigned long) addr; - } - else if (inet_aton((char *)pHostName, pIPA) == ERROR) { - /* - * return indicating an error - */ + int addr = hostGetByName ( (char *) pHostName ); + if ( addr == ERROR ) { return -1; } + pIPA->s_addr = (unsigned long) addr; /* * success diff --git a/src/libCom/osi/osiNTPTime.c b/src/libCom/osi/osiNTPTime.c index 909e6f121..64362b2e8 100644 --- a/src/libCom/osi/osiNTPTime.c +++ b/src/libCom/osi/osiNTPTime.c @@ -18,6 +18,7 @@ #include #include +#define epicsExportSharedSymbols #include "epicsEvent.h" #include "epicsExit.h" #include "epicsTypes.h" diff --git a/src/libCom/test/blockingSockTest.cpp b/src/libCom/test/blockingSockTest.cpp index 126bac160..1a16bb9e6 100644 --- a/src/libCom/test/blockingSockTest.cpp +++ b/src/libCom/test/blockingSockTest.cpp @@ -56,11 +56,13 @@ private: class server { public: - server ( address & ); + server ( const address & ); void start (); void daemon (); void stop (); + address addr () const; protected: + address srvaddr; SOCKET sock; epicsThreadId id; bool exit; @@ -155,20 +157,20 @@ extern "C" void serverDaemon ( void * pParam ) { pSrv->daemon (); } -server::server ( address & addrIn ) : +server::server ( const address & addrIn ) : + srvaddr ( addrIn ), sock ( epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ), id ( 0 ), exit ( false ) { testOk ( this->sock != INVALID_SOCKET, "Server socket valid" ); // setup server side - int status = bind ( this->sock, - & addrIn.sa, sizeof ( addrIn ) ); + osiSocklen_t slen = sizeof ( this->srvaddr ); + int status = bind ( this->sock, & this->srvaddr.sa, slen ); if ( status ) { testDiag ( "bind to server socket failed, status = %d", status ); } - osiSocklen_t slen = sizeof ( addrIn ); - if ( getsockname(this->sock, &addrIn.sa, &slen) != 0 ) { + if ( getsockname(this->sock, & this->srvaddr.sa, & slen) != 0 ) { testAbort ( "Failed to read socket address" ); } status = listen ( this->sock, 10 ); @@ -184,7 +186,7 @@ void server::start () testOk ( this->id != 0, "Server thread created" ); } -void server::daemon () +void server::daemon () { while ( ! this->exit ) { // accept client side @@ -206,13 +208,18 @@ void server::stop () epicsSocketDestroy ( this->sock ); } +address server::addr () const +{ + return this->srvaddr; +} + serverCircuit::serverCircuit ( SOCKET sockIn ) : circuit ( sockIn ) { circuit * pCir = this; - epicsThreadId threadId = epicsThreadCreate ( - "server circuit", epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium), + epicsThreadId threadId = epicsThreadCreate ( + "server circuit", epicsThreadPriorityMedium, + epicsThreadGetStackSize(epicsThreadStackMedium), socketRecvTest, pCir ); testOk ( threadId != 0, "Server circuit thread created" ); } @@ -233,7 +240,7 @@ static const char *mechName(int mech) {esscimqi_socketBothShutdownRequired, "esscimqi_socketBothShutdownRequired" }, {esscimqi_socketSigAlarmRequired, "esscimqi_socketSigAlarmRequired" } }; - + for (unsigned i=0; i < (sizeof(mechs) / sizeof(mechs[0])); ++i) { if (mech == mechs[i].mech) return mechs[i].name; @@ -254,6 +261,7 @@ MAIN(blockingSockTest) server srv ( addr ); srv.start (); + addr = srv.addr (); clientCircuit client ( addr ); epicsThreadSleep ( 1.0 ); diff --git a/src/libCom/test/epicsTimeTest.cpp b/src/libCom/test/epicsTimeTest.cpp index 83d0a8a07..970258801 100644 --- a/src/libCom/test/epicsTimeTest.cpp +++ b/src/libCom/test/epicsTimeTest.cpp @@ -9,11 +9,6 @@ /* * Authors: Jeff Hill, Marty Kraimer and Andrew Johnson */ - -#ifdef __SUNPRO_CC -using namespace std; -#endif - #include #include #include