Merged Jeff's 3.15_libcom_from_cvs_trunk branch.

This commit is contained in:
Andrew Johnson
2014-08-25 16:27:18 -05:00
14 changed files with 375 additions and 271 deletions

View File

@@ -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 ) {

View File

@@ -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;

View File

@@ -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<T>.
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<fred,uintId>;
template class resTable<jane,stringId>;
#endif

View File

@@ -21,20 +21,17 @@
// 1) This library is not thread safe
//
//
// ANSI C
//
#include <errno.h>
#include <string.h>
#include <algorithm>
#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 &reg)
void fdManager::installReg (fdReg &reg)
{
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

View File

@@ -104,8 +104,8 @@ private:
fdReg * pCBReg;
void reschedule ();
double quantum ();
epicsShareFunc void installReg (fdReg &reg);
epicsShareFunc void removeReg (fdReg &reg);
void installReg (fdReg &reg);
void removeReg (fdReg &reg);
void lazyInitTimerQueue ();
fdManager ( const fdManager & );
fdManager & operator = ( const fdManager & );

View File

@@ -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 <string.h>
#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;
}

View File

@@ -25,7 +25,7 @@
#include <string>
#include <climits>
#include <stdexcept>
#include <stdio.h>
#include <cstdio>
#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

View File

@@ -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 <unsigned long> ( 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 <unsigned long> ( -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 <unsigned long> ( -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 );

View File

@@ -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] = "<empty string>";
}
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] = "<empty string>";
}
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");
}
*/
}

View File

@@ -17,10 +17,10 @@
//
// ANSI C
//
#include <math.h>
#include <time.h>
#include <limits.h>
#include <stdio.h>
#include <cmath>
#include <ctime>
#include <climits>
#include <cstdio>
//
// WIN32
@@ -28,6 +28,7 @@
#define VC_EXTRALEAN
#define STRICT
#include <windows.h>
#include <process.h>
//
// 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

View File

@@ -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

View File

@@ -18,6 +18,7 @@
#include <time.h>
#include <errno.h>
#define epicsExportSharedSymbols
#include "epicsEvent.h"
#include "epicsExit.h"
#include "epicsTypes.h"

View File

@@ -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 );

View File

@@ -9,11 +9,6 @@
/*
* Authors: Jeff Hill, Marty Kraimer and Andrew Johnson
*/
#ifdef __SUNPRO_CC
using namespace std;
#endif
#include <cstddef>
#include <cstdio>
#include <ctime>