diff --git a/configure/CONFIG b/configure/CONFIG
index 52f0a2ee5..eb95a2037 100644
--- a/configure/CONFIG
+++ b/configure/CONFIG
@@ -56,6 +56,8 @@ include $(CONFIG)/CONFIG_BASE_VERSION
include $(CONFIG)/os/CONFIG.$(EPICS_HOST_ARCH).Common
-include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
+RELEASE_TOPS := $(shell $(CONVERTRELEASE) -T $(TOP) releaseTops)
+
ifdef T_A
# Cross compile specific definitions
@@ -86,8 +88,10 @@ endif
# Include
GNU readline or Tecla library
- GNU readline and Tecla librararies can be used by the IOC shell to
+ GNU readline and Tecla libraries can be used by the IOC shell to
provide command line editing and command line history recall and edit.
GNU readline (or Tecla library) must be installed on your target system
when COMMANDLINE_LIBRARY is set to READLINE (or TECLA) for that target.
@@ -130,7 +130,7 @@
EPICS documentation is available through the EPICS website at Argonne. -Release specific documenataion can also be found in the base/documentation +
Release specific documentation can also be found in the base/documentation directory of the distribution.
-base/documentation/README* files
+base/documentation directory - contains setup, build, and install + documents
README.1st Instructions for setup and building epics base README.html html version of README.1st @@ -196,7 +197,7 @@ CONFIG_COMMON Definitions common to all builds CONFIG_ENV Definitions of EPICS environment variables CONFIG_FILE_TYPE - CONFIG_SITE Site specific make defintions + CONFIG_SITE Site specific make definitions CONFIG_SITE_ENV Site defaults for EPICS environment variables MAKEFILE Installs CONFIG* RULES* creates RELEASE Location of external products diff --git a/src/ca/client/perl/Makefile b/src/ca/client/perl/Makefile index 2ad98ec42..bac6e347a 100644 --- a/src/ca/client/perl/Makefile +++ b/src/ca/client/perl/Makefile @@ -24,9 +24,8 @@ PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version) PERL_ARCHNAME = $(shell $(PERL) ../perlConfig.pl archname) PERL_ARCHPATH = $(PERL_VERSION)/$(PERL_ARCHNAME) -ifeq ($(findstring Host,$(VALID_BUILDS)),Host) -ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32),) - # Doesn't build on WIN32 +ifeq ($(T_A),$(EPICS_HOST_ARCH)) # No cross-builds (wrong Perl!) +ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32),) # Doesn't build on WIN32 LOADABLE_LIBRARY_HOST = Cap5 PERL_SCRIPTS += cainfo.pl diff --git a/src/ca/client/repeater.cpp b/src/ca/client/repeater.cpp index ef271e461..5e123ee2d 100644 --- a/src/ca/client/repeater.cpp +++ b/src/ca/client/repeater.cpp @@ -3,8 +3,7 @@ * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -16,26 +15,6 @@ * Author: Jeff Hill * Date: 3-27-90 * - * Control System Software for the GTA Project - * - * Copyright 1988, 1989, the Regents of the University of California. - * - * This software was produced under a U.S. Government contract - * (W-7405-ENG-36) at the Los Alamos National Laboratory, which is - * operated by the University of California for the U.S. Department - * of Energy. - * - * Developed by the Controls and Automation Group (AT-8) - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Direct inqueries to: - * Jeff HIll, AT-8, Mail Stop H820 - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * Phone: (505) 665-1831 - * E-mail: johill@lanl.gov - * * PURPOSE: * Broadcasts fan out over the LAN, but old IP kernels do not allow * two processes on the same machine to get the same broadcast @@ -108,23 +87,24 @@ static const unsigned short PORT_ANY = 0u; /* * makeSocket() */ -static bool makeSocket ( unsigned short port, bool reuseAddr, SOCKET * pSock ) +static int makeSocket ( unsigned short port, bool reuseAddr, SOCKET * pSock ) { - int status; - union { - struct sockaddr_in ia; - struct sockaddr sa; - } bd; - SOCKET sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, 0 ); + if ( sock == INVALID_SOCKET ) { - return false; + *pSock = sock; + return SOCKERRNO; } /* * no need to bind if unconstrained */ if ( port != PORT_ANY ) { + int status; + union { + struct sockaddr_in ia; + struct sockaddr sa; + } bd; memset ( (char *) &bd, 0, sizeof (bd) ); bd.ia.sin_family = AF_INET; @@ -132,15 +112,16 @@ static bool makeSocket ( unsigned short port, bool reuseAddr, SOCKET * pSock ) bd.ia.sin_port = htons ( port ); status = bind ( sock, &bd.sa, (int) sizeof(bd) ); if ( status < 0 ) { + status = SOCKERRNO; epicsSocketDestroy ( sock ); - return false; + return status; } if ( reuseAddr ) { epicsSocketEnableAddressReuseDuringTimeWaitState ( sock ); } } *pSock = sock; - return true; + return 0; } repeaterClient::repeaterClient ( const osiSockAddr &fromIn ) : @@ -156,10 +137,10 @@ bool repeaterClient::connect () { int status; - if ( ! makeSocket ( PORT_ANY, false, & this->sock ) ) { + if ( int sockerrno = makeSocket ( PORT_ANY, false, & this->sock ) ) { char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( - sockErrBuf, sizeof ( sockErrBuf ) ); + epicsSocketConvertErrorToString ( + sockErrBuf, sizeof ( sockErrBuf ), sockerrno ); fprintf ( stderr, "%s: no client sock because \"%s\"\n", __FILE__, sockErrBuf ); return false; @@ -300,20 +281,25 @@ inline bool repeaterClient::identicalPort ( const osiSockAddr &fromIn ) bool repeaterClient::verify () { SOCKET tmpSock; - bool success = makeSocket ( this->port (), false, & tmpSock ); - if ( success ) { + int sockerrno = makeSocket ( this->port (), false, & tmpSock ); + + if ( sockerrno == SOCK_EADDRINUSE ) { + // Normal result, client using port + return true; + } + + if ( sockerrno == 0 ) { + // Client went away, released port epicsSocketDestroy ( tmpSock ); } else { - if ( SOCKERRNO != SOCK_EADDRINUSE ) { - char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( - sockErrBuf, sizeof ( sockErrBuf ) ); - fprintf ( stderr, "CA Repeater: bind test err was \"%s\"\n", - sockErrBuf ); - } + char sockErrBuf[64]; + epicsSocketConvertErrorToString ( + sockErrBuf, sizeof ( sockErrBuf ), sockerrno ); + fprintf ( stderr, "CA Repeater: Bind test error \"%s\"\n", + sockErrBuf ); } - return ! success; + return false; } @@ -387,10 +373,10 @@ static void register_new_client ( osiSockAddr & from, if ( ! init ) { SOCKET sock; - if ( ! makeSocket ( PORT_ANY, true, & sock ) ) { + if ( int sockerrno = makeSocket ( PORT_ANY, true, & sock ) ) { char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( - sockErrBuf, sizeof ( sockErrBuf ) ); + epicsSocketConvertErrorToString ( + sockErrBuf, sizeof ( sockErrBuf ), sockerrno ); fprintf ( stderr, "%s: Unable to create repeater bind test socket because \"%s\"\n", __FILE__, sockErrBuf ); } @@ -511,18 +497,18 @@ void ca_repeater () port = envGetInetPortConfigParam ( & EPICS_CA_REPEATER_PORT, static_cast(CA_REPEATER_PORT) ); - if ( ! makeSocket ( port, true, & sock ) ) { + if ( int sockerrno = makeSocket ( port, true, & sock ) ) { /* * test for server was already started */ - if ( SOCKERRNO == SOCK_EADDRINUSE ) { + if ( sockerrno == SOCK_EADDRINUSE ) { osiSockRelease (); debugPrintf ( ( "CA Repeater: exiting because a repeater is already running\n" ) ); return; } char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( - sockErrBuf, sizeof ( sockErrBuf ) ); + epicsSocketConvertErrorToString ( + sockErrBuf, sizeof ( sockErrBuf ), sockerrno ); fprintf ( stderr, "%s: Unable to create repeater socket because \"%s\" - fatal\n", __FILE__, sockErrBuf ); osiSockRelease (); diff --git a/src/ca/client/tools/tool_lib.c b/src/ca/client/tools/tool_lib.c index f47cfb383..8b9c5ca28 100644 --- a/src/ca/client/tools/tool_lib.c +++ b/src/ca/client/tools/tool_lib.c @@ -59,28 +59,33 @@ capri caPriority = DEFAULT_CA_PRIORITY; /* CA Priority */ -void sprint_long (char *ret, long val, IntFormatT outType) +static void sprint_long (char *ret, dbr_long_t val, IntFormatT outType) { - long i, bit, skip=-1L; /* used only for printing bits */ - switch (outType) { - case hex: sprintf(ret, "0x%lX", val); break; - case oct: sprintf(ret, "0o%lo", val); break; - case bin: - for (i=31; i>=0 ; i--) - { - bit = (val>>i) & 0x1L; - if (skip<0 && bit) - { + if (outType == bin && val != 0) { + /* sprintf doesn't do binary; this code doesn't handle 0 */ + int i, skip = -1; + + for (i = 31; i >= 0; i--) { + int bit = (val >> i) & 1; + + if (skip < 0 && bit) { skip = 31 - i; /* skip leading 0's */ ret[i+1] = '\0'; } - if (skip >= 0) - { - ret[31-i-skip] = (bit) ? '1' : '0'; + if (skip >= 0) { + ret[31-i-skip] = '0' + bit; } } - break; - default: sprintf(ret, "%ld", val); /* decimal */ + } + else { + const char *fmt[4] = { /* Order must match the enum IntFormatT */ + "%ld" /* dec */, + "0" /* bin, val is 0 */, + "0o%lo" /* oct */, + "0x%lX" /* hex */ + }; + + sprintf(ret, fmt[outType], val); } } @@ -113,6 +118,7 @@ char *val2str (const void *v, unsigned type, int index) strcpy (str, "*** invalid type"); return str; } + strcpy (str, "!!!"); base_type = type % (LAST_TYPE+1); diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c index 5b5854f6c..b13d7a138 100644 --- a/src/ioc/db/dbAccess.c +++ b/src/ioc/db/dbAccess.c @@ -739,6 +739,11 @@ static long getLinkValue(DBADDR *paddr, short dbrType, if (nRequest && *nRequest > 1) *nRequest = 1; break; + case DBR_DOUBLE: /* Needed for dbCa links */ + if (nRequest && *nRequest) *nRequest = 1; + *(double *)pbuf = epicsNAN; + return 0; + case DBR_CHAR: case DBR_UCHAR: if (nRequest && *nRequest > 0) { diff --git a/src/ioc/db/dbCa.c b/src/ioc/db/dbCa.c index f6422873b..1ae5a8026 100644 --- a/src/ioc/db/dbCa.c +++ b/src/ioc/db/dbCa.c @@ -425,7 +425,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType, plink->value.pv_link.pvlMask |= pvlOptOutNative; */ } - if (nRequest == 1){ + if (nRequest == 1 && pca->nelements==1){ long (*fConvert)(const void *from, void *to, struct dbAddr *paddr); fConvert = dbFastPutConvertRoutine[dbrType][newType]; @@ -439,7 +439,13 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType, dbAddr.pfield = pca->pputNative; /*Following only used for DBF_STRING*/ dbAddr.field_size = MAX_STRING_SIZE; + if(nRequest>pca->nelements) + nRequest = pca->nelements; status = aConvert(&dbAddr, pbuffer, nRequest, pca->nelements, 0); + if(nRequest nelements) { + long elemsize = dbr_value_size[ca_field_type(pca->chid)]; + memset(nRequest*elemsize+(char*)pca->pputNative, 0, (pca->nelements-nRequest)*elemsize); + } } link_action |= CA_WRITE_NATIVE; pca->gotOutNative = TRUE; diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index f1bdbf33e..c51f1a119 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -14,7 +14,7 @@ TESTLIBRARY = dbTestIoc dbTestIoc_SRCS += xRecord.c dbTestIoc_SRCS += dbLinkdset.c -dbTestIoc_LIBS = dbCore +dbTestIoc_LIBS = dbCore ca Com TARGETS += $(COMMON_DIR)/dbTestIoc.dbd dbTestIoc_DBD += menuGlobal.dbd diff --git a/src/ioc/dbStatic/dbStaticLib.c b/src/ioc/dbStatic/dbStaticLib.c index 9f13c8803..45dbda411 100644 --- a/src/ioc/dbStatic/dbStaticLib.c +++ b/src/ioc/dbStatic/dbStaticLib.c @@ -50,7 +50,7 @@ int dbStaticDebug = 0; static char *pNullString = ""; #define messagesize 100 -#define RPCL_LEN 184 +#define RPCL_LEN INFIX_TO_POSTFIX_SIZE(80) static char *ppstring[5]={"NPP","PP","CA","CP","CPP"}; static char *msstring[4]={"NMS","MS","MSI","MSS"}; diff --git a/src/ioc/dbStatic/dbYacc.y b/src/ioc/dbStatic/dbYacc.y index 858e666d3..0f0c757fe 100644 --- a/src/ioc/dbStatic/dbYacc.y +++ b/src/ioc/dbStatic/dbYacc.y @@ -271,12 +271,14 @@ alias: tokenALIAS '(' tokenSTRING ',' tokenSTRING ')' static int yyerror(char *str) { if (str) - epicsPrintf("Error: %s\n ", str); + epicsPrintf("Error: %s\n", str); else epicsPrintf("Error"); - epicsPrintf(" at or before \"%s\"", yytext); - dbIncludePrint(); - yyFailed = TRUE; + if (!yyFailed) { /* Only print this stuff once */ + epicsPrintf(" at or before \"%s\"", yytext); + dbIncludePrint(); + yyFailed = TRUE; + } return(0); } static long pvt_yy_parse(void) diff --git a/src/ioc/rsrv/camessage.c b/src/ioc/rsrv/camessage.c index f9f0bbc6f..6ade766ed 100644 --- a/src/ioc/rsrv/camessage.c +++ b/src/ioc/rsrv/camessage.c @@ -284,21 +284,18 @@ static void log_header ( pciu = MPTOPCIU(mp); if (pContext) { - epicsPrintf ("CAS: request from %s => \"%s\"\n", + epicsPrintf ("CAS: request from %s => %s\n", hostName, pContext); } - epicsPrintf ( -"CAS: Request from %s => cmmd=%d cid=0x%x type=%d count=%d postsize=%u\n", + epicsPrintf ( "CAS: Request from %s => cmmd=%d cid=0x%x type=%d count=%d postsize=%u\n", hostName, mp->m_cmmd, mp->m_cid, mp->m_dataType, mp->m_count, mp->m_postsize); - epicsPrintf ( -"CAS: Request from %s => available=0x%x \tN=%u dbch=%p\n", - hostName, mp->m_available, mnum, (pciu?(void *)&pciu->dbch:NULL)); + epicsPrintf ( "CAS: Request from %s => available=0x%x \tN=%u paddr=%p\n", + hostName, mp->m_available, mnum, (pciu ? (void *)&pciu->dbch : NULL)); if (mp->m_cmmd==CA_PROTO_WRITE && mp->m_dataType==DBF_STRING && pPayLoad ) { - epicsPrintf ( -"CAS: Request from %s => \tThe string written: %s \n", + epicsPrintf ( "CAS: Request from %s => Wrote string \"%s\"\n", hostName, (char *)pPayLoad ); } } @@ -854,10 +851,10 @@ static int write_action ( caHdrLargeArray *mp, return RSRV_ERROR; } - asWritePvt = asTrapWriteBefore ( pciu->asClientPVT, + asWritePvt = asTrapWriteWithData ( pciu->asClientPVT, pciu->client->pUserName ? pciu->client->pUserName : "", pciu->client->pHostName ? pciu->client->pHostName : "", - pciu->dbch ); + pciu->dbch, mp->m_dataType, mp->m_count, pPayload ); dbStatus = dbChannel_put( pciu->dbch, @@ -1881,11 +1878,12 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload, pciu->pPutNotify->dbrType = mp->m_dataType; - pciu->pPutNotify->asWritePvt = asTrapWriteBefore ( + pciu->pPutNotify->asWritePvt = asTrapWriteWithData ( pciu->asClientPVT, pciu->client->pUserName ? pciu->client->pUserName : "", pciu->client->pHostName ? pciu->client->pHostName : "", - pciu->dbch ); + pciu->dbch, mp->m_dataType, mp->m_count, + pciu->pPutNotify->pbuffer ); dbProcessNotify(&pciu->pPutNotify->dbPutNotify); diff --git a/src/ioc/rsrv/camsgtask.c b/src/ioc/rsrv/camsgtask.c index 4eedfc428..65d37c9a9 100644 --- a/src/ioc/rsrv/camsgtask.c +++ b/src/ioc/rsrv/camsgtask.c @@ -68,9 +68,10 @@ void camsgtask ( void *pParm ) status = socket_ioctl (client->sock, FIONREAD, &nchars); if (status < 0) { char sockErrBuf[64]; + epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - errlogPrintf("CAS: io ctl err - %s\n", + errlogPrintf("CAS: ioctl error - %s\n", sockErrBuf); cas_send_bs_msg(client, TRUE); } @@ -99,9 +100,8 @@ void camsgtask ( void *pParm ) } if ( anerrno == SOCK_ENOBUFS ) { - errlogPrintf ( - "rsrv: system low on network buffers " - "- receive retry in 15 seconds\n" ); + errlogPrintf ( + "CAS: Out of network buffers, retring receive in 15 seconds\n" ); epicsThreadSleep ( 15.0 ); continue; } @@ -110,10 +110,15 @@ void camsgtask ( void *pParm ) * normal conn lost conditions */ if ( ( anerrno != SOCK_ECONNABORTED && - anerrno != SOCK_ECONNRESET && - anerrno != SOCK_ETIMEDOUT ) || - CASDEBUG > 2 ) { - errlogPrintf ( "CAS: client disconnect(errno=%d)\n", anerrno ); + anerrno != SOCK_ECONNRESET && + anerrno != SOCK_ETIMEDOUT ) || + CASDEBUG > 2 ) { + char sockErrBuf[64]; + + epicsSocketConvertErrorToString( + sockErrBuf, sizeof ( sockErrBuf ), anerrno); + errlogPrintf ( "CAS: Client disconnected - %s\n", + sockErrBuf ); } break; } diff --git a/src/ioc/rsrv/caserverio.c b/src/ioc/rsrv/caserverio.c index 91cb5e2c6..c5865d91d 100644 --- a/src/ioc/rsrv/caserverio.c +++ b/src/ioc/rsrv/caserverio.c @@ -90,7 +90,8 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed ) } if ( anerrno == SOCK_ENOBUFS ) { - errlogPrintf ( "rsrv: system low on network buffers - send retry in 15 seconds\n" ); + errlogPrintf ( + "CAS: Out of network buffers, retrying send in 15 seconds\n" ); epicsThreadSleep ( 15.0 ); continue; } @@ -108,8 +109,7 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed ) char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - errlogPrintf ( - "CAS: TCP send to \"%s\" failed because \"%s\"\n", + errlogPrintf ( "CAS: TCP send to %s failed - %s\n", buf, sockErrBuf); } pclient->disconnect = TRUE; @@ -135,7 +135,7 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed ) char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - errlogPrintf ("rsrv: socket shutdown error was %s\n", + errlogPrintf ("CAS: Socket shutdown error - %s\n", sockErrBuf ); } } @@ -204,7 +204,7 @@ void cas_send_dg_msg ( struct client * pclient ) } else { errlogPrintf ( - "cas: system failed to send entire udp frame?\n" ); + "CAS: System failed to send entire udp frame?\n" ); } } else { @@ -213,11 +213,8 @@ void cas_send_dg_msg ( struct client * pclient ) epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); ipAddrToDottedIP ( &pclient->addr, buf, sizeof(buf) ); - errlogPrintf( - "CAS: UDP send to \"%s\" " - "failed because \"%s\"\n", - buf, - sockErrBuf); + errlogPrintf( "CAS: UDP send to %s failed - %s\n", + buf, sockErrBuf); } pclient->send.stk = 0u; diff --git a/src/ioc/rsrv/caservertask.c b/src/ioc/rsrv/caservertask.c index 00095eaf1..132fe462f 100644 --- a/src/ioc/rsrv/caservertask.c +++ b/src/ioc/rsrv/caservertask.c @@ -276,7 +276,7 @@ int rsrv_init (void) status = envGetLongConfigParam ( &EPICS_CA_MAX_ARRAY_BYTES, &maxBytesAsALong ); if ( status || maxBytesAsALong < 0 ) { - errlogPrintf ( "cas: EPICS_CA_MAX_ARRAY_BYTES was not a positive integer\n" ); + errlogPrintf ( "CAS: EPICS_CA_MAX_ARRAY_BYTES was not a positive integer\n" ); rsrvSizeofLargeBufTCP = MAX_TCP; } else { @@ -290,7 +290,7 @@ int rsrv_init (void) maxBytes = 0xffffffff; } if ( maxBytes < MAX_TCP ) { - errlogPrintf ( "cas: EPICS_CA_MAX_ARRAY_BYTES was rounded up to %u\n", MAX_TCP ); + errlogPrintf ( "CAS: EPICS_CA_MAX_ARRAY_BYTES was rounded up to %u\n", MAX_TCP ); rsrvSizeofLargeBufTCP = MAX_TCP; } else { @@ -571,7 +571,7 @@ void destroy_client ( struct client *client ) freeListFree ( rsrvLargeBufFreeListTCP, client->send.buf ); } else { - errlogPrintf ( "cas: Corrupt send buffer free list type code=%u during client cleanup?\n", + errlogPrintf ( "CAS: Corrupt send buffer free list type code=%u during client cleanup?\n", client->send.type ); } } @@ -583,7 +583,7 @@ void destroy_client ( struct client *client ) freeListFree ( rsrvLargeBufFreeListTCP, client->recv.buf ); } else { - errlogPrintf ( "cas: Corrupt recv buffer free list type code=%u during client cleanup?\n", + errlogPrintf ( "CAS: Corrupt recv buffer free list type code=%u during client cleanup?\n", client->send.type ); } } diff --git a/src/libCom/as/asLib.h b/src/libCom/as/asLib.h index af8e0dc30..95fed7a9a 100644 --- a/src/libCom/as/asLib.h +++ b/src/libCom/as/asLib.h @@ -30,25 +30,38 @@ typedef enum{ } asClientStatus; typedef void (*ASCLIENTCALLBACK) (ASCLIENTPVT,asClientStatus); + /* The following routines are macros with the following syntax long asCheckGet(ASCLIENTPVT asClientPvt); long asCheckPut(ASCLIENTPVT asClientPvt); */ -#define asCheckGet(asClientPvt)\ - (asActive \ - ? ((asClientPvt)->access>=asREAD ? TRUE : FALSE)\ - : TRUE) -#define asCheckPut(asClientPvt)\ - (asActive \ - ? ((asClientPvt)->access>=asWRITE ? TRUE : FALSE)\ - : TRUE) -#define asTrapWriteBefore(asClientPvt,user,host,addr) \ - (((asActive) && (asClientPvt)->trapMask) \ - ? asTrapWriteBeforeWrite((user),(host),(addr)) \ - : 0) +#define asCheckGet(asClientPvt) \ + (!asActive || ((asClientPvt)->access >= asREAD)) +#define asCheckPut(asClientPvt) \ + (!asActive || ((asClientPvt)->access >= asWRITE)) + +/* More convenience macros +void *asTrapWriteWithData(ASCLIENTPVT asClientPvt, + const char *userid, const char *hostid, void *addr, + int dbrType, int no_elements, void *data); +void asTrapWriteAfter(ASCLIENTPVT asClientPvt); +*/ +#define asTrapWriteWithData(asClientPvt, user, host, addr, type, count, data) \ + ((asActive && (asClientPvt)->trapMask) \ + ? asTrapWriteBeforeWithData((user), (host), (addr), (type), (count), (data)) \ + : 0) +#define asTrapWriteAfter(pvt) \ + if (pvt) asTrapWriteAfterWrite(pvt) + +/* This macro is for backwards compatibility, upgrade any code + calling it to use asTrapWriteWithData() instead ASAP: +void *asTrapWriteBefore(ASCLIENTPVT asClientPvt, + const char *userid, const char *hostid, void *addr); +*/ +#define asTrapWriteBefore(asClientPvt, user, host, addr) \ + asTrapWriteWithData(asClientPvt, user, host, addr, 0, 0, NULL) + -#define asTrapWriteAfter(pvt) if((pvt)) asTrapWriteAfterWrite((pvt)) - epicsShareFunc long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction); epicsShareFunc long epicsShareAPI asInitFile( const char *filename,const char *substitutions); @@ -100,8 +113,9 @@ epicsShareFunc int epicsShareAPI asDumpMemFP(FILE *fp,const char *asgname, epicsShareFunc int epicsShareAPI asDumpHash(void); epicsShareFunc int epicsShareAPI asDumpHashFP(FILE *fp); -epicsShareFunc void * epicsShareAPI asTrapWriteBeforeWrite( - const char *userid,const char *hostid,void *addr); +epicsShareFunc void * epicsShareAPI asTrapWriteBeforeWithData( + const char *userid, const char *hostid, void *addr, + int dbrType, int no_elements, void *data); epicsShareFunc void epicsShareAPI asTrapWriteAfterWrite(void *pvt); diff --git a/src/libCom/as/asTrapWrite.c b/src/libCom/as/asTrapWrite.c index 9aa795262..544e9a211 100644 --- a/src/libCom/as/asTrapWrite.c +++ b/src/libCom/as/asTrapWrite.c @@ -3,8 +3,7 @@ * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /*asTrapWrite.c */ @@ -101,47 +100,53 @@ void epicsShareAPI asTrapWriteUnregisterListener(asTrapWriteId id) = (listenerPvt *)ellNext(&plistenerPvt->node); if(plistenerPvt->plistener == plistener) { ellDelete(&pwriteMessage->listenerPvtList,&plistenerPvt->node); - freeListFree(pasTrapWritePvt->freeListListenerPvt,(void *)plistenerPvt); + freeListFree(pasTrapWritePvt->freeListListenerPvt, plistenerPvt); } plistenerPvt = pnext; } pwriteMessage = (writeMessage *)ellNext(&pwriteMessage->node); } ellDelete(&pasTrapWritePvt->listenerList,&plistener->node); - free((void *)plistener); + free(plistener); epicsMutexUnlock(pasTrapWritePvt->lock); } -void * epicsShareAPI asTrapWriteBeforeWrite( - const char *userid,const char *hostid,void *addr) +void * epicsShareAPI asTrapWriteBeforeWithData( + const char *userid, const char *hostid, void *addr, + int dbrType, int no_elements, void *data) { writeMessage *pwriteMessage; listener *plistener; - listenerPvt *plistenerPvt; - if(pasTrapWritePvt==0) return(0); - if(ellCount(&pasTrapWritePvt->listenerList)<=0) return 0; + if (pasTrapWritePvt == 0 || + ellCount(&pasTrapWritePvt->listenerList) <= 0) return 0; + pwriteMessage = (writeMessage *)freeListCalloc( pasTrapWritePvt->freeListWriteMessage); pwriteMessage->message.userid = userid; pwriteMessage->message.hostid = hostid; pwriteMessage->message.serverSpecific = addr; + pwriteMessage->message.dbrType = dbrType; + pwriteMessage->message.no_elements = no_elements; + pwriteMessage->message.data = data; ellInit(&pwriteMessage->listenerPvtList); + epicsMutexMustLock(pasTrapWritePvt->lock); - ellAdd(&pasTrapWritePvt->writeMessageList,&pwriteMessage->node); + ellAdd(&pasTrapWritePvt->writeMessageList, &pwriteMessage->node); plistener = (listener *)ellFirst(&pasTrapWritePvt->listenerList); - while(plistener) { - plistenerPvt = (listenerPvt *)freeListCalloc( + while (plistener) { + listenerPvt *plistenerPvt = (listenerPvt *)freeListCalloc( pasTrapWritePvt->freeListListenerPvt); + plistenerPvt->plistener = plistener; pwriteMessage->message.userPvt = 0; - (*plistener->func)(&pwriteMessage->message,0); + plistener->func(&pwriteMessage->message, 0); plistenerPvt->userPvt = pwriteMessage->message.userPvt; - ellAdd(&pwriteMessage->listenerPvtList,&plistenerPvt->node); + ellAdd(&pwriteMessage->listenerPvtList, &plistenerPvt->node); plistener = (listener *)ellNext(&plistener->node); } epicsMutexUnlock(pasTrapWritePvt->lock); - return((void *)pwriteMessage); + return pwriteMessage; } void epicsShareAPI asTrapWriteAfterWrite(void *pvt) @@ -149,20 +154,22 @@ void epicsShareAPI asTrapWriteAfterWrite(void *pvt) writeMessage *pwriteMessage = (writeMessage *)pvt; listenerPvt *plistenerPvt; - if(pwriteMessage==0 || pasTrapWritePvt==0) return; + if (pwriteMessage == 0 || + pasTrapWritePvt == 0) return; + epicsMutexMustLock(pasTrapWritePvt->lock); plistenerPvt = (listenerPvt *)ellFirst(&pwriteMessage->listenerPvtList); - while(plistenerPvt) { + while (plistenerPvt) { listenerPvt *pnext = (listenerPvt *)ellNext(&plistenerPvt->node); - listener *plistener; - plistener = plistenerPvt->plistener; + listener *plistener = plistenerPvt->plistener; + pwriteMessage->message.userPvt = plistenerPvt->userPvt; - (*plistener->func)(&pwriteMessage->message,1); - ellDelete(&pwriteMessage->listenerPvtList,&plistenerPvt->node); - freeListFree(pasTrapWritePvt->freeListListenerPvt,(void *)plistenerPvt); + plistener->func(&pwriteMessage->message, 1); + ellDelete(&pwriteMessage->listenerPvtList, &plistenerPvt->node); + freeListFree(pasTrapWritePvt->freeListListenerPvt, plistenerPvt); plistenerPvt = pnext; } - ellDelete(&pasTrapWritePvt->writeMessageList,&pwriteMessage->node); - freeListFree(pasTrapWritePvt->freeListWriteMessage,(void *)pwriteMessage); + ellDelete(&pasTrapWritePvt->writeMessageList, &pwriteMessage->node); + freeListFree(pasTrapWritePvt->freeListWriteMessage, pwriteMessage); epicsMutexUnlock(pasTrapWritePvt->lock); } diff --git a/src/libCom/as/asTrapWrite.h b/src/libCom/as/asTrapWrite.h index ec34c5312..b8033cb94 100644 --- a/src/libCom/as/asTrapWrite.h +++ b/src/libCom/as/asTrapWrite.h @@ -3,9 +3,8 @@ * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /*asTrapWrite.h*/ /* Author: Marty Kraimer Date: 07NOV2000 */ @@ -24,6 +23,9 @@ typedef struct asTrapWriteMessage { const char *hostid; void *serverSpecific; void *userPvt; + int dbrType; /* Data type from ca/db_access.h, NOT dbFldTypes.h */ + int no_elements; + void *data; /* Might be NULL if no data is available */ } asTrapWriteMessage; diff --git a/src/libCom/cxxTemplates/epicsSingleton.h b/src/libCom/cxxTemplates/epicsSingleton.h index b97c82b8c..cece8007c 100644 --- a/src/libCom/cxxTemplates/epicsSingleton.h +++ b/src/libCom/cxxTemplates/epicsSingleton.h @@ -19,6 +19,7 @@ #define epicsSingleton_h #include +#include #include "shareLib.h" #include "epicsAssert.h" diff --git a/src/libCom/misc/epicsString.c b/src/libCom/misc/epicsString.c index de38005b4..7a63580a2 100644 --- a/src/libCom/misc/epicsString.c +++ b/src/libCom/misc/epicsString.c @@ -100,7 +100,7 @@ int epicsStrnRawFromEscaped(char *dst, size_t dstlen, const char *src, { /* \xXXX... */ unsigned int u = 0; - if (!srclen-- || !(c = *src++)) + if (!srclen-- || !(c = *src++ & 0xff)) goto done; while (isxdigit(c)) { @@ -108,7 +108,7 @@ int epicsStrnRawFromEscaped(char *dst, size_t dstlen, const char *src, if (u > 0xff) { /* Undefined behaviour! */ } - if (!srclen-- || !(c = *src++)) { + if (!srclen-- || !(c = *src++ & 0xff)) { OUT(u); goto done; } @@ -153,7 +153,7 @@ int epicsStrnEscapedFromRaw(char *dst, size_t dstlen, const char *src, case '\'': OUT('\\'); OUT('\''); break; case '\"': OUT('\\'); OUT('\"'); break; default: - if (isprint(c)) { + if (isprint(c & 0xff)) { OUT(c); break; } @@ -183,7 +183,7 @@ size_t epicsStrnEscapedFromRawSize(const char *src, size_t srclen) ndst++; break; default: - if (!isprint(c)) + if (!isprint(c & 0xff)) ndst += 3; } } @@ -247,7 +247,7 @@ int epicsStrPrintEscaped(FILE *fp, const char *s, size_t len) case '\'': nout += fprintf(fp, "\\'"); break; case '\"': nout += fprintf(fp, "\\\""); break; default: - if (isprint((int)c)) + if (isprint(0xff & (int)c)) nout += fprintf(fp, "%c", c); else nout += fprintf(fp, "\\%03o", (unsigned char)c); diff --git a/src/libCom/osi/compiler/clang/compilerSpecific.h b/src/libCom/osi/compiler/clang/compilerSpecific.h index 482ee513e..9871fcf7d 100644 --- a/src/libCom/osi/compiler/clang/compilerSpecific.h +++ b/src/libCom/osi/compiler/clang/compilerSpecific.h @@ -20,6 +20,12 @@ # error compiler/clang/compilerSpecific.h is only for use with the clang compiler #endif +#if __has_attribute(always_inline) +#define EPICS_ALWAYS_INLINE __inline__ __attribute__((always_inline)) +#else +#define EPICS_ALWAYS_INLINE __inline__ +#endif + #ifdef __cplusplus /* diff --git a/src/libCom/osi/compiler/clang/epicsAtomicCD.h b/src/libCom/osi/compiler/clang/epicsAtomicCD.h index 00fa24e4b..763cb0537 100644 --- a/src/libCom/osi/compiler/clang/epicsAtomicCD.h +++ b/src/libCom/osi/compiler/clang/epicsAtomicCD.h @@ -16,16 +16,8 @@ #ifndef epicsAtomicCD_h #define epicsAtomicCD_h -#if defined ( __cplusplus ) -# define EPICS_ATOMIC_INLINE inline -#else -# define EPICS_ATOMIC_INLINE __inline__ -#endif +#define EPICS_ATOMIC_CMPLR_NAME "CLANG" -/* - * we have an inline keyword so we can proceed - * with an os specific inline instantiation - */ #include "epicsAtomicOSD.h" #endif /* epicsAtomicCD_h */ diff --git a/src/libCom/osi/compiler/default/compilerSpecific.h b/src/libCom/osi/compiler/default/compilerSpecific.h index f2a3f8c36..8af1727c5 100644 --- a/src/libCom/osi/compiler/default/compilerSpecific.h +++ b/src/libCom/osi/compiler/default/compilerSpecific.h @@ -15,6 +15,14 @@ #ifndef compilerSpecific_h #define compilerSpecific_h + +/* The 'inline' key work, possibily with compiler + * dependent flags to force inlineing where it would + * otherwise not be done. + * + * Warning: Second guessing the compiler may result in larger code size + */ +#define EPICS_ALWAYS_INLINE inline #ifdef __cplusplus diff --git a/src/libCom/osi/compiler/default/epicsAtomicCD.h b/src/libCom/osi/compiler/default/epicsAtomicCD.h index 3ca260759..585a39c97 100644 --- a/src/libCom/osi/compiler/default/epicsAtomicCD.h +++ b/src/libCom/osi/compiler/default/epicsAtomicCD.h @@ -16,15 +16,8 @@ #ifndef epicsAtomicCD_h #define epicsAtomicCD_h -#if __STDC_VERSION__ >= 199901L || defined ( __cplusplus ) -# define EPICS_ATOMIC_INLINE inline - /* - * We have already defined the public interface in epicsAtomic.h - * so there is nothing more to implement if there isnt an inline - * keyword available. Otherwise, if we have an inline keyword - * we will proceed with an os specific inline implementation. - */ -# include "epicsAtomicOSD.h" -#endif +#define EPICS_ATOMIC_CMPLR_NAME "DEFAULT" + +#include "epicsAtomicOSD.h" #endif /* epicsAtomicCD_h */ diff --git a/src/libCom/osi/compiler/gcc/compilerSpecific.h b/src/libCom/osi/compiler/gcc/compilerSpecific.h index 6696c7a89..ca46a9348 100644 --- a/src/libCom/osi/compiler/gcc/compilerSpecific.h +++ b/src/libCom/osi/compiler/gcc/compilerSpecific.h @@ -23,6 +23,12 @@ #ifdef __clang__ # error compiler/gcc/compilerSpecific.h is not for use with the clang compiler #endif + +#if __GNUC__ > 2 +# define EPICS_ALWAYS_INLINE __inline__ __attribute__((always_inline)) +#else +# define EPICS_ALWAYS_INLINE __inline__ +#endif #ifdef __cplusplus diff --git a/src/libCom/osi/compiler/gcc/epicsAtomicCD.h b/src/libCom/osi/compiler/gcc/epicsAtomicCD.h index e3989769f..15b9a6c9a 100644 --- a/src/libCom/osi/compiler/gcc/epicsAtomicCD.h +++ b/src/libCom/osi/compiler/gcc/epicsAtomicCD.h @@ -20,7 +20,7 @@ # error this header is only for use with the gnu compiler #endif -#define EPICS_ATOMIC_INLINE __inline__ +#define EPICS_ATOMIC_CMPLR_NAME "GCC" #define GCC_ATOMIC_CONCAT( A, B ) GCC_ATOMIC_CONCATR(A,B) #define GCC_ATOMIC_CONCATR( A, B ) ( A ## B ) @@ -69,7 +69,7 @@ extern "C" { #ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER #define EPICS_ATOMIC_READ_MEMORY_BARRIER -EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void) { __sync_synchronize (); } @@ -77,7 +77,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () #ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER #define EPICS_ATOMIC_WRITE_MEMORY_BARRIER -EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void) { __sync_synchronize (); } @@ -88,7 +88,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () #ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER #if GCC_ATOMIC_INTRINSICS_MIN_X86 #define EPICS_ATOMIC_READ_MEMORY_BARRIER -EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void) { asm("mfence;"); } @@ -98,7 +98,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () #ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER #if GCC_ATOMIC_INTRINSICS_MIN_X86 #define EPICS_ATOMIC_WRITE_MEMORY_BARRIER -EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void) { asm("mfence;"); } diff --git a/src/libCom/osi/compiler/msvc/compilerSpecific.h b/src/libCom/osi/compiler/msvc/compilerSpecific.h index 587d534c7..49cf266ae 100644 --- a/src/libCom/osi/compiler/msvc/compilerSpecific.h +++ b/src/libCom/osi/compiler/msvc/compilerSpecific.h @@ -20,6 +20,12 @@ # error compiler/msvc/compilerSpecific.h is only for use with the Microsoft compiler #endif +#if _MSC_VER >= 1200 +#define EPICS_ALWAYS_INLINE __forceinline +#else +#define EPICS_ALWAYS_INLINE __inline +#endif + #ifdef __cplusplus /* diff --git a/src/libCom/osi/compiler/msvc/epicsAtomicCD.h b/src/libCom/osi/compiler/msvc/epicsAtomicCD.h index f834f0405..e7d1c4b77 100644 --- a/src/libCom/osi/compiler/msvc/epicsAtomicCD.h +++ b/src/libCom/osi/compiler/msvc/epicsAtomicCD.h @@ -24,18 +24,14 @@ #ifdef _MSC_EXTENSIONS -#include +#define EPICS_ATOMIC_CMPLR_NAME "MSVC-INTRINSIC" -#if _MSC_VER >= 1200 -# define EPICS_ATOMIC_INLINE __forceinline -#else -# define EPICS_ATOMIC_INLINE __inline -#endif +#include #if defined ( _M_IX86 ) # pragma warning( push ) # pragma warning( disable : 4793 ) - EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier () + EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier (void) { long fence; __asm { xchg fence, eax } @@ -44,14 +40,14 @@ #elif defined ( _M_X64 ) # define MS_ATOMIC_64 # pragma intrinsic ( __faststorefence ) - EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier () + EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier (void) { __faststorefence (); } #elif defined ( _M_IA64 ) # define MS_ATOMIC_64 # pragma intrinsic ( __mf ) - EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier () + EPICS_ATOMIC_INLINE void epicsAtomicMemoryBarrier (void) { __mf (); } @@ -88,13 +84,13 @@ extern "C" { #endif /* __cplusplus */ #define EPICS_ATOMIC_READ_MEMORY_BARRIER -EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void) { epicsAtomicMemoryBarrier (); } #define EPICS_ATOMIC_WRITE_MEMORY_BARRIER -EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void) { epicsAtomicMemoryBarrier (); } @@ -108,9 +104,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () #else /* ifdef _MSC_EXTENSIONS */ -#if defined ( __cplusplus ) -# define EPICS_ATOMIC_INLINE inline -#endif +#define EPICS_ATOMIC_CMPLR_NAME "MSVC-DIRECT" /* * if unavailable as an intrinsic we will try diff --git a/src/libCom/osi/compiler/solStudio/compilerSpecific.h b/src/libCom/osi/compiler/solStudio/compilerSpecific.h new file mode 100644 index 000000000..a9d59a5bf --- /dev/null +++ b/src/libCom/osi/compiler/solStudio/compilerSpecific.h @@ -0,0 +1,44 @@ +/*************************************************************************\ +* Copyright (c) 2008 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. +\*************************************************************************/ + +/* + * Author: + * Jeffrey O. Hill + * johill@lanl.gov + */ + +#ifndef compilerSpecific_h +#define compilerSpecific_h + +#if !defined(__SUNPRO_C) && !defined (__SUNPRO_CC) +# error Not Solaris Studio +#endif + +#if (defined(__SUNPRO_C) && __SUNPRO_C < 0x590) || \ + (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) +# define EPICS_ALWAYS_INLINE inline +#else +# define EPICS_ALWAYS_INLINE inline __attribute__((always_inline)) +#endif + +#ifdef __cplusplus + +/* + * CXX_PLACEMENT_DELETE - defined if compiler supports placement delete + * CXX_THROW_SPECIFICATION - defined if compiler supports throw specification + * + * (our default guess is that the compiler implements the C++ 97 standard) + */ +#define CXX_THROW_SPECIFICATION +#define CXX_PLACEMENT_DELETE + +#endif /* __cplusplus */ + + +#endif /* ifndef compilerSpecific_h */ diff --git a/src/libCom/osi/compiler/solStudio/epicsAtomicCD.h b/src/libCom/osi/compiler/solStudio/epicsAtomicCD.h index 60083cf71..8a733a558 100644 --- a/src/libCom/osi/compiler/solStudio/epicsAtomicCD.h +++ b/src/libCom/osi/compiler/solStudio/epicsAtomicCD.h @@ -16,16 +16,8 @@ #ifndef epicsAtomicCD_h #define epicsAtomicCD_h -#if defined ( __cplusplus ) -# define EPICS_ATOMIC_INLINE inline -#else -# define EPICS_ATOMIC_INLINE __inline -#endif +#define EPICS_ATOMIC_CMPLR_NAME "SOLSTUDIO" -/* - * we have an inline keyword so we can proceed - * with an os specific inline instantiation - */ #include "epicsAtomicOSD.h" #endif /* epicsAtomicCD_h */ diff --git a/src/libCom/osi/epicsAtomic.h b/src/libCom/osi/epicsAtomic.h index f3d509f56..b3aad5c9c 100644 --- a/src/libCom/osi/epicsAtomic.h +++ b/src/libCom/osi/epicsAtomic.h @@ -17,7 +17,9 @@ #include /* define size_t */ -#include "shareLib.h" +#include "compilerSpecific.h" + +#define EPICS_ATOMIC_INLINE static EPICS_ALWAYS_INLINE #ifdef __cplusplus extern "C" { @@ -26,10 +28,10 @@ extern "C" { typedef void * EpicsAtomicPtrT; /* load target into cache */ -epicsShareFunc void epicsAtomicReadMemoryBarrier (); +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void); /* push cache version of target into target */ -epicsShareFunc void epicsAtomicWriteMemoryBarrier (); +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void); /* * lock out other smp processors from accessing the target, @@ -37,8 +39,8 @@ epicsShareFunc void epicsAtomicWriteMemoryBarrier (); * to target, allow other smp processors to access the target, * return new value of target as modified by this operation */ -epicsShareFunc size_t epicsAtomicIncrSizeT ( size_t * pTarget ); -epicsShareFunc int epicsAtomicIncrIntT ( int * pTarget ); +EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget ); +EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget ); /* * lock out other smp processors from accessing the target, @@ -46,8 +48,8 @@ epicsShareFunc int epicsAtomicIncrIntT ( int * pTarget ); * to target, allow out other smp processors to access the target, * return new value of target as modified by this operation */ -epicsShareFunc size_t epicsAtomicDecrSizeT ( size_t * pTarget ); -epicsShareFunc int epicsAtomicDecrIntT ( int * pTarget ); +EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget ); +EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget ); /* * lock out other smp processors from accessing the target, @@ -55,23 +57,23 @@ epicsShareFunc int epicsAtomicDecrIntT ( int * pTarget ); * to target, allow other smp processors to access the target, * return new value of target as modified by this operation */ -epicsShareFunc size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta ); -epicsShareFunc size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta ); -epicsShareFunc int epicsAtomicAddIntT ( int * pTarget, int delta ); +EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta ); +EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta ); +EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta ); /* * set cache version of target, flush cache to target */ -epicsShareFunc void epicsAtomicSetSizeT ( size_t * pTarget, size_t newValue ); -epicsShareFunc void epicsAtomicSetIntT ( int * pTarget, int newValue ); -epicsShareFunc void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newValue ); +EPICS_ATOMIC_INLINE void epicsAtomicSetSizeT ( size_t * pTarget, size_t newValue ); +EPICS_ATOMIC_INLINE void epicsAtomicSetIntT ( int * pTarget, int newValue ); +EPICS_ATOMIC_INLINE void epicsAtomicSetPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT newValue ); /* * fetch target into cache, return new value of target */ -epicsShareFunc size_t epicsAtomicGetSizeT ( const size_t * pTarget ); -epicsShareFunc int epicsAtomicGetIntT ( const int * pTarget ); -epicsShareFunc EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget ); +EPICS_ATOMIC_INLINE size_t epicsAtomicGetSizeT ( const size_t * pTarget ); +EPICS_ATOMIC_INLINE int epicsAtomicGetIntT ( const int * pTarget ); +EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTarget ); /* * lock out other smp processors from accessing the target, @@ -80,11 +82,11 @@ epicsShareFunc EpicsAtomicPtrT epicsAtomicGetPtrT ( const EpicsAtomicPtrT * pTar * to access the target, return the original value stored in the * target */ -epicsShareFunc size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, +EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, size_t oldVal, size_t newVal ); -epicsShareFunc int epicsAtomicCmpAndSwapIntT ( int * pTarget, +EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, int oldVal, int newVal ); -epicsShareFunc EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( +EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal ); @@ -111,119 +113,98 @@ namespace atomic { /* * overloaded c++ interface */ -epicsShareFunc size_t increment ( size_t & v ); -epicsShareFunc int increment ( int & v ); -epicsShareFunc size_t decrement ( size_t & v ); -epicsShareFunc int decrement ( int & v ); -epicsShareFunc size_t add ( size_t & v, size_t delta ); -epicsShareFunc int add ( int & v, int delta ); -epicsShareFunc size_t subtract ( size_t & v, size_t delta ); -epicsShareFunc int subtract ( int & v, int delta ); -epicsShareFunc void set ( size_t & v , size_t newValue ); -epicsShareFunc void set ( int & v, int newValue ); -epicsShareFunc void set ( EpicsAtomicPtrT & v, - EpicsAtomicPtrT newValue ); -epicsShareFunc size_t get ( const size_t & v ); -epicsShareFunc int get ( const int & v ); -epicsShareFunc EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v ); -epicsShareFunc size_t compareAndSwap ( size_t & v, size_t oldVal, - size_t newVal ); -epicsShareFunc int compareAndSwap ( int & v, int oldVal, int newVal ); -epicsShareFunc EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v, - EpicsAtomicPtrT oldVal, - EpicsAtomicPtrT newVal ); /************* incr ***************/ -inline size_t increment ( size_t & v ) +EPICS_ATOMIC_INLINE size_t increment ( size_t & v ) { return epicsAtomicIncrSizeT ( & v ); } -inline int increment ( int & v ) +EPICS_ATOMIC_INLINE int increment ( int & v ) { return epicsAtomicIncrIntT ( & v ); } /************* decr ***************/ -inline size_t decrement ( size_t & v ) +EPICS_ATOMIC_INLINE size_t decrement ( size_t & v ) { return epicsAtomicDecrSizeT ( & v ); } -inline int decrement ( int & v ) +EPICS_ATOMIC_INLINE int decrement ( int & v ) { return epicsAtomicDecrIntT ( & v ); } /************* add ***************/ -inline size_t add ( size_t & v, size_t delta ) +EPICS_ATOMIC_INLINE size_t add ( size_t & v, size_t delta ) { return epicsAtomicAddSizeT ( & v, delta ); } -inline int add ( int & v, int delta ) +EPICS_ATOMIC_INLINE int add ( int & v, int delta ) { return epicsAtomicAddIntT ( & v, delta ); } /************* sub ***************/ -inline size_t subtract ( size_t & v, size_t delta ) +EPICS_ATOMIC_INLINE size_t subtract ( size_t & v, size_t delta ) { return epicsAtomicSubSizeT ( & v, delta ); } -inline int subtract ( int & v, int delta ) +EPICS_ATOMIC_INLINE int subtract ( int & v, int delta ) { return epicsAtomicAddIntT ( & v, -delta ); } /************* set ***************/ -inline void set ( size_t & v , size_t newValue ) +EPICS_ATOMIC_INLINE void set ( size_t & v , size_t newValue ) { epicsAtomicSetSizeT ( & v, newValue ); } -inline void set ( int & v, int newValue ) +EPICS_ATOMIC_INLINE void set ( int & v, int newValue ) { epicsAtomicSetIntT ( & v, newValue ); } -inline void set ( EpicsAtomicPtrT & v, EpicsAtomicPtrT newValue ) +EPICS_ATOMIC_INLINE void set ( EpicsAtomicPtrT & v, EpicsAtomicPtrT newValue ) { epicsAtomicSetPtrT ( & v, newValue ); } /************* get ***************/ -inline size_t get ( const size_t & v ) +EPICS_ATOMIC_INLINE size_t get ( const size_t & v ) { return epicsAtomicGetSizeT ( & v ); } -inline int get ( const int & v ) +EPICS_ATOMIC_INLINE int get ( const int & v ) { return epicsAtomicGetIntT ( & v ); } -inline EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v ) +EPICS_ATOMIC_INLINE EpicsAtomicPtrT get ( const EpicsAtomicPtrT & v ) { return epicsAtomicGetPtrT ( & v ); } /************* cas ***************/ -inline size_t compareAndSwap ( size_t & v, - size_t oldVal, size_t newVal ) +EPICS_ATOMIC_INLINE size_t compareAndSwap ( size_t & v, + size_t oldVal, size_t newVal ) { return epicsAtomicCmpAndSwapSizeT ( & v, oldVal, newVal ); } -inline int compareAndSwap ( int & v, int oldVal, int newVal ) +EPICS_ATOMIC_INLINE int compareAndSwap ( int & v, int oldVal, int newVal ) { return epicsAtomicCmpAndSwapIntT ( & v, oldVal, newVal ); } -inline EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v, - EpicsAtomicPtrT oldVal, - EpicsAtomicPtrT newVal ) +EPICS_ATOMIC_INLINE EpicsAtomicPtrT compareAndSwap ( EpicsAtomicPtrT & v, + EpicsAtomicPtrT oldVal, + EpicsAtomicPtrT newVal ) { return epicsAtomicCmpAndSwapPtrT ( & v, oldVal, newVal ); } diff --git a/src/libCom/osi/os/RTEMS/epicsAtomicOSD.cpp b/src/libCom/osi/os/RTEMS/epicsAtomicOSD.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/libCom/osi/os/RTEMS/epicsAtomicOSD.h b/src/libCom/osi/os/RTEMS/epicsAtomicOSD.h new file mode 100644 index 000000000..fefd2015e --- /dev/null +++ b/src/libCom/osi/os/RTEMS/epicsAtomicOSD.h @@ -0,0 +1,65 @@ + +/*************************************************************************\ +* Copyright (c) 2011 LANS LLC, as Operator of +* Los Alamos National Laboratory. +* Copyright (c) 2011 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. +\*************************************************************************/ + +/* + * Author Jeffrey O. Hill + * johill@lanl.gov + */ + +#ifndef epicsAtomicOSD_h +#define epicsAtomicOSD_h + +#include +#include "epicsMMIO.h" +#include "compilerSpecific.h" +#include "epicsInterrupt.h" + +#define EPICS_ATOMIC_OS_NAME "RTEMS" + +typedef struct EpicsAtomicLockKey { + int key; +} EpicsAtomicLockKey; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void) +{ + epicsAtomicMemoryBarrierFallback(); +} +#endif + +#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void) +{ + rwbarr(); +} +#endif + +EPICS_ATOMIC_INLINE void epicsAtomicLock ( struct EpicsAtomicLockKey * pkey ) +{ + pkey->key = epicsInterruptLock(); +} + +EPICS_ATOMIC_INLINE void epicsAtomicUnlock ( struct EpicsAtomicLockKey * pkey ) +{ + epicsInterruptUnlock(pkey->key); +} + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif /* __cplusplus */ + +#include "epicsAtomicDefault.h" + +#endif /* epicsAtomicOSD_h */ + diff --git a/src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp b/src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp deleted file mode 100644 index e3f684e29..000000000 --- a/src/libCom/osi/os/WIN32/epicsAtomicOSD.cpp +++ /dev/null @@ -1,22 +0,0 @@ - -/*************************************************************************\ -* Copyright (c) 2011 LANS LLC, 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. -\*************************************************************************/ - -/* - * Author Jeffrey O. Hill - * johill@lanl.gov - */ - -#define epicsExportSharedSymbols -#include "epicsAtomic.h" - -// if the compiler is unable to inline then instantiate out-of-line -#ifndef EPICS_ATOMIC_INLINE -# define EPICS_ATOMIC_INLINE -# include "epicsAtomicOSD.h" -#endif - diff --git a/src/libCom/osi/os/WIN32/epicsAtomicOSD.h b/src/libCom/osi/os/WIN32/epicsAtomicOSD.h index da5e49c86..2170fceff 100644 --- a/src/libCom/osi/os/WIN32/epicsAtomicOSD.h +++ b/src/libCom/osi/os/WIN32/epicsAtomicOSD.h @@ -16,6 +16,8 @@ #ifndef epicsAtomicOSD_h #define epicsAtomicOSD_h +#define EPICS_ATOMIC_OS_NAME "WIN32" + #ifdef VC_EXTRALEAN # define VC_EXTRALEAN_DETECTED_epicsAtomicOSD_h #else diff --git a/src/libCom/osi/os/WIN32/epicsSocketConvertErrnoToString.cpp b/src/libCom/osi/os/WIN32/epicsSocketConvertErrnoToString.cpp index d0a70aeaa..5ab809cde 100644 --- a/src/libCom/osi/os/WIN32/epicsSocketConvertErrnoToString.cpp +++ b/src/libCom/osi/os/WIN32/epicsSocketConvertErrnoToString.cpp @@ -1,11 +1,9 @@ - /*************************************************************************\ * Copyright (c) 2002 The University of Chicago, 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 Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ @@ -20,28 +18,36 @@ #include "epicsStdio.h" /* - * epicsSocketConvertErrnoToString () + * epicsSocketConvertErrorToString () */ -void epicsSocketConvertErrnoToString ( - char * pBuf, unsigned bufSize ) +void epicsSocketConvertErrorToString ( + char * pBuf, unsigned bufSize, int theSockError ) { if ( bufSize ) { - /* - * this does not work on systems prior to W2K - */ - int theSockError = SOCKERRNO; - DWORD success = FormatMessage ( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, - NULL, theSockError, - MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ), /* Default language */ - pBuf, bufSize, NULL ); - if ( ! success ) { + /* + * this does not work on systems prior to W2K + */ + DWORD success = FormatMessage ( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, theSockError, + MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ), /* Default language */ + pBuf, bufSize, NULL ); + if ( ! success ) { int status = epicsSnprintf ( pBuf, bufSize, "WINSOCK Error %d", theSockError ); if ( status <= 0 ) { strncpy ( pBuf, "WINSOCK Error", bufSize ); pBuf [bufSize - 0] = '\0'; } - } + } } } + +/* + * epicsSocketConvertErrnoToString () + */ +void epicsSocketConvertErrnoToString ( + char * pBuf, unsigned bufSize ) +{ + epicsSocketConvertErrorToString ( pBuf, bufSize, SOCKERRNO ); +} diff --git a/src/libCom/osi/os/default/epicsAtomicOSD.cpp b/src/libCom/osi/os/default/epicsAtomicOSD.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/libCom/osi/os/default/epicsSocketConvertErrnoToString.cpp b/src/libCom/osi/os/default/epicsSocketConvertErrnoToString.cpp index 0edee89de..0e0ef94f0 100644 --- a/src/libCom/osi/os/default/epicsSocketConvertErrnoToString.cpp +++ b/src/libCom/osi/os/default/epicsSocketConvertErrnoToString.cpp @@ -1,11 +1,9 @@ - /*************************************************************************\ * Copyright (c) 2002 The University of Chicago, 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 Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* osdSock.c */ @@ -22,14 +20,22 @@ #include "osiSock.h" /* - * epicsSocketConvertErrnoToString() + * epicsSocketConvertErrorToString() */ -void epicsSocketConvertErrnoToString ( - char * pBuf, unsigned bufSize ) +void epicsSocketConvertErrorToString ( + char * pBuf, unsigned bufSize, int theSockError ) { if ( bufSize ) { - strncpy ( pBuf, strerror ( SOCKERRNO ), bufSize ); + strncpy ( pBuf, strerror ( theSockError ), bufSize ); pBuf[bufSize-1] = '\0'; } } +/* + * epicsSocketConvertErrnoToString() + */ +void epicsSocketConvertErrnoToString ( + char * pBuf, unsigned bufSize ) +{ + epicsSocketConvertErrorToString ( pBuf, bufSize, SOCKERRNO ); +} diff --git a/src/libCom/osi/os/posix/epicsAtomicOSD.cpp b/src/libCom/osi/os/posix/epicsAtomicOSD.cpp index 6e94cbcc4..1cc227fcd 100644 --- a/src/libCom/osi/os/posix/epicsAtomicOSD.cpp +++ b/src/libCom/osi/os/posix/epicsAtomicOSD.cpp @@ -19,14 +19,6 @@ #include "epicsAssert.h" #include "epicsAtomic.h" -// if the compiler is unable to inline then instantiate out-of-line -#ifndef EPICS_ATOMIC_INLINE -# define EPICS_ATOMIC_INLINE -# include "epicsAtomicOSD.h" -#endif - -#ifndef EPICS_ATOMIC_LOCK - /* * Slow, but probably correct on all systems. * Useful only if something more efficient isn`t @@ -69,31 +61,14 @@ void epicsAtomicUnlock ( EpicsAtomicLockKey * ) assert ( status == 0 ); } -#endif // ifndef EPICS_ATOMIC_LOCK -#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER // Slow, but probably correct on all systems. // Useful only if something more efficient isn`t // provided based on knowledge of the compiler // or OS -void epicsAtomicReadMemoryBarrier () +void epicsAtomicMemoryBarrierFallback (void) { EpicsAtomicLockKey key; epicsAtomicLock ( & key ); epicsAtomicUnlock ( & key ); } -#endif - -#ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER -// Slow, but probably correct on all systems. -// Useful only if something more efficient isn`t -// provided based on knowledge of the compiler -// or OS -void epicsAtomicWriteMemoryBarrier () -{ - EpicsAtomicLockKey key; - epicsAtomicLock ( & key ); - epicsAtomicUnlock ( & key ); -} -#endif - diff --git a/src/libCom/osi/os/posix/epicsAtomicOSD.h b/src/libCom/osi/os/posix/epicsAtomicOSD.h index ff972016d..892d2dcb5 100644 --- a/src/libCom/osi/os/posix/epicsAtomicOSD.h +++ b/src/libCom/osi/os/posix/epicsAtomicOSD.h @@ -16,6 +16,10 @@ #ifndef epicsAtomicOSD_h #define epicsAtomicOSD_h +#include + +#define EPICS_ATOMIC_OS_NAME "POSIX" + typedef struct EpicsAtomicLockKey {} EpicsAtomicLockKey; #ifdef __cplusplus @@ -24,6 +28,21 @@ extern "C" { epicsShareFunc void epicsAtomicLock ( struct EpicsAtomicLockKey * ); epicsShareFunc void epicsAtomicUnlock ( struct EpicsAtomicLockKey * ); +epicsShareFunc void epicsAtomicMemoryBarrierFallback ( void ); + +#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void) +{ + epicsAtomicMemoryBarrierFallback(); +} +#endif + +#ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void) +{ + epicsAtomicMemoryBarrierFallback(); +} +#endif #ifdef __cplusplus } /* end of extern "C" */ diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c index 613c3456c..632b545f9 100644 --- a/src/libCom/osi/os/posix/osdThread.c +++ b/src/libCom/osi/os/posix/osdThread.c @@ -64,12 +64,14 @@ typedef struct commonAttr{ int maxPriority; int minPriority; int schedPolicy; + int usePolicy; } commonAttr; #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 typedef struct { int min_pri, max_pri; int policy; + int ok; } priAvailable; #endif @@ -132,6 +134,8 @@ static void setSchedulingPolicy(epicsThreadOSD *pthreadInfo,int policy) #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 int status; + if(!pcommonAttr->usePolicy) return; + status = pthread_attr_getschedparam( &pthreadInfo->attr,&pthreadInfo->schedParam); checkStatusOnce(status,"pthread_attr_getschedparam"); @@ -281,6 +285,7 @@ int low, try; prm->min_pri = min; prm->max_pri = try_pri(max, prm->policy) ? max-1 : max; + prm->ok = 1; return 0; } @@ -293,6 +298,7 @@ void *dummy; int status; arg.policy = a_p->schedPolicy; + arg.ok = 0; status = pthread_create(&id, 0, find_pri_range, &arg); checkStatusQuit(status, "pthread_create","epicsThreadInit"); @@ -302,6 +308,7 @@ int status; a_p->minPriority = arg.min_pri; a_p->maxPriority = arg.max_pri; + a_p->usePolicy = arg.ok; } #endif @@ -627,7 +634,8 @@ epicsShareFunc void epicsShareAPI epicsThreadSetPriority(epicsThreadId pthreadIn pthreadInfo->osiPriority = priority; if(!pthreadInfo->isRealTimeScheduled) return; -#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 + if(!pcommonAttr->usePolicy) return; pthreadInfo->schedParam.sched_priority = epicsThreadGetPosixPriority(pthreadInfo); status = pthread_attr_setschedparam( &pthreadInfo->attr,&pthreadInfo->schedParam); diff --git a/src/libCom/osi/os/solaris/epicsAtomicOSD.h b/src/libCom/osi/os/solaris/epicsAtomicOSD.h index 6dbda494d..1fa23bd88 100644 --- a/src/libCom/osi/os/solaris/epicsAtomicOSD.h +++ b/src/libCom/osi/os/solaris/epicsAtomicOSD.h @@ -13,9 +13,13 @@ * johill@lanl.gov */ +#include "shareLib.h" + #ifndef epicsAtomicOSD_h #define epicsAtomicOSD_h +#define EPICS_ATOMIC_OS_NAME "Solaris" + #if defined ( __SunOS_5_10 ) /* @@ -31,7 +35,7 @@ extern "C" { #ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER #define EPICS_ATOMIC_READ_MEMORY_BARRIER -EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void) { membar_consumer (); } @@ -39,7 +43,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () #ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER #define EPICS_ATOMIC_WRITE_MEMORY_BARRIER -EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void) { membar_producer (); } @@ -47,7 +51,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () #ifndef EPICS_ATOMIC_CAS_INTT #define EPICS_ATOMIC_CAS_INTT -EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, +EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, int oldVal, int newVal ) { STATIC_ASSERT ( sizeof ( int ) == sizeof ( unsigned ) ); @@ -59,7 +63,7 @@ EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, #ifndef EPICS_ATOMIC_CAS_SIZET #define EPICS_ATOMIC_CAS_SIZET -EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( +EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget, size_t oldVal, size_t newVal ) { @@ -71,7 +75,7 @@ EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( #ifndef EPICS_ATOMIC_CAS_PTRT #define EPICS_ATOMIC_CAS_PTRT -EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( +EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT ( EpicsAtomicPtrT * pTarget, EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal ) @@ -132,7 +136,7 @@ EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta ) #ifndef EPICS_ATOMIC_ADD_SIZET #define EPICS_ATOMIC_ADD_SIZET -EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, +EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta ) { STATIC_ASSERT ( sizeof ( ulong_t ) == sizeof ( size_t ) ); @@ -143,7 +147,7 @@ EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, #ifndef EPICS_ATOMIC_SUB_SIZET #define EPICS_ATOMIC_SUB_SIZET -EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, +EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta ) { STATIC_ASSERT ( sizeof ( ulong_t ) == sizeof ( size_t ) ); diff --git a/src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp b/src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp index 6a9f529a3..e69de29bb 100644 --- a/src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp +++ b/src/libCom/osi/os/vxWorks/epicsAtomicOSD.cpp @@ -1,21 +0,0 @@ - -/*************************************************************************\ -* Copyright (c) 2011 LANS LLC, 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. -\*************************************************************************/ - -/* - * Author Jeffrey O. Hill - * johill@lanl.gov - */ - -#define epicsExportSharedSymbols -#include "epicsAtomic.h" - -// if the compiler is unable to inline then instantiate out-of-line -#ifndef EPICS_ATOMIC_INLINE -# define EPICS_ATOMIC_INLINE -# include "epicsAtomicOSD.h" -#endif diff --git a/src/libCom/osi/os/vxWorks/epicsAtomicOSD.h b/src/libCom/osi/os/vxWorks/epicsAtomicOSD.h index 5454e70ba..e7bdde0c3 100644 --- a/src/libCom/osi/os/vxWorks/epicsAtomicOSD.h +++ b/src/libCom/osi/os/vxWorks/epicsAtomicOSD.h @@ -32,13 +32,15 @@ #include #include +#define EPICS_ATOMIC_OS_NAME "VX-ATOMICLIB" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER #define EPICS_ATOMIC_READ_MEMORY_BARRIER -EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void) { VX_MEM_BARRIER_R (); } @@ -46,7 +48,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () #ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER #define EPICS_ATOMIC_WRITE_MEMORY_BARRIER -EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void) { VX_MEM_BARRIER_W (); } @@ -206,6 +208,8 @@ EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget, #include "vxLib.h" #include "intLib.h" +#define EPICS_ATOMIC_OS_NAME "VX-INTLIB" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -232,7 +236,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicUnlock ( EpicsAtomicLockKey * pKey ) * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system * (we are not protecting against multiple access to memory mapped IO) */ -EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () {} +EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void) {} #endif #ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER @@ -241,7 +245,7 @@ EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier () {} * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system * (we are not protecting against multiple access to memory mapped IO) */ -EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier () {} +EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void) {} #endif #ifdef __cplusplus diff --git a/src/libCom/osi/osiSock.h b/src/libCom/osi/osiSock.h index b098290da..1b52c7993 100644 --- a/src/libCom/osi/osiSock.h +++ b/src/libCom/osi/osiSock.h @@ -140,9 +140,11 @@ epicsShareFunc int epicsShareAPI osiSockAttach (void); /* returns T if success, epicsShareFunc void epicsShareAPI osiSockRelease (void); /* - * convert socket error number to a string + * convert socket error numbers to a string */ -epicsShareFunc void epicsSocketConvertErrnoToString ( +epicsShareFunc void epicsSocketConvertErrorToString ( + char * pBuf, unsigned bufSize, int error ); +epicsShareFunc void epicsSocketConvertErrnoToString ( char * pBuf, unsigned bufSize ); typedef union osiSockAddr { diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index 3a3d32a8f..e0c1b064c 100755 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -22,6 +22,14 @@ epicsTypesTest_SRCS += epicsTypesTest.cpp testHarness_SRCS += epicsTypesTest.cpp TESTS += epicsTypesTest +TESTPROD_HOST += epicsInlineTest +epicsInlineTest_SRCS += epicsInlineTest1.c +epicsInlineTest_SRCS += epicsInlineTest2.c +epicsInlineTest_SRCS += epicsInlineTest3.cpp +epicsInlineTest_SRCS += epicsInlineTest4.cpp +testHarness_SRCS += $(epicsInlineTest_SRCS) +TESTS += epicsInlineTest + TESTPROD_HOST += epicsCalcTest epicsCalcTest_SRCS += epicsCalcTest.cpp testHarness_SRCS += epicsCalcTest.cpp diff --git a/src/libCom/test/epicsAtomicTest.cpp b/src/libCom/test/epicsAtomicTest.cpp index 78cfa5b95..1c4dcf20f 100644 --- a/src/libCom/test/epicsAtomicTest.cpp +++ b/src/libCom/test/epicsAtomicTest.cpp @@ -248,11 +248,89 @@ template void testCAS < EpicsAtomicPtrT > (void); # pragma warning ( pop ) #endif +static void testClassify() +{ + testDiag("Classify Build conditions"); +#ifdef EPICS_ATOMIC_CMPLR_NAME + testDiag("Compiler dependent impl name %s", EPICS_ATOMIC_CMPLR_NAME); +#else + testDiag("Compiler dependent impl name undefined"); +#endif +#ifdef EPICS_ATOMIC_OS_NAME + testDiag("OS dependent impl name %s", EPICS_ATOMIC_OS_NAME); +#else + testDiag("OS dependent impl name undefined"); +#endif + +#ifdef __GNUC__ +#if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER + testDiag("GCC using atomic builtin memory barrier"); +#else + testDiag("GCC using asm memory barrier"); +#endif +#if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER + testDiag("GCC use builtin for int"); +#endif +#if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER + testDiag("GCC use builtin for size_t"); +#endif + +#ifndef EPICS_ATOMIC_INCR_INTT + testDiag("Use default epicsAtomicIncrIntT()"); +#endif +#ifndef EPICS_ATOMIC_INCR_SIZET + testDiag("Use default epicsAtomicIncrSizeT()"); +#endif +#ifndef EPICS_ATOMIC_DECR_INTT + testDiag("Use default epicsAtomicDecrIntT()"); +#endif +#ifndef EPICS_ATOMIC_DECR_SIZET + testDiag("Use default epicsAtomicDecrSizeT()"); +#endif +#ifndef EPICS_ATOMIC_ADD_INTT + testDiag("Use default epicsAtomicAddIntT()"); +#endif +#ifndef EPICS_ATOMIC_ADD_SIZET + testDiag("Use default epicsAtomicAddSizeT()"); +#endif +#ifndef EPICS_ATOMIC_SUB_SIZET + testDiag("Use default epicsAtomicSubSizeT()"); +#endif +#ifndef EPICS_ATOMIC_SET_INTT + testDiag("Use default epicsAtomicSetIntT()"); +#endif +#ifndef EPICS_ATOMIC_SET_SIZET + testDiag("Use default epicsAtomicSetSizeT()"); +#endif +#ifndef EPICS_ATOMIC_SET_PTRT + testDiag("Use default epicsAtomicSetPtrT()"); +#endif +#ifndef EPICS_ATOMIC_GET_INTT + testDiag("Use default epicsAtomicGetIntT()"); +#endif +#ifndef EPICS_ATOMIC_GET_SIZET + testDiag("Use default epicsAtomicGetSizeT()"); +#endif +#ifndef EPICS_ATOMIC_GET_PTRT + testDiag("Use default epicsAtomicGetPtrT()"); +#endif +#ifndef EPICS_ATOMIC_CAS_INTT + testDiag("Use default epicsAtomicCmpAndSwapIntT()"); +#endif +#ifndef EPICS_ATOMIC_CAS_SIZET + testDiag("Use default epicsAtomicCmpAndSwapSizeT()"); +#endif +#ifndef EPICS_ATOMIC_CAS_PTRT + testDiag("Use default epicsAtomicCmpAndSwapPtrT()"); +#endif +#endif /* __GNUC__ */ +} MAIN ( epicsAtomicTest ) { testPlan ( 31 ); + testClassify (); testIncrDecr < int > (); testIncrDecr < size_t > (); diff --git a/src/libCom/test/epicsCalcTest.cpp b/src/libCom/test/epicsCalcTest.cpp index 694a62d58..92ec61a37 100644 --- a/src/libCom/test/epicsCalcTest.cpp +++ b/src/libCom/test/epicsCalcTest.cpp @@ -553,10 +553,18 @@ MAIN(epicsCalcTest) testExpr(0.0 + NaN); testExpr(Inf + 0.0); testExpr(Inf + Inf); +#if defined(_WIN64) && defined(_MSC_VER) + testCalc("Inf + -Inf", NaN); +#else testExpr(Inf + -Inf); +#endif testExpr(Inf + NaN); testExpr(-Inf + 0.0); +#if defined(_WIN64) && defined(_MSC_VER) + testCalc("-Inf + Inf", NaN); +#else testExpr(-Inf + Inf); +#endif testExpr(-Inf + -Inf); testExpr(-Inf + NaN); testExpr(NaN + 0.0); diff --git a/src/libCom/test/epicsExceptionTest.cpp b/src/libCom/test/epicsExceptionTest.cpp index b9ecdc940..b40ceb0dc 100644 --- a/src/libCom/test/epicsExceptionTest.cpp +++ b/src/libCom/test/epicsExceptionTest.cpp @@ -70,7 +70,7 @@ static void epicsExceptionTestPrivate () try { char * p = new ( nothrow ) char [unsuccessfulNewSize]; - testOk(p == 0, "new (nothrow)"); + testOk(p == 0, "new (nothrow) returned %p", p); } catch( ... ) { testFail("new (nothrow): threw"); diff --git a/src/libCom/test/epicsInlineTest1.c b/src/libCom/test/epicsInlineTest1.c new file mode 100644 index 000000000..e377e5f1d --- /dev/null +++ b/src/libCom/test/epicsInlineTest1.c @@ -0,0 +1,64 @@ +/*************************************************************************\ +* Copyright (c) 2015 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* This test checks the variations on inline function defintions. + * + * "static inline int func(void) {...}" + * + * Consistent meaning in C89, C99, and C++ (98 and 11). + * If not inline'd results in a private symbol in each compilation unit. + * Thus the non-inline'd version is duplicated in each compilation unit. + * However, definitions in different compilation units may be different. + * + * "inline int func(void) {...}" + * Warning: Not consistent, avoid use in headers meant for C or C++ + * + * In C++ this may be safely defined in more than one compilation unit. + * Where not inlined it will result in a weak public symbol. + * Thus non-inline'd version isn't duplicated, but must be the same + * in all compilation units. + * + */ + +#include "compilerSpecific.h" +#include "epicsUnitTest.h" + +#include "testMain.h" + +static EPICS_ALWAYS_INLINE int epicsInlineTestFn1(void) +{ + return 1; +} + +/* Fails to link in C99 +inline int epicsInlineTestFn2(void) +{ + return 42; +} +*/ + +void epicsInlineTest1(void) +{ + testDiag("epicsInlineTest1()"); + testOk1(epicsInlineTestFn1()==1); + /*testOk1(epicsInlineTestFn2()==42);*/ +} + +void epicsInlineTest2(void); +void epicsInlineTest3(void); +void epicsInlineTest4(void); + +MAIN(epicsInlineTest) +{ + testPlan(6); + testDiag("Test variation on inline int func()"); + epicsInlineTest1(); + epicsInlineTest2(); + epicsInlineTest3(); + epicsInlineTest4(); + return testDone(); +} diff --git a/src/libCom/test/epicsInlineTest2.c b/src/libCom/test/epicsInlineTest2.c new file mode 100644 index 000000000..b787276fb --- /dev/null +++ b/src/libCom/test/epicsInlineTest2.c @@ -0,0 +1,28 @@ +/*************************************************************************\ +* Copyright (c) 2015 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include "compilerSpecific.h" +#include "epicsUnitTest.h" + +static EPICS_ALWAYS_INLINE int epicsInlineTestFn1(void) +{ + return 2; +} + +/* Fails to link in C99 +inline int epicsInlineTestFn2(void) +{ + return 42; +} +*/ + +void epicsInlineTest2(void) +{ + testDiag("epicsInlineTest2()"); + testOk1(epicsInlineTestFn1()==2); + /*testOk1(epicsInlineTestFn2()==42);*/ +} diff --git a/src/libCom/test/epicsInlineTest3.cpp b/src/libCom/test/epicsInlineTest3.cpp new file mode 100644 index 000000000..9647be6dc --- /dev/null +++ b/src/libCom/test/epicsInlineTest3.cpp @@ -0,0 +1,27 @@ +/*************************************************************************\ +* Copyright (c) 2015 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include "compilerSpecific.h" +#include "epicsUnitTest.h" + +static EPICS_ALWAYS_INLINE int epicsInlineTestFn1(void) +{ + return 3; +} + +inline int epicsInlineTestFn2(void) +{ + return 42; +} + +extern "C" +void epicsInlineTest3(void) +{ + testDiag("epicsInlineTest3()"); + testOk1(epicsInlineTestFn1()==3); + testOk1(epicsInlineTestFn2()==42); +} diff --git a/src/libCom/test/epicsInlineTest4.cpp b/src/libCom/test/epicsInlineTest4.cpp new file mode 100644 index 000000000..545b45ffd --- /dev/null +++ b/src/libCom/test/epicsInlineTest4.cpp @@ -0,0 +1,27 @@ +/*************************************************************************\ +* Copyright (c) 2015 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include "compilerSpecific.h" +#include "epicsUnitTest.h" + +static EPICS_ALWAYS_INLINE int epicsInlineTestFn1(void) +{ + return 4; +} + +inline int epicsInlineTestFn2(void) +{ + return 42; +} + +extern "C" +void epicsInlineTest4(void) +{ + testDiag("epicsInlineTest4()"); + testOk1(epicsInlineTestFn1()==4); + testOk1(epicsInlineTestFn2()==42); +} diff --git a/src/libCom/test/epicsMathTest.c b/src/libCom/test/epicsMathTest.c index 527dd2922..8ea763cf0 100644 --- a/src/libCom/test/epicsMathTest.c +++ b/src/libCom/test/epicsMathTest.c @@ -31,11 +31,26 @@ MAIN(epicsMathTest) testOk1(epicsINF == epicsINF); testOk1(epicsINF > 0.0); testOk1(epicsINF - epicsINF != 0.0); + +#if defined(_WIN64) && defined(_MSC_VER) + testTodoBegin("Known failure on windows-x64"); +#endif testOk1(epicsINF + -epicsINF != 0.0); testOk1(-epicsINF + epicsINF != 0.0); +#if defined(_WIN64) && defined(_MSC_VER) + testTodoEnd(); +#endif + testOk1(isnan(epicsINF - epicsINF)); + +#if defined(_WIN64) && defined(_MSC_VER) + testTodoBegin("Known failure on windows-x64"); +#endif testOk1(isnan(epicsINF + -epicsINF)); testOk1(isnan(-epicsINF + epicsINF)); +#if defined(_WIN64) && defined(_MSC_VER) + testTodoEnd(); +#endif testOk1(isnan(epicsNAN)); testOk1(!isinf(epicsNAN)); @@ -46,8 +61,15 @@ MAIN(epicsMathTest) testOk1(!(epicsNAN >= epicsNAN)); testOk1(!(epicsNAN > epicsNAN)); testOk1(isnan(epicsNAN - epicsNAN)); + +#if defined(_WIN64) && defined(_MSC_VER) + testTodoBegin("Known failure on windows-x64"); +#endif testOk1(isnan(epicsNAN + -epicsNAN)); testOk1(isnan(-epicsNAN + epicsNAN)); +#if defined(_WIN64) && defined(_MSC_VER) + testTodoEnd(); +#endif c = huge / tiny; testOk(!isnan(c), "!isnan(1e300 / 1e-300)"); diff --git a/src/libCom/test/epicsMessageQueueTest.cpp b/src/libCom/test/epicsMessageQueueTest.cpp index 5e33361c5..e4216c291 100644 --- a/src/libCom/test/epicsMessageQueueTest.cpp +++ b/src/libCom/test/epicsMessageQueueTest.cpp @@ -10,8 +10,6 @@ * $Revision-Id$ * * Author W. Eric Norum - * norume@aps.anl.gov - * 630 252 4793 */ #include #include @@ -27,8 +25,10 @@ #include "testMain.h" static const char *msg1 = "1234567890This is a very long message."; -static volatile int testExit = 0; +static volatile int sendExit = 0; +static volatile int recvExit = 0; static epicsEventId finished; +static unsigned int mediumStack; /* * In Numerical Recipes in C: The Art of Scientific Computing (William H. @@ -79,6 +79,7 @@ extern "C" void receiver(void *arg) { epicsMessageQueue *q = (epicsMessageQueue *)arg; + const char *myName = epicsThreadGetNameSelf(); char cbuf[80]; int expectmsg[4]; int len; @@ -87,10 +88,10 @@ receiver(void *arg) for (sender = 1 ; sender <= 4 ; sender++) expectmsg[sender-1] = 1; - while (!testExit) { + while (!recvExit) { cbuf[0] = '\0'; len = q->receive(cbuf, sizeof cbuf, 5.0); - if (len < 0 && !testExit) { + if (len < 0 && !recvExit) { testDiag("receiver() received unexpected timeout"); ++errors; } @@ -98,7 +99,8 @@ receiver(void *arg) sender >= 1 && sender <= 4) { if (expectmsg[sender-1] != msgNum) { ++errors; - testDiag("%s received %d '%.*s' -- expected %d", epicsThreadGetNameSelf(), len, len, cbuf, expectmsg[sender-1]); + testDiag("%s received %d '%.*s' -- expected %d", + myName, len, len, cbuf, expectmsg[sender-1]); } expectmsg[sender-1] = msgNum + 1; epicsThreadSleep(0.001 * (randBelow(20))); @@ -106,10 +108,12 @@ receiver(void *arg) } for (sender = 1 ; sender <= 4 ; sender++) { if (expectmsg[sender-1] > 1) - testDiag("Sender %d -- %d messages", sender, expectmsg[sender-1]-1); + testDiag("Received %d messages from Sender %d", + expectmsg[sender-1]-1, sender); } if (!testOk1(errors == 0)) - testDiag("error count was %d", errors); + testDiag("Error count was %d", errors); + testDiag("%s exiting", myName); epicsEventSignal(finished); } @@ -121,16 +125,18 @@ sender(void *arg) int len; int i = 0; - while (!testExit) { + while (!sendExit) { len = sprintf(cbuf, "%s -- %d.", epicsThreadGetNameSelf(), ++i); while (q->trySend((void *)cbuf, len) < 0) epicsThreadSleep(0.005 * (randBelow(5))); epicsThreadSleep(0.005 * (randBelow(20))); } + testDiag("%s exiting, sent %d messages", epicsThreadGetNameSelf(), i); } extern "C" void messageQueueTest(void *parm) { + epicsThreadId myThreadId = epicsThreadGetIdSelf(); unsigned int i; char cbuf[80]; int len; @@ -152,20 +158,23 @@ extern "C" void messageQueueTest(void *parm) len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 3); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) - testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); want++; len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 2); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) - testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); q1->trySend((void *)msg1, i++); want++; len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 2); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) - testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); q1->trySend((void *)msg1, i++); testOk1(q1->pending() == 3); @@ -175,7 +184,8 @@ extern "C" void messageQueueTest(void *parm) testOk(q1->pending() == i, "q1->pending() == %d", i); want++; if (!testOk1((len == want) & (strncmp(msg1, cbuf, len) == 0))) - testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); } testOk1(q1->pending() == 0); @@ -192,20 +202,23 @@ extern "C" void messageQueueTest(void *parm) len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 3); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) - testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); want++; len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 2); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) - testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); q1->send((void *)msg1, i++, 1.0); want++; len = q1->receive(cbuf, sizeof cbuf); testOk1(q1->pending() == 2); if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) - testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); q1->send((void *)msg1, i++, 1.0); testOk1(q1->pending() == 3); @@ -215,7 +228,8 @@ extern "C" void messageQueueTest(void *parm) testOk(q1->pending() == i, "q1->pending() == %d", i); want++; if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) - testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); } testOk1(q1->pending() == 0); @@ -231,7 +245,8 @@ extern "C" void messageQueueTest(void *parm) testOk1(q1->pending() == 0); testDiag("Single receiver with invalid size, single sender tests:"); - epicsThreadCreate("Bad Receiver", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), badReceiver, q1); + epicsThreadCreate("Bad Receiver", epicsThreadPriorityMedium, + mediumStack, badReceiver, q1); epicsThreadSleep(1.0); testOk(q1->send((void *)msg1, 10) == 0, "Send with waiting receiver"); epicsThreadSleep(2.0); @@ -239,8 +254,9 @@ extern "C" void messageQueueTest(void *parm) epicsThreadSleep(2.0); testDiag("Single receiver, single sender tests:"); - epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityHigh); - epicsThreadCreate("Receiver one", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), receiver, q1); + epicsThreadSetPriority(myThreadId, epicsThreadPriorityHigh); + epicsThreadCreate("Receiver one", epicsThreadPriorityMedium, + mediumStack, receiver, q1); for (pass = 1 ; pass <= 3 ; pass++) { for (i = 0 ; i < 10 ; i++) { if (q1->trySend((void *)msg1, i) < 0) @@ -252,7 +268,7 @@ extern "C" void messageQueueTest(void *parm) case 1: if (i<6) testDiag(" priority-based scheduler, sent %d messages", i); - epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityLow); + epicsThreadSetPriority(myThreadId, epicsThreadPriorityLow); break; case 2: if (i<10) @@ -272,27 +288,43 @@ extern "C" void messageQueueTest(void *parm) */ testDiag("Single receiver, multiple sender tests:"); testDiag("This test lasts 60 seconds..."); - epicsThreadCreate("Sender 1", epicsThreadPriorityLow, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); - epicsThreadCreate("Sender 2", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); - epicsThreadCreate("Sender 3", epicsThreadPriorityHigh, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); - epicsThreadCreate("Sender 4", epicsThreadPriorityHigh, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); + testOk(!!epicsThreadCreate("Sender 1", epicsThreadPriorityLow, + mediumStack, sender, q1), + "Created Sender 1"); + testOk(!!epicsThreadCreate("Sender 2", epicsThreadPriorityMedium, + mediumStack, sender, q1), + "Created Sender 2"); + testOk(!!epicsThreadCreate("Sender 3", epicsThreadPriorityHigh, + mediumStack, sender, q1), + "Created Sender 3"); + testOk(!!epicsThreadCreate("Sender 4", epicsThreadPriorityHigh, + mediumStack, sender, q1), + "Created Sender 4"); - epicsThreadSleep(60.0); + for (i = 0; i < 10; i++) { + testDiag("... %2d", 10 - i); + epicsThreadSleep(6.0); + } - testExit = 1; + sendExit = 1; + epicsThreadSleep(1.0); + recvExit = 1; + testDiag("Scheduler exiting"); } MAIN(epicsMessageQueueTest) { - testPlan(58); + testPlan(62); finished = epicsEventMustCreate(epicsEventEmpty); + mediumStack = epicsThreadGetStackSize(epicsThreadStackMedium); epicsThreadCreate("messageQueueTest", epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium), - messageQueueTest, NULL); + mediumStack, messageQueueTest, NULL); - (void) epicsEventWait(finished); + epicsEventMustWait(finished); + testDiag("Main thread signalled"); + epicsThreadSleep(1.0); return testDone(); } diff --git a/src/libCom/test/epicsRunLibComTests.c b/src/libCom/test/epicsRunLibComTests.c index 5bf6cafd1..fe308b061 100644 --- a/src/libCom/test/epicsRunLibComTests.c +++ b/src/libCom/test/epicsRunLibComTests.c @@ -44,6 +44,7 @@ int epicsThreadTest(void); int epicsTimerTest(void); int epicsTimeTest(void); int epicsTypesTest(void); +int epicsInlineTest(void); int macDefExpandTest(void); int macLibTest(void); int ringBytesTest(void); @@ -92,6 +93,7 @@ void epicsRunLibComTests(void) runTest(epicsThreadPrivateTest); runTest(epicsTimeTest); runTest(epicsTypesTest); + runTest(epicsInlineTest); runTest(macDefExpandTest); runTest(macLibTest); runTest(ringBytesTest); diff --git a/src/libCom/test/epicsTimerTest.cpp b/src/libCom/test/epicsTimerTest.cpp index a4ab9cccc..96f1a78cd 100644 --- a/src/libCom/test/epicsTimerTest.cpp +++ b/src/libCom/test/epicsTimerTest.cpp @@ -29,6 +29,41 @@ #define verify(exp) ((exp) ? (void)0 : \ epicsAssert(__FILE__, __LINE__, #exp, epicsAssertAuthor)) +class notified : public epicsTimerNotify +{ +public: + bool done; + notified() : epicsTimerNotify(), done(false) {} + + expireStatus expire(const epicsTime ¤tTime) + {done=true; return expireStatus(noRestart);} +}; + +void testRefCount() +{ + notified action; + + epicsTimerQueueActive *Q1, *Q2; + epicsTimer *T1, *T2; + + Q1 = &epicsTimerQueueActive::allocate ( true, epicsThreadPriorityMin ); + + T1 = &Q1->createTimer(); + //timer->start(action, 0.0); + + Q2 = &epicsTimerQueueActive::allocate ( true, epicsThreadPriorityMin ); + + testOk1(Q1==Q2); + + T2 = &Q2->createTimer(); + + T2->destroy(); + Q2->release(); + + T1->destroy(); + Q1->release(); +} + static const double delayVerifyOffset = 1.0; // sec class delayVerify : public epicsTimerNotify { @@ -419,7 +454,8 @@ void testPeriodic () MAIN(epicsTimerTest) { - testPlan(40); + testPlan(41); + testRefCount(); testAccuracy (); testCancel (); testExpireDestroy (); diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile index fcdb0ac7f..db2c099ff 100644 --- a/src/std/rec/test/Makefile +++ b/src/std/rec/test/Makefile @@ -35,8 +35,8 @@ testHarness_SRCS += analogMonitorTest_registerRecordDeviceDriver.cpp TESTFILES += $(COMMON_DIR)/analogMonitorTest.dbd ../analogMonitorTest.db TESTS += analogMonitorTest -# epicsRunTests runs all the test programs in a known working order. -testHarness_SRCS += epicsRunTests.c +# epicsRunRecordTests runs all the test programs in a known working order. +testHarness_SRCS += epicsRunRecordTests.c recordTestHarness_SRCS += $(testHarness_SRCS) recordTestHarness_SRCS_RTEMS += rtemsTestHarness.c @@ -44,8 +44,8 @@ recordTestHarness_SRCS_RTEMS += rtemsTestHarness.c PROD_vxWorks = recordTestHarness PROD_RTEMS = recordTestHarness -TESTSPEC_vxWorks = recordTestHarness.munch; epicsRunTests -TESTSPEC_RTEMS = recordTestHarness.boot; epicsRunTests +TESTSPEC_vxWorks = recordTestHarness.munch; epicsRunRecordTests +TESTSPEC_RTEMS = recordTestHarness.boot; epicsRunRecordTests TESTSCRIPTS_HOST += $(TESTS:%=%.t) diff --git a/src/std/rec/test/epicsRunTests.c b/src/std/rec/test/epicsRunRecordTests.c similarity index 95% rename from src/std/rec/test/epicsRunTests.c rename to src/std/rec/test/epicsRunRecordTests.c index 2c2e9c70a..092c0a6ce 100644 --- a/src/std/rec/test/epicsRunTests.c +++ b/src/std/rec/test/epicsRunRecordTests.c @@ -15,7 +15,7 @@ int analogMonitorTest(void); int arrayOpTest(void); -void epicsRunTests(void) +void epicsRunRecordTests(void) { testHarness(); diff --git a/src/std/rec/test/rtemsTestHarness.c b/src/std/rec/test/rtemsTestHarness.c index dd25941ef..772d5394e 100644 --- a/src/std/rec/test/rtemsTestHarness.c +++ b/src/std/rec/test/rtemsTestHarness.c @@ -5,10 +5,10 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ -extern void epicsRunTests(void); +extern void epicsRunRecordTests(void); int main(int argc, char **argv) { - epicsRunTests(); /* calls epicsExit(0) */ + epicsRunRecordTests(); /* calls epicsExit(0) */ return 0; } diff --git a/src/tools/dbdToRecordtypeH.pl b/src/tools/dbdToRecordtypeH.pl index d4140cc87..06c3b565e 100755 --- a/src/tools/dbdToRecordtypeH.pl +++ b/src/tools/dbdToRecordtypeH.pl @@ -112,13 +112,16 @@ if ($opt_D) { # Output dependencies only, to stdout sub oldtables { # Output compatible with R3.14.x - print OUTFILE "#ifdef __cplusplus\n" . + print OUTFILE + "#include \n" . + "#include \n" . + "#ifdef __cplusplus\n" . "extern \"C\" {\n" . "#endif\n" . - "#include \n" . "static int ${rn}RecordSizeOffset(dbRecordType *prt)\n" . "{\n" . - " ${rn}Record *prec = 0;\n" . + " ${rn}Record *prec = 0;\n\n" . + " assert(prt->no_fields == " . scalar($rtyp->fields) . ");\n" . join("\n", map { " prt->papFldDes[${rn}Record" . $_->name . "]->size = " . "sizeof(prec->" . $_->C_name . ");" diff --git a/src/tools/makeTestfile.pl b/src/tools/makeTestfile.pl index a037eb71c..4ac5162db 100644 --- a/src/tools/makeTestfile.pl +++ b/src/tools/makeTestfile.pl @@ -10,7 +10,7 @@ # The makeTestfile.pl script generates a file $target.t which is needed # because some versions of the Perl test harness can only run test scripts -# that are actually written in Perl. The script we generate execs the +# that are actually written in Perl. The script we generate runs the # real test program which must be in the same directory as the .t file. # If the script is given an argument -tap it sets HARNESS_ACTIVE in the # environment to make the epicsUnitTest code generate strict TAP output. @@ -23,12 +23,21 @@ use strict; my ($target, $exe) = @ARGV; +# Use system on Windows, exec doesn't work the same there and +# GNUmake thinks the test has finished as soon as Perl exits. +my $exec = $^O eq 'MSWin32' ? "system('./$exe') == 0" : "exec './$exe'"; + open(my $OUT, '>', $target) or die "Can't create $target: $!\n"; print $OUT <