Merge branch '7.0' of https://github.com/epics-base/epics-base into rtems5
This commit is contained in:
@@ -26,5 +26,7 @@ ERR_S_FILES += $(LIBCOM)/as/asLib.h
|
||||
ERR_S_FILES += $(LIBCOM)/misc/epicsStdlib.h
|
||||
ERR_S_FILES += $(LIBCOM)/pool/epicsThreadPool.h
|
||||
ERR_S_FILES += $(LIBCOM)/error/errMdef.h
|
||||
ERR_S_FILES += $(TOP)/modules/database/src/ioc/db/dbAccessDefs.h
|
||||
ERR_S_FILES += $(TOP)/modules/database/src/ioc/dbStatic/dbStaticLib.h
|
||||
|
||||
CLEANS += errSymTbl.c
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "cantProceed.h"
|
||||
#include "epicsString.h"
|
||||
#include "epicsMath.h"
|
||||
|
||||
/* Deprecated, use epicsStrnRawFromEscaped() instead */
|
||||
int dbTranslateEscape(char *dst, const char *src)
|
||||
@@ -358,3 +360,71 @@ unsigned int epicsMemHash(const char *str, size_t length, unsigned int seed)
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* Compute normalized Levenshtein distance
|
||||
*
|
||||
* https://en.wikipedia.org/wiki/Levenshtein_distance
|
||||
*
|
||||
* We modify this to give half weight to case insensitive substitution.
|
||||
* All normal integer weights are multiplied by two, with case
|
||||
* insensitive added in as one.
|
||||
*/
|
||||
double epicsStrSimilarity(const char *A, const char *B)
|
||||
{
|
||||
double ret = 0;
|
||||
size_t lA, lB, a, b;
|
||||
size_t norm;
|
||||
size_t *dist0, *dist1, *stemp;
|
||||
|
||||
lA = strlen(A);
|
||||
lB = strlen(B);
|
||||
|
||||
/* max number of edits to change A into B is max(lA, lB) */
|
||||
norm = lA > lB ? lA : lB;
|
||||
/* take into account our weighting */
|
||||
norm *= 2u;
|
||||
|
||||
dist0 = calloc(1+lB, sizeof(*dist0));
|
||||
dist1 = calloc(1+lB, sizeof(*dist1));
|
||||
if(!dist0 || !dist1) {
|
||||
ret = -1.0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
for(b=0; b<1+lB; b++)
|
||||
dist0[b] = 2*b;
|
||||
|
||||
for(a=0; a<lA; a++) {
|
||||
dist1[0] = 2*(a+1);
|
||||
|
||||
for(b=0; b<lB; b++) {
|
||||
size_t delcost = dist0[b+1] + 2,
|
||||
inscost = dist1[b] + 2,
|
||||
subcost = dist0[b],
|
||||
mincost = delcost;
|
||||
char ca = A[a], cb = B[b];
|
||||
|
||||
if(ca!=cb)
|
||||
subcost++;
|
||||
if(toupper((int)ca)!=toupper((int)cb))
|
||||
subcost++;
|
||||
|
||||
if(mincost > inscost)
|
||||
mincost = inscost;
|
||||
if(mincost > subcost)
|
||||
mincost = subcost;
|
||||
|
||||
dist1[b+1] = mincost;
|
||||
}
|
||||
|
||||
stemp = dist0;
|
||||
dist0 = dist1;
|
||||
dist1 = stemp;
|
||||
}
|
||||
|
||||
ret = norm ? (norm - dist0[lB]) / (double)norm : 1.0;
|
||||
done:
|
||||
free(dist0);
|
||||
free(dist1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,16 @@ LIBCOM_API char * epicsStrtok_r(char *s, const char *delim, char **lasts);
|
||||
LIBCOM_API unsigned int epicsStrHash(const char *str, unsigned int seed);
|
||||
LIBCOM_API unsigned int epicsMemHash(const char *str, size_t length,
|
||||
unsigned int seed);
|
||||
/** Compare two strings and return a number in the range [0.0, 1.0] or -1.0 on error.
|
||||
*
|
||||
* Computes a normalized edit distance representing the similarity between two strings.
|
||||
*
|
||||
* @returns 1.0 when A and B are identical, down to 0.0 when A and B are unrelated,
|
||||
* or < 0.0 on error.
|
||||
*
|
||||
* @since UNRELEASED
|
||||
*/
|
||||
LIBCOM_API double epicsStrSimilarity(const char *A, const char *B);
|
||||
|
||||
/* dbTranslateEscape is deprecated, use epicsStrnRawFromEscaped instead */
|
||||
LIBCOM_API int dbTranslateEscape(char *s, const char *ct);
|
||||
|
||||
@@ -112,6 +112,7 @@ Com_SRCS += osdStdio.c
|
||||
THREAD_CPPFLAGS_NO += -DDONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING
|
||||
osdThread_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING))
|
||||
osdSpin_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING))
|
||||
osdMutex_CPPFLAGS += $(THREAD_CPPFLAGS_$(USE_POSIX_THREAD_PRIORITY_SCHEDULING))
|
||||
|
||||
Com_SRCS += osdThread.c
|
||||
Com_SRCS += osdThreadExtra.c
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* currently safe to convert a thread id to a thread name because
|
||||
* the thread may have exited making the thread id invalid.
|
||||
*/
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include <new>
|
||||
|
||||
@@ -223,6 +224,7 @@ void epicsStdCall epicsMutexShowAll(int onlyLocked,unsigned int level)
|
||||
|
||||
printf("ellCount(&mutexList) %d ellCount(&freeList) %d\n",
|
||||
ellCount(&mutexList),ellCount(&freeList));
|
||||
epicsMutexOsdShowAll();
|
||||
epicsMutexLockStatus lockStat =
|
||||
epicsMutexOsdLock(epicsMutexGlobalLock);
|
||||
assert ( lockStat == epicsMutexLockOK );
|
||||
|
||||
@@ -258,6 +258,9 @@ void epicsMutexOsdUnlock(struct epicsMutexOSD *);
|
||||
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD *);
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD *);
|
||||
void epicsMutexOsdShow(struct epicsMutexOSD *,unsigned int level);
|
||||
#ifdef EPICS_PRIVATE_API
|
||||
void epicsMutexOsdShowAll(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "../osi/osdNetIfAddrs.c"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../osi/osdNetIfAddrs.c"
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsEvent.h"
|
||||
@@ -193,3 +195,5 @@ LIBCOM_API void epicsMutexOsdShow(struct epicsMutexOSD * id,unsigned int level)
|
||||
#endif
|
||||
epicsEventShow ((epicsEventId)id,level);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void) {}
|
||||
|
||||
@@ -10,24 +10,31 @@
|
||||
#define EPICS_EXPOSE_LIBCOM_MONOTONIC_PRIVATE
|
||||
#include "dbDefs.h"
|
||||
#include "errlog.h"
|
||||
#include "cantProceed.h"
|
||||
#include "epicsTime.h"
|
||||
#include "generalTimeSup.h"
|
||||
|
||||
static unsigned char osdUsePrefCounter;
|
||||
static epicsUInt64 osdMonotonicResolution;
|
||||
static epicsUInt64 osdMonotonicResolution; /* timer resolution in nanoseconds */
|
||||
static epicsUInt64 perfCounterFrequency; /* performance counter tics per second */
|
||||
static LONGLONG perfCounterOffset; /* performance counter value at initialisation */
|
||||
static const epicsUInt64 sec2nsec = 1000000000; /* number of nanoseconds in a second */
|
||||
|
||||
void osdMonotonicInit(void)
|
||||
{
|
||||
LARGE_INTEGER freq, val;
|
||||
|
||||
if(!QueryPerformanceFrequency(&freq) ||
|
||||
!QueryPerformanceCounter(&val))
|
||||
{
|
||||
double period = 1.0/freq.QuadPart;
|
||||
osdMonotonicResolution = period*1e9;
|
||||
osdUsePrefCounter = 1;
|
||||
} else {
|
||||
osdMonotonicResolution = 1e6; /* 1 ms TODO place holder */
|
||||
/* QueryPerformanceCounter() is available on Windows 2000 and later, and is
|
||||
* guaranteed to succeed on Windows XP or later. On Windows 2000 it may
|
||||
* return 0 for freq.QuadPart if unavailable */
|
||||
if (QueryPerformanceFrequency(&freq) &&
|
||||
QueryPerformanceCounter(&val) &&
|
||||
freq.QuadPart != 0) {
|
||||
perfCounterFrequency = freq.QuadPart;
|
||||
perfCounterOffset = val.QuadPart;
|
||||
osdMonotonicResolution = sec2nsec / perfCounterFrequency +
|
||||
!!(sec2nsec % perfCounterFrequency);
|
||||
}
|
||||
else {
|
||||
cantProceed("osdMonotonicInit: Windows Performance Counter is not available\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,15 +46,11 @@ epicsUInt64 epicsMonotonicResolution(void)
|
||||
epicsUInt64 epicsMonotonicGet(void)
|
||||
{
|
||||
LARGE_INTEGER val;
|
||||
if(osdUsePrefCounter) {
|
||||
if(!QueryPerformanceCounter(&val)) {
|
||||
errMessage(errlogMinor, "Warning: failed to fetch performance counter\n");
|
||||
return 0;
|
||||
} else
|
||||
return val.QuadPart;
|
||||
} else {
|
||||
epicsUInt64 ret = GetTickCount();
|
||||
ret *= 1000000;
|
||||
return ret;
|
||||
double dval;
|
||||
if (!QueryPerformanceCounter(&val)) {
|
||||
cantProceed("epicsMonotonicGet: Failed to read Windows Performance Counter\n");
|
||||
return 0;
|
||||
}
|
||||
dval = val.QuadPart - perfCounterOffset;
|
||||
return (epicsUInt64)(dval * sec2nsec / perfCounterFrequency + 0.5);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include "libComAPI.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsAssert.h"
|
||||
@@ -176,3 +178,5 @@ void epicsMutexOsdShow ( epicsMutexOSD * pSem, unsigned level )
|
||||
}
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void) {}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "../osi/osdNetIfAddrs.c"
|
||||
@@ -1,351 +1 @@
|
||||
/*************************************************************************\
|
||||
* 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.
|
||||
* SPDX-License-Identifier: EPICS
|
||||
* EPICS Base is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Author: Jeff Hill
|
||||
* Date: 04-05-94
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "osiSock.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsThread.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
# define ifDepenDebugPrintf(argsInParen) printf argsInParen
|
||||
#else
|
||||
# define ifDepenDebugPrintf(argsInParen)
|
||||
#endif
|
||||
|
||||
static osiSockAddr osiLocalAddrResult;
|
||||
static epicsThreadOnceId osiLocalAddrId = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
/*
|
||||
* Determine the size of an ifreq structure
|
||||
* Made difficult by the fact that addresses larger than the structure
|
||||
* size may be returned from the kernel.
|
||||
*/
|
||||
static size_t ifreqSize ( struct ifreq *pifreq )
|
||||
{
|
||||
size_t size;
|
||||
|
||||
size = ifreq_size ( pifreq );
|
||||
if ( size < sizeof ( *pifreq ) ) {
|
||||
size = sizeof ( *pifreq );
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move to the next ifreq structure
|
||||
*/
|
||||
static struct ifreq * ifreqNext ( struct ifreq *pifreq )
|
||||
{
|
||||
struct ifreq *ifr;
|
||||
|
||||
ifr = ( struct ifreq * )( ifreqSize (pifreq) + ( char * ) pifreq );
|
||||
ifDepenDebugPrintf( ("ifreqNext() pifreq %p, size 0x%x, ifr 0x%p\n", pifreq, (unsigned)ifreqSize (pifreq), ifr) );
|
||||
return ifr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* osiSockDiscoverBroadcastAddresses ()
|
||||
*/
|
||||
LIBCOM_API void epicsStdCall osiSockDiscoverBroadcastAddresses
|
||||
(ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr)
|
||||
{
|
||||
static const unsigned nelem = 100;
|
||||
int status;
|
||||
struct ifconf ifconf;
|
||||
struct ifreq *pIfreqList;
|
||||
struct ifreq *pIfreqListEnd;
|
||||
struct ifreq *pifreq;
|
||||
struct ifreq *pnextifreq;
|
||||
osiSockAddrNode *pNewNode;
|
||||
|
||||
if ( pMatchAddr->sa.sa_family == AF_INET ) {
|
||||
if ( pMatchAddr->ia.sin_addr.s_addr == htonl (INADDR_LOOPBACK) ) {
|
||||
pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
|
||||
if ( pNewNode == NULL ) {
|
||||
errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
|
||||
return;
|
||||
}
|
||||
pNewNode->addr.ia.sin_family = AF_INET;
|
||||
pNewNode->addr.ia.sin_port = htons ( 0 );
|
||||
pNewNode->addr.ia.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
||||
ellAdd ( pList, &pNewNode->node );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* use pool so that we avoid using too much stack space
|
||||
*
|
||||
* nelem is set to the maximum interfaces
|
||||
* on one machine here
|
||||
*/
|
||||
pIfreqList = (struct ifreq *) calloc ( nelem, sizeof(*pifreq) );
|
||||
if (!pIfreqList) {
|
||||
errlogPrintf ("osiSockDiscoverBroadcastAddresses(): no memory to complete request\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ifconf.ifc_len = nelem * sizeof(*pifreq);
|
||||
ifconf.ifc_req = pIfreqList;
|
||||
status = socket_ioctl (socket, SIOCGIFCONF, &ifconf);
|
||||
if (status < 0 || ifconf.ifc_len == 0) {
|
||||
errlogPrintf ("osiSockDiscoverBroadcastAddresses(): unable to fetch network interface configuration (%d)\n", status);
|
||||
free (pIfreqList);
|
||||
return;
|
||||
}
|
||||
|
||||
pIfreqListEnd = (struct ifreq *) (ifconf.ifc_len + (char *) pIfreqList);
|
||||
pIfreqListEnd--;
|
||||
|
||||
for ( pifreq = pIfreqList; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) {
|
||||
uint32_t current_ifreqsize;
|
||||
|
||||
/*
|
||||
* find the next ifreq
|
||||
*/
|
||||
pnextifreq = ifreqNext (pifreq);
|
||||
|
||||
/* determine ifreq size */
|
||||
current_ifreqsize = ifreqSize ( pifreq );
|
||||
/* copy current ifreq to aligned bufferspace (to start of pIfreqList buffer) */
|
||||
memmove(pIfreqList, pifreq, current_ifreqsize);
|
||||
|
||||
ifDepenDebugPrintf (("osiSockDiscoverBroadcastAddresses(): found IFACE: %s len: 0x%x current_ifreqsize: 0x%x \n",
|
||||
pIfreqList->ifr_name,
|
||||
(unsigned)ifreq_size(pifreq),
|
||||
(unsigned)current_ifreqsize));
|
||||
|
||||
/*
|
||||
* If its not an internet interface then dont use it
|
||||
*/
|
||||
if ( pIfreqList->ifr_addr.sa_family != AF_INET ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): interface \"%s\" was not AF_INET\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if it isnt a wildcarded interface then look for
|
||||
* an exact match
|
||||
*/
|
||||
if ( pMatchAddr->sa.sa_family != AF_UNSPEC ) {
|
||||
if ( pMatchAddr->sa.sa_family != AF_INET ) {
|
||||
continue;
|
||||
}
|
||||
if ( pMatchAddr->ia.sin_addr.s_addr != htonl (INADDR_ANY) ) {
|
||||
struct sockaddr_in *pInetAddr = (struct sockaddr_in *) &pIfreqList->ifr_addr;
|
||||
if ( pInetAddr->sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" didnt match\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = socket_ioctl ( socket, SIOCGIFFLAGS, pIfreqList );
|
||||
if ( status ) {
|
||||
errlogPrintf ("osiSockDiscoverBroadcastAddresses(): net intf flags fetch for \"%s\" failed\n", pIfreqList->ifr_name);
|
||||
continue;
|
||||
}
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" flags: %x\n", pIfreqList->ifr_name, pIfreqList->ifr_flags) );
|
||||
|
||||
/*
|
||||
* dont bother with interfaces that have been disabled
|
||||
*/
|
||||
if ( ! ( pIfreqList->ifr_flags & IFF_UP ) ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" was down\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* dont use the loop back interface
|
||||
*/
|
||||
if ( pIfreqList->ifr_flags & IFF_LOOPBACK ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): ignoring loopback interface: \"%s\"\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
|
||||
if ( pNewNode == NULL ) {
|
||||
errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
|
||||
free ( pIfreqList );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is an interface that supports
|
||||
* broadcast fetch the broadcast address.
|
||||
*
|
||||
* Otherwise if this is a point to point
|
||||
* interface then use the destination address.
|
||||
*
|
||||
* Otherwise CA will not query through the
|
||||
* interface.
|
||||
*/
|
||||
if ( pIfreqList->ifr_flags & IFF_BROADCAST ) {
|
||||
osiSockAddr baddr;
|
||||
status = socket_ioctl (socket, SIOCGIFBRDADDR, pIfreqList);
|
||||
if ( status ) {
|
||||
errlogPrintf ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\": bcast addr fetch fail\n", pIfreqList->ifr_name);
|
||||
free ( pNewNode );
|
||||
continue;
|
||||
}
|
||||
baddr.sa = pIfreqList->ifr_broadaddr;
|
||||
if (baddr.ia.sin_family==AF_INET && baddr.ia.sin_addr.s_addr != INADDR_ANY) {
|
||||
pNewNode->addr.sa = pIfreqList->ifr_broadaddr;
|
||||
ifDepenDebugPrintf ( ( "found broadcast addr = %x\n", ntohl ( baddr.ia.sin_addr.s_addr ) ) );
|
||||
} else {
|
||||
ifDepenDebugPrintf ( ( "Ignoring broadcast addr = %x\n", ntohl ( baddr.ia.sin_addr.s_addr ) ) );
|
||||
free ( pNewNode );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#if defined (IFF_POINTOPOINT)
|
||||
else if ( pIfreqList->ifr_flags & IFF_POINTOPOINT ) {
|
||||
status = socket_ioctl ( socket, SIOCGIFDSTADDR, pIfreqList);
|
||||
if ( status ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\": pt to pt addr fetch fail\n", pIfreqList->ifr_name) );
|
||||
free ( pNewNode );
|
||||
continue;
|
||||
}
|
||||
pNewNode->addr.sa = pIfreqList->ifr_dstaddr;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
ifDepenDebugPrintf ( ( "osiSockDiscoverBroadcastAddresses(): net intf \"%s\": not point to point or bcast?\n", pIfreqList->ifr_name ) );
|
||||
free ( pNewNode );
|
||||
continue;
|
||||
}
|
||||
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" found\n", pIfreqList->ifr_name) );
|
||||
|
||||
/*
|
||||
* LOCK applied externally
|
||||
*/
|
||||
ellAdd ( pList, &pNewNode->node );
|
||||
}
|
||||
|
||||
free ( pIfreqList );
|
||||
}
|
||||
|
||||
/*
|
||||
* osiLocalAddr ()
|
||||
*/
|
||||
static void osiLocalAddrOnce (void *raw)
|
||||
{
|
||||
SOCKET *psocket = raw;
|
||||
const unsigned nelem = 100;
|
||||
osiSockAddr addr;
|
||||
int status;
|
||||
struct ifconf ifconf;
|
||||
struct ifreq *pIfreqList;
|
||||
struct ifreq *pifreq;
|
||||
struct ifreq *pIfreqListEnd;
|
||||
struct ifreq *pnextifreq;
|
||||
|
||||
memset ( (void *) &addr, '\0', sizeof ( addr ) );
|
||||
addr.sa.sa_family = AF_UNSPEC;
|
||||
|
||||
pIfreqList = (struct ifreq *) calloc ( nelem, sizeof(*pIfreqList) );
|
||||
if ( ! pIfreqList ) {
|
||||
errlogPrintf ( "osiLocalAddr(): no memory to complete request\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ifconf.ifc_len = nelem * sizeof ( *pIfreqList );
|
||||
ifconf.ifc_req = pIfreqList;
|
||||
status = socket_ioctl ( *psocket, SIOCGIFCONF, &ifconf );
|
||||
if ( status < 0 || ifconf.ifc_len == 0 ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf (
|
||||
"osiLocalAddr(): SIOCGIFCONF ioctl failed because \"%s\"\n",
|
||||
sockErrBuf );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pIfreqListEnd = (struct ifreq *) ( ifconf.ifc_len + (char *) ifconf.ifc_req );
|
||||
pIfreqListEnd--;
|
||||
|
||||
for ( pifreq = ifconf.ifc_req; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) {
|
||||
osiSockAddr addrCpy;
|
||||
uint32_t current_ifreqsize;
|
||||
|
||||
/*
|
||||
* find the next if req
|
||||
*/
|
||||
pnextifreq = ifreqNext ( pifreq );
|
||||
|
||||
/* determine ifreq size */
|
||||
current_ifreqsize = ifreqSize ( pifreq );
|
||||
/* copy current ifreq to aligned bufferspace (to start of pIfreqList buffer) */
|
||||
memmove(pIfreqList, pifreq, current_ifreqsize);
|
||||
|
||||
if ( pIfreqList->ifr_addr.sa_family != AF_INET ) {
|
||||
ifDepenDebugPrintf ( ("osiLocalAddr(): interface %s was not AF_INET\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
addrCpy.sa = pIfreqList->ifr_addr;
|
||||
|
||||
status = socket_ioctl ( *psocket, SIOCGIFFLAGS, pIfreqList );
|
||||
if ( status < 0 ) {
|
||||
errlogPrintf ( "osiLocalAddr(): net intf flags fetch for %s failed\n", pIfreqList->ifr_name );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! ( pIfreqList->ifr_flags & IFF_UP ) ) {
|
||||
ifDepenDebugPrintf ( ("osiLocalAddr(): net intf %s was down\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* dont use the loop back interface
|
||||
*/
|
||||
if ( pIfreqList->ifr_flags & IFF_LOOPBACK ) {
|
||||
ifDepenDebugPrintf ( ("osiLocalAddr(): ignoring loopback interface: %s\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
ifDepenDebugPrintf ( ("osiLocalAddr(): net intf %s found\n", pIfreqList->ifr_name) );
|
||||
|
||||
osiLocalAddrResult = addrCpy;
|
||||
free ( pIfreqList );
|
||||
return;
|
||||
}
|
||||
|
||||
errlogPrintf (
|
||||
"osiLocalAddr(): only loopback found\n");
|
||||
fail:
|
||||
/* fallback to loopback */
|
||||
memset ( (void *) &addr, '\0', sizeof ( addr ) );
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
osiLocalAddrResult = addr;
|
||||
|
||||
free ( pIfreqList );
|
||||
}
|
||||
|
||||
|
||||
LIBCOM_API osiSockAddr epicsStdCall osiLocalAddr (SOCKET socket)
|
||||
{
|
||||
epicsThreadOnce(&osiLocalAddrId, osiLocalAddrOnce, &socket);
|
||||
return osiLocalAddrResult;
|
||||
}
|
||||
#include "../osi/osdNetIfConf.c"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "../osi/osdNetIfAddrs.c"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../osi/osdNetIfAddrs.c"
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "epicsEvent.h"
|
||||
#include "epicsTime.h"
|
||||
#include "errlog.h"
|
||||
#include "osdPosixMutexPriv.h"
|
||||
|
||||
struct epicsEventOSD {
|
||||
pthread_mutex_t mutex;
|
||||
@@ -50,11 +51,11 @@ LIBCOM_API epicsEventId epicsEventCreate(epicsEventInitialState init)
|
||||
epicsEventId pevent = malloc(sizeof(*pevent));
|
||||
|
||||
if (pevent) {
|
||||
int status = pthread_mutex_init(&pevent->mutex, 0);
|
||||
int status = osdPosixMutexInit(&pevent->mutex, 0);
|
||||
|
||||
pevent->isFull = (init == epicsEventFull);
|
||||
if (status) {
|
||||
printStatus(status, "pthread_mutex_init", "epicsEventCreate");
|
||||
printStatus(status, "osdPosixMutexInit", "epicsEventCreate");
|
||||
} else {
|
||||
status = pthread_cond_init(&pevent->cond, 0);
|
||||
if (!status)
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
/* Author: Marty Kraimer Date: 13AUG1999 */
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -20,10 +24,14 @@
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include "epicsMutex.h"
|
||||
#include "osdPosixMutexPriv.h"
|
||||
#include "cantProceed.h"
|
||||
#include "epicsTime.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsAssert.h"
|
||||
|
||||
#define checkStatus(status,message) \
|
||||
@@ -38,6 +46,69 @@
|
||||
cantProceed((method)); \
|
||||
}
|
||||
|
||||
#if defined(DONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING)
|
||||
#undef _POSIX_THREAD_PRIO_INHERIT
|
||||
#endif
|
||||
|
||||
/* Global var - pthread_once does not support passing args but it is more efficient
|
||||
* than epicsThreadOnce which always acquires a mutex.
|
||||
*/
|
||||
static pthread_mutexattr_t globalAttrDefault;
|
||||
static pthread_mutexattr_t globalAttrRecursive;
|
||||
static pthread_once_t globalAttrInitOnce = PTHREAD_ONCE_INIT;
|
||||
|
||||
static void globalAttrInit()
|
||||
{
|
||||
int status;
|
||||
|
||||
status = pthread_mutexattr_init(&globalAttrDefault);
|
||||
checkStatusQuit(status,"pthread_mutexattr_init(&globalAttrDefault)","globalAttrInit");
|
||||
status = pthread_mutexattr_init(&globalAttrRecursive);
|
||||
checkStatusQuit(status,"pthread_mutexattr_init(&globalAttrRecursive)","globalAttrInit");
|
||||
status = pthread_mutexattr_settype(&globalAttrRecursive, PTHREAD_MUTEX_RECURSIVE);
|
||||
checkStatusQuit(status, "pthread_mutexattr_settype(&globalAttrRecursive, PTHREAD_MUTEX_RECURSIVE)", "globalAttrInit");
|
||||
#if defined _POSIX_THREAD_PRIO_INHERIT
|
||||
status = pthread_mutexattr_setprotocol(&globalAttrDefault, PTHREAD_PRIO_INHERIT);
|
||||
if (errVerbose) checkStatus(status, "pthread_mutexattr_setprotocol(&globalAttrDefault, PTHREAD_PRIO_INHERIT)");
|
||||
status = pthread_mutexattr_setprotocol(&globalAttrRecursive, PTHREAD_PRIO_INHERIT);
|
||||
if (errVerbose) checkStatus(status, "pthread_mutexattr_setprotocol(&globalAttrRecursive, PTHREAD_PRIO_INHERIT)");
|
||||
if (status == 0) {
|
||||
/* Can we really use PTHREAD_PRIO_INHERIT? */
|
||||
pthread_mutex_t temp;
|
||||
status = pthread_mutex_init(&temp, &globalAttrRecursive);
|
||||
if (errVerbose) checkStatus(status, "pthread_mutex_init(&temp, &globalAttrRecursive)");
|
||||
if (status != 0) {
|
||||
/* No, PTHREAD_PRIO_INHERIT does not work, fall back to PTHREAD_PRIO_NONE */;
|
||||
pthread_mutexattr_setprotocol(&globalAttrDefault, PTHREAD_PRIO_NONE);
|
||||
pthread_mutexattr_setprotocol(&globalAttrRecursive, PTHREAD_PRIO_NONE);
|
||||
} else {
|
||||
pthread_mutex_destroy(&temp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int osdPosixMutexInit (pthread_mutex_t *m, int mutextype)
|
||||
{
|
||||
pthread_mutexattr_t *atts;
|
||||
int status;
|
||||
|
||||
status = pthread_once( &globalAttrInitOnce, globalAttrInit );
|
||||
checkStatusQuit(status,"pthread_once","epicsPosixMutexAttrGet");
|
||||
|
||||
switch (mutextype) {
|
||||
case PTHREAD_MUTEX_DEFAULT:
|
||||
atts = &globalAttrDefault;
|
||||
break;
|
||||
case PTHREAD_MUTEX_RECURSIVE:
|
||||
atts = &globalAttrRecursive;
|
||||
break;
|
||||
default:
|
||||
return ENOTSUP;
|
||||
}
|
||||
return pthread_mutex_init(m, atts);
|
||||
}
|
||||
|
||||
static int mutexLock(pthread_mutex_t *id)
|
||||
{
|
||||
int status;
|
||||
@@ -48,23 +119,8 @@ static int mutexLock(pthread_mutex_t *id)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Until these can be demonstrated to work leave them undefined*/
|
||||
/* On solaris 8 _POSIX_THREAD_PRIO_INHERIT fails*/
|
||||
#undef _POSIX_THREAD_PROCESS_SHARED
|
||||
#undef _POSIX_THREAD_PRIO_INHERIT
|
||||
|
||||
/* Two completely different implementations are provided below
|
||||
* If support is available for PTHREAD_MUTEX_RECURSIVE then
|
||||
* only pthread_mutex is used.
|
||||
* If support is not available for PTHREAD_MUTEX_RECURSIVE then
|
||||
* a much more complicated solution is required
|
||||
*/
|
||||
|
||||
|
||||
#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE)>=500
|
||||
typedef struct epicsMutexOSD {
|
||||
pthread_mutex_t lock;
|
||||
pthread_mutexattr_t mutexAttr;
|
||||
} epicsMutexOSD;
|
||||
|
||||
epicsMutexOSD * epicsMutexOsdCreate(void) {
|
||||
@@ -73,32 +129,12 @@ epicsMutexOSD * epicsMutexOsdCreate(void) {
|
||||
|
||||
pmutex = calloc(1, sizeof(*pmutex));
|
||||
if(!pmutex)
|
||||
goto fail;
|
||||
return NULL;
|
||||
|
||||
status = pthread_mutexattr_init(&pmutex->mutexAttr);
|
||||
if (status)
|
||||
goto fail;
|
||||
status = osdPosixMutexInit(&pmutex->lock, PTHREAD_MUTEX_RECURSIVE);
|
||||
if (!status)
|
||||
return pmutex;
|
||||
|
||||
#if defined(_POSIX_THREAD_PRIO_INHERIT) && _POSIX_THREAD_PRIO_INHERIT > 0
|
||||
status = pthread_mutexattr_setprotocol(&pmutex->mutexAttr,
|
||||
PTHREAD_PRIO_INHERIT);
|
||||
if (errVerbose) checkStatus(status, "pthread_mutexattr_setprotocal");
|
||||
#endif /*_POSIX_THREAD_PRIO_INHERIT*/
|
||||
|
||||
status = pthread_mutexattr_settype(&pmutex->mutexAttr,
|
||||
PTHREAD_MUTEX_RECURSIVE);
|
||||
checkStatus(status, "pthread_mutexattr_settype");
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
status = pthread_mutex_init(&pmutex->lock, &pmutex->mutexAttr);
|
||||
if (status)
|
||||
goto dattr;
|
||||
return pmutex;
|
||||
|
||||
dattr:
|
||||
pthread_mutexattr_destroy(&pmutex->mutexAttr);
|
||||
fail:
|
||||
free(pmutex);
|
||||
return NULL;
|
||||
}
|
||||
@@ -109,11 +145,9 @@ void epicsMutexOsdDestroy(struct epicsMutexOSD * pmutex)
|
||||
|
||||
status = pthread_mutex_destroy(&pmutex->lock);
|
||||
checkStatus(status, "pthread_mutex_destroy");
|
||||
status = pthread_mutexattr_destroy(&pmutex->mutexAttr);
|
||||
checkStatus(status, "pthread_mutexattr_destroy");
|
||||
free(pmutex);
|
||||
}
|
||||
|
||||
|
||||
void epicsMutexOsdUnlock(struct epicsMutexOSD * pmutex)
|
||||
{
|
||||
int status;
|
||||
@@ -157,178 +191,14 @@ void epicsMutexOsdShow(struct epicsMutexOSD * pmutex, unsigned int level)
|
||||
*/
|
||||
printf(" pthread_mutex_t* uaddr=%p\n", &pmutex->lock);
|
||||
}
|
||||
|
||||
#else /*defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE)>=500 */
|
||||
|
||||
typedef struct epicsMutexOSD {
|
||||
pthread_mutex_t lock;
|
||||
pthread_mutexattr_t mutexAttr;
|
||||
pthread_cond_t waitToBeOwner;
|
||||
#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED > 0
|
||||
pthread_condattr_t condAttr;
|
||||
#endif /*_POSIX_THREAD_PROCESS_SHARED*/
|
||||
int count;
|
||||
int owned; /* TRUE | FALSE */
|
||||
pthread_t ownerTid;
|
||||
} epicsMutexOSD;
|
||||
|
||||
epicsMutexOSD * epicsMutexOsdCreate(void) {
|
||||
epicsMutexOSD *pmutex;
|
||||
int status;
|
||||
|
||||
pmutex = calloc(1, sizeof(*pmutex));
|
||||
if(!pmutex)
|
||||
return NULL;
|
||||
|
||||
status = pthread_mutexattr_init(&pmutex->mutexAttr);
|
||||
if(status)
|
||||
goto fail;
|
||||
|
||||
#if defined(_POSIX_THREAD_PRIO_INHERIT) && _POSIX_THREAD_PRIO_INHERIT > 0
|
||||
status = pthread_mutexattr_setprotocol(
|
||||
&pmutex->mutexAttr,PTHREAD_PRIO_INHERIT);
|
||||
if (errVerbose) checkStatus(status, "pthread_mutexattr_setprotocal");
|
||||
#endif /*_POSIX_THREAD_PRIO_INHERIT*/
|
||||
|
||||
status = pthread_mutex_init(&pmutex->lock, &pmutex->mutexAttr);
|
||||
if(status)
|
||||
goto dattr;
|
||||
|
||||
#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED > 0
|
||||
status = pthread_condattr_init(&pmutex->condAttr);
|
||||
checkStatus(status, "pthread_condattr_init");
|
||||
status = pthread_condattr_setpshared(&pmutex->condAttr,
|
||||
PTHREAD_PROCESS_PRIVATE);
|
||||
checkStatus(status, "pthread_condattr_setpshared");
|
||||
status = pthread_cond_init(&pmutex->waitToBeOwner, &pmutex->condAttr);
|
||||
#else
|
||||
status = pthread_cond_init(&pmutex->waitToBeOwner, 0);
|
||||
#endif /*_POSIX_THREAD_PROCESS_SHARED*/
|
||||
if(status)
|
||||
goto dmutex;
|
||||
|
||||
return pmutex;
|
||||
|
||||
dmutex:
|
||||
pthread_mutex_destroy(&pmutex->lock);
|
||||
dattr:
|
||||
pthread_mutexattr_destroy(&pmutex->mutexAttr);
|
||||
fail:
|
||||
free(pmutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void epicsMutexOsdDestroy(struct epicsMutexOSD * pmutex)
|
||||
void epicsMutexOsdShowAll(void)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = pthread_cond_destroy(&pmutex->waitToBeOwner);
|
||||
checkStatus(status, "pthread_cond_destroy");
|
||||
#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED > 0
|
||||
status = pthread_condattr_destroy(&pmutex->condAttr);
|
||||
#endif /*_POSIX_THREAD_PROCESS_SHARED*/
|
||||
status = pthread_mutex_destroy(&pmutex->lock);
|
||||
checkStatus(status, "pthread_mutex_destroy");
|
||||
status = pthread_mutexattr_destroy(&pmutex->mutexAttr);
|
||||
checkStatus(status, "pthread_mutexattr_destroy");
|
||||
free(pmutex);
|
||||
}
|
||||
|
||||
void epicsMutexOsdUnlock(struct epicsMutexOSD * pmutex)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = mutexLock(&pmutex->lock);
|
||||
checkStatus(status, "pthread_mutex_lock epicsMutexOsdUnlock");
|
||||
if(status)
|
||||
return;
|
||||
|
||||
if ((pmutex->count <= 0) || (pmutex->ownerTid != pthread_self())) {
|
||||
pthread_mutex_unlock(&pmutex->lock);
|
||||
checkStatus(status, "pthread_mutex_unlock epicsMutexOsdUnlock");
|
||||
errlogPrintf("epicsMutexOsdUnlock but caller is not owner\n");
|
||||
cantProceed("epicsMutexOsdUnlock but caller is not owner");
|
||||
return;
|
||||
}
|
||||
|
||||
pmutex->count--;
|
||||
if (pmutex->count == 0) {
|
||||
pmutex->owned = 0;
|
||||
pmutex->ownerTid = 0;
|
||||
status = pthread_cond_signal(&pmutex->waitToBeOwner);
|
||||
checkStatusQuit(status, "pthread_cond_signal epicsMutexOsdUnlock", "epicsMutexOsdUnlock");
|
||||
}
|
||||
|
||||
status = pthread_mutex_unlock(&pmutex->lock);
|
||||
checkStatus(status, "pthread_mutex_unlock epicsMutexOsdUnlock");
|
||||
}
|
||||
|
||||
static int condWait(pthread_cond_t *condId, pthread_mutex_t *mutexId)
|
||||
{
|
||||
int status;
|
||||
|
||||
while ((status = pthread_cond_wait(condId, mutexId)) == EINTR) {
|
||||
errlogPrintf("pthread_cond_wait returned EINTR. Violates SUSv3\n");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdLock(struct epicsMutexOSD * pmutex)
|
||||
{
|
||||
pthread_t tid = pthread_self();
|
||||
int status;
|
||||
|
||||
if (!pmutex || !tid) return epicsMutexLockError;
|
||||
status = mutexLock(&pmutex->lock);
|
||||
if (status == EINVAL) return epicsMutexLockError;
|
||||
checkStatus(status, "pthread_mutex_lock epicsMutexOsdLock");
|
||||
if(status)
|
||||
return epicsMutexLockError;
|
||||
|
||||
while (pmutex->owned && !pthread_equal(pmutex->ownerTid, tid))
|
||||
condWait(&pmutex->waitToBeOwner, &pmutex->lock);
|
||||
pmutex->ownerTid = tid;
|
||||
pmutex->owned = 1;
|
||||
pmutex->count++;
|
||||
|
||||
status = pthread_mutex_unlock(&pmutex->lock);
|
||||
checkStatus(status, "pthread_mutex_unlock epicsMutexOsdLock");
|
||||
if(status)
|
||||
return epicsMutexLockError;
|
||||
return epicsMutexLockOK;
|
||||
}
|
||||
|
||||
epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * pmutex)
|
||||
{
|
||||
pthread_t tid = pthread_self();
|
||||
epicsMutexLockStatus result;
|
||||
int status;
|
||||
|
||||
status = mutexLock(&pmutex->lock);
|
||||
if (status == EINVAL) return epicsMutexLockError;
|
||||
checkStatus(status, "pthread_mutex_lock epicsMutexOsdTryLock");
|
||||
if(status)
|
||||
return epicsMutexLockError;
|
||||
|
||||
if (!pmutex->owned || pthread_equal(pmutex->ownerTid, tid)) {
|
||||
pmutex->ownerTid = tid;
|
||||
pmutex->owned = 1;
|
||||
pmutex->count++;
|
||||
result = epicsMutexLockOK;
|
||||
int proto = -1;
|
||||
int ret = pthread_mutexattr_getprotocol(&globalAttrRecursive, &proto);
|
||||
if(ret) {
|
||||
printf("PI maybe not enabled: %d\n", ret);
|
||||
} else {
|
||||
result = epicsMutexLockTimeout;
|
||||
printf("PI is%s enabled\n", proto==PTHREAD_PRIO_INHERIT ? "" : " not");
|
||||
}
|
||||
|
||||
status = pthread_mutex_unlock(&pmutex->lock);
|
||||
checkStatus(status, "pthread_mutex_unlock epicsMutexOsdTryLock");
|
||||
if(status)
|
||||
return epicsMutexLockError;
|
||||
return result;
|
||||
}
|
||||
|
||||
void epicsMutexOsdShow(struct epicsMutexOSD *pmutex,unsigned int level)
|
||||
{
|
||||
printf("ownerTid %p count %d owned %d\n",
|
||||
(void *)pmutex->ownerTid, pmutex->count, pmutex->owned);
|
||||
}
|
||||
#endif /*defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE)>=500 */
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*************************************************************************\
|
||||
* 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.
|
||||
* SPDX-License-Identifier: EPICS
|
||||
* EPICS Base is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef osdPosixMutexPrivh
|
||||
#define osdPosixMutexPrivh
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Returns ENOTSUP if requested mutextype is not supported */
|
||||
/* At the moment, only 0 (default non recursive mutex) and PTHREAD_MUTEX_RECURSIVE are supported */
|
||||
int osdPosixMutexInit(pthread_mutex_t *,int mutextype);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* osdPosixMutexPrivh */
|
||||
@@ -109,6 +109,8 @@ void epicsSpinUnlock(epicsSpinId spin) {
|
||||
* POSIX MUTEX IMPLEMENTATION
|
||||
*/
|
||||
|
||||
#include <osdPosixMutexPriv.h>
|
||||
|
||||
typedef struct epicsSpin {
|
||||
pthread_mutex_t lock;
|
||||
} epicsSpin;
|
||||
@@ -121,8 +123,8 @@ epicsSpinId epicsSpinCreate(void) {
|
||||
if (!spin)
|
||||
goto fail;
|
||||
|
||||
status = pthread_mutex_init(&spin->lock, NULL);
|
||||
checkStatus(status, "pthread_mutex_init");
|
||||
status = osdPosixMutexInit(&spin->lock, 0);
|
||||
checkStatus(status, "osdPosixMutexInit");
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "ellLib.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "osdPosixMutexPriv.h"
|
||||
#include "epicsString.h"
|
||||
#include "epicsThread.h"
|
||||
#include "cantProceed.h"
|
||||
@@ -328,10 +329,10 @@ static void once(void)
|
||||
int status;
|
||||
|
||||
pthread_key_create(&getpthreadInfo,0);
|
||||
status = pthread_mutex_init(&onceLock,0);
|
||||
checkStatusOnceQuit(status,"pthread_mutex_init","epicsThreadInit");
|
||||
status = pthread_mutex_init(&listLock,0);
|
||||
checkStatusOnceQuit(status,"pthread_mutex_init","epicsThreadInit");
|
||||
status = osdPosixMutexInit(&onceLock,0);
|
||||
checkStatusOnceQuit(status,"osdPosixMutexInit","epicsThreadInit");
|
||||
status = osdPosixMutexInit(&listLock,0);
|
||||
checkStatusOnceQuit(status,"osdPosixMutexInit","epicsThreadInit");
|
||||
pcommonAttr = calloc(1,sizeof(commonAttr));
|
||||
if(!pcommonAttr) checkStatusOnceQuit(errno,"calloc","epicsThreadInit");
|
||||
status = pthread_attr_init(&pcommonAttr->attr);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
/* The following not defined in an vxWorks header */
|
||||
int sysClkRateGet(void);
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include "epicsMutex.h"
|
||||
|
||||
@@ -47,3 +48,5 @@ void epicsMutexOsdShow(struct epicsMutexOSD * id,unsigned int level)
|
||||
{
|
||||
semShow((SEM_ID)id,level);
|
||||
}
|
||||
|
||||
void epicsMutexOsdShowAll(void) {}
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/*************************************************************************\
|
||||
* 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.
|
||||
* SPDX-License-Identifier: EPICS
|
||||
* EPICS Base is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* This file included from various os/.../osdNetIntf.c */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "osiSock.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsThread.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
# define ifDepenDebugPrintf(argsInParen) printf argsInParen
|
||||
#else
|
||||
# define ifDepenDebugPrintf(argsInParen)
|
||||
#endif
|
||||
|
||||
static osiSockAddr osiLocalAddrResult;
|
||||
static epicsThreadOnceId osiLocalAddrId = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
/*
|
||||
* osiSockDiscoverBroadcastAddresses ()
|
||||
*/
|
||||
LIBCOM_API void epicsStdCall osiSockDiscoverBroadcastAddresses
|
||||
(ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr)
|
||||
{
|
||||
osiSockAddrNode *pNewNode;
|
||||
struct ifaddrs *ifa;
|
||||
|
||||
if ( pMatchAddr->sa.sa_family == AF_INET ) {
|
||||
if ( pMatchAddr->ia.sin_addr.s_addr == htonl (INADDR_LOOPBACK) ) {
|
||||
pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
|
||||
if ( pNewNode == NULL ) {
|
||||
errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
|
||||
return;
|
||||
}
|
||||
pNewNode->addr.ia.sin_family = AF_INET;
|
||||
pNewNode->addr.ia.sin_port = htons ( 0 );
|
||||
pNewNode->addr.ia.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
||||
ellAdd ( pList, &pNewNode->node );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct ifaddrs *ifaddr;
|
||||
int result = getifaddrs (&ifaddr);
|
||||
if ( result != 0 ) {
|
||||
errlogPrintf("osiSockDiscoverBroadcastAddresses(): getifaddrs failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next ) {
|
||||
if ( ifa->ifa_addr == NULL ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ifDepenDebugPrintf (("osiSockDiscoverBroadcastAddresses(): found IFACE: %s\n",
|
||||
ifa->ifa_name));
|
||||
|
||||
/*
|
||||
* If its not an internet interface then dont use it
|
||||
*/
|
||||
if ( ifa->ifa_addr->sa_family != AF_INET ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): interface \"%s\" was not AF_INET\n", ifa->ifa_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if it isnt a wildcarded interface then look for
|
||||
* an exact match
|
||||
*/
|
||||
if ( pMatchAddr->sa.sa_family != AF_UNSPEC ) {
|
||||
if ( pMatchAddr->sa.sa_family != AF_INET ) {
|
||||
continue;
|
||||
}
|
||||
if ( pMatchAddr->ia.sin_addr.s_addr != htonl (INADDR_ANY) ) {
|
||||
struct sockaddr_in *pInetAddr = (struct sockaddr_in *) ifa->ifa_addr;
|
||||
if ( pInetAddr->sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" didnt match\n", ifa->ifa_name) );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dont bother with interfaces that have been disabled
|
||||
*/
|
||||
if ( ! ( ifa->ifa_flags & IFF_UP ) ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" was down\n", ifa->ifa_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* dont use the loop back interface
|
||||
*/
|
||||
if ( ifa->ifa_flags & IFF_LOOPBACK ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): ignoring loopback interface: \"%s\"\n", ifa->ifa_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
|
||||
if ( pNewNode == NULL ) {
|
||||
errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
|
||||
freeifaddrs ( ifaddr );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is an interface that supports
|
||||
* broadcast use the broadcast address.
|
||||
*
|
||||
* Otherwise if this is a point to point
|
||||
* interface then use the destination address.
|
||||
*
|
||||
* Otherwise CA will not query through the
|
||||
* interface.
|
||||
*/
|
||||
if ( ifa->ifa_flags & IFF_BROADCAST ) {
|
||||
osiSockAddr baddr;
|
||||
baddr.sa = *ifa->ifa_broadaddr;
|
||||
if (baddr.ia.sin_family==AF_INET && baddr.ia.sin_addr.s_addr != INADDR_ANY) {
|
||||
pNewNode->addr.sa = *ifa->ifa_broadaddr;
|
||||
ifDepenDebugPrintf ( ( "found broadcast addr = %08x\n", ntohl ( baddr.ia.sin_addr.s_addr ) ) );
|
||||
} else {
|
||||
ifDepenDebugPrintf ( ( "Ignoring broadcast addr = %08x\n", ntohl ( baddr.ia.sin_addr.s_addr ) ) );
|
||||
free ( pNewNode );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#if defined (IFF_POINTOPOINT)
|
||||
else if ( ifa->ifa_flags & IFF_POINTOPOINT ) {
|
||||
pNewNode->addr.sa = *ifa->ifa_dstaddr;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
ifDepenDebugPrintf ( ( "osiSockDiscoverBroadcastAddresses(): net intf \"%s\": not point to point or bcast?\n", ifa->ifa_name ) );
|
||||
free ( pNewNode );
|
||||
continue;
|
||||
}
|
||||
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" found\n", ifa->ifa_name) );
|
||||
|
||||
/*
|
||||
* LOCK applied externally
|
||||
*/
|
||||
ellAdd ( pList, &pNewNode->node );
|
||||
}
|
||||
|
||||
freeifaddrs ( ifaddr );
|
||||
}
|
||||
|
||||
/*
|
||||
* osiLocalAddrOnce ()
|
||||
*/
|
||||
static void osiLocalAddrOnce (void *raw)
|
||||
{
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
int result = getifaddrs (&ifaddr);
|
||||
if ( result != 0 ) {
|
||||
errlogPrintf("osiLocalAddrOnce(): getifaddrs failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next ) {
|
||||
if ( ifa->ifa_addr == NULL ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! ( ifa->ifa_flags & IFF_UP ) ) {
|
||||
ifDepenDebugPrintf ( ("osiLocalAddrOnce(): net intf %s was down\n", ifa->ifa_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ifa->ifa_addr->sa_family != AF_INET ) {
|
||||
ifDepenDebugPrintf ( ("osiLocalAddrOnce(): interface %s was not AF_INET\n", ifa->ifa_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* dont use the loop back interface
|
||||
*/
|
||||
if ( ifa->ifa_flags & IFF_LOOPBACK ) {
|
||||
ifDepenDebugPrintf ( ("osiLocalAddrOnce(): ignoring loopback interface: %s\n", ifa->ifa_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
ifDepenDebugPrintf ( ("osiLocalAddr(): net intf %s found\n", ifa->ifa_name) );
|
||||
|
||||
osiLocalAddrResult.sa = *ifa->ifa_addr;
|
||||
freeifaddrs ( ifaddr );
|
||||
return;
|
||||
}
|
||||
|
||||
errlogPrintf (
|
||||
"osiLocalAddr(): only loopback found\n");
|
||||
/* fallback to loopback */
|
||||
osiSockAddr addr;
|
||||
memset ( (void *) &addr, '\0', sizeof ( addr ) );
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
osiLocalAddrResult = addr;
|
||||
|
||||
freeifaddrs ( ifaddr );
|
||||
}
|
||||
|
||||
|
||||
LIBCOM_API osiSockAddr epicsStdCall osiLocalAddr (SOCKET socket)
|
||||
{
|
||||
epicsThreadOnce(&osiLocalAddrId, osiLocalAddrOnce, &socket);
|
||||
return osiLocalAddrResult;
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
/*************************************************************************\
|
||||
* 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.
|
||||
* SPDX-License-Identifier: EPICS
|
||||
* EPICS Base is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* This file included from various os/.../osdNetIntf.c */
|
||||
|
||||
/*
|
||||
* Author: Jeff Hill
|
||||
* Date: 04-05-94
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "osiSock.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsThread.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
# define ifDepenDebugPrintf(argsInParen) printf argsInParen
|
||||
#else
|
||||
# define ifDepenDebugPrintf(argsInParen)
|
||||
#endif
|
||||
|
||||
static osiSockAddr osiLocalAddrResult;
|
||||
static epicsThreadOnceId osiLocalAddrId = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
/*
|
||||
* Determine the size of an ifreq structure
|
||||
* Made difficult by the fact that addresses larger than the structure
|
||||
* size may be returned from the kernel.
|
||||
*/
|
||||
static size_t ifreqSize ( struct ifreq *pifreq )
|
||||
{
|
||||
size_t size;
|
||||
|
||||
size = ifreq_size ( pifreq );
|
||||
if ( size < sizeof ( *pifreq ) ) {
|
||||
size = sizeof ( *pifreq );
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move to the next ifreq structure
|
||||
*/
|
||||
static struct ifreq * ifreqNext ( struct ifreq *pifreq )
|
||||
{
|
||||
struct ifreq *ifr;
|
||||
|
||||
ifr = ( struct ifreq * )( ifreqSize (pifreq) + ( char * ) pifreq );
|
||||
ifDepenDebugPrintf( ("ifreqNext() pifreq %p, size 0x%x, ifr 0x%p\n", pifreq, (unsigned)ifreqSize (pifreq), ifr) );
|
||||
return ifr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* osiSockDiscoverBroadcastAddresses ()
|
||||
*/
|
||||
LIBCOM_API void epicsStdCall osiSockDiscoverBroadcastAddresses
|
||||
(ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr)
|
||||
{
|
||||
static const unsigned nelem = 100;
|
||||
int status;
|
||||
struct ifconf ifconf;
|
||||
struct ifreq *pIfreqList;
|
||||
struct ifreq *pIfreqListEnd;
|
||||
struct ifreq *pifreq;
|
||||
struct ifreq *pnextifreq;
|
||||
osiSockAddrNode *pNewNode;
|
||||
|
||||
if ( pMatchAddr->sa.sa_family == AF_INET ) {
|
||||
if ( pMatchAddr->ia.sin_addr.s_addr == htonl (INADDR_LOOPBACK) ) {
|
||||
pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
|
||||
if ( pNewNode == NULL ) {
|
||||
errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
|
||||
return;
|
||||
}
|
||||
pNewNode->addr.ia.sin_family = AF_INET;
|
||||
pNewNode->addr.ia.sin_port = htons ( 0 );
|
||||
pNewNode->addr.ia.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
||||
ellAdd ( pList, &pNewNode->node );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* use pool so that we avoid using too much stack space
|
||||
*
|
||||
* nelem is set to the maximum interfaces
|
||||
* on one machine here
|
||||
*/
|
||||
pIfreqList = (struct ifreq *) calloc ( nelem, sizeof(*pifreq) );
|
||||
if (!pIfreqList) {
|
||||
errlogPrintf ("osiSockDiscoverBroadcastAddresses(): no memory to complete request\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ifconf.ifc_len = nelem * sizeof(*pifreq);
|
||||
ifconf.ifc_req = pIfreqList;
|
||||
status = socket_ioctl (socket, SIOCGIFCONF, &ifconf);
|
||||
if (status < 0 || ifconf.ifc_len == 0) {
|
||||
errlogPrintf ("osiSockDiscoverBroadcastAddresses(): unable to fetch network interface configuration (%d)\n", status);
|
||||
free (pIfreqList);
|
||||
return;
|
||||
}
|
||||
|
||||
pIfreqListEnd = (struct ifreq *) (ifconf.ifc_len + (char *) pIfreqList);
|
||||
pIfreqListEnd--;
|
||||
|
||||
for ( pifreq = pIfreqList; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) {
|
||||
uint32_t current_ifreqsize;
|
||||
|
||||
/*
|
||||
* find the next ifreq
|
||||
*/
|
||||
pnextifreq = ifreqNext (pifreq);
|
||||
|
||||
/* determine ifreq size */
|
||||
current_ifreqsize = ifreqSize ( pifreq );
|
||||
/* copy current ifreq to aligned bufferspace (to start of pIfreqList buffer) */
|
||||
memmove(pIfreqList, pifreq, current_ifreqsize);
|
||||
|
||||
ifDepenDebugPrintf (("osiSockDiscoverBroadcastAddresses(): found IFACE: %s len: 0x%x current_ifreqsize: 0x%x \n",
|
||||
pIfreqList->ifr_name,
|
||||
(unsigned)ifreq_size(pifreq),
|
||||
(unsigned)current_ifreqsize));
|
||||
|
||||
/*
|
||||
* If its not an internet interface then dont use it
|
||||
*/
|
||||
if ( pIfreqList->ifr_addr.sa_family != AF_INET ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): interface \"%s\" was not AF_INET\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if it isnt a wildcarded interface then look for
|
||||
* an exact match
|
||||
*/
|
||||
if ( pMatchAddr->sa.sa_family != AF_UNSPEC ) {
|
||||
if ( pMatchAddr->sa.sa_family != AF_INET ) {
|
||||
continue;
|
||||
}
|
||||
if ( pMatchAddr->ia.sin_addr.s_addr != htonl (INADDR_ANY) ) {
|
||||
struct sockaddr_in *pInetAddr = (struct sockaddr_in *) &pIfreqList->ifr_addr;
|
||||
if ( pInetAddr->sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" didnt match\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = socket_ioctl ( socket, SIOCGIFFLAGS, pIfreqList );
|
||||
if ( status ) {
|
||||
errlogPrintf ("osiSockDiscoverBroadcastAddresses(): net intf flags fetch for \"%s\" failed\n", pIfreqList->ifr_name);
|
||||
continue;
|
||||
}
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" flags: %x\n", pIfreqList->ifr_name, pIfreqList->ifr_flags) );
|
||||
|
||||
/*
|
||||
* dont bother with interfaces that have been disabled
|
||||
*/
|
||||
if ( ! ( pIfreqList->ifr_flags & IFF_UP ) ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" was down\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* dont use the loop back interface
|
||||
*/
|
||||
if ( pIfreqList->ifr_flags & IFF_LOOPBACK ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): ignoring loopback interface: \"%s\"\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
|
||||
if ( pNewNode == NULL ) {
|
||||
errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
|
||||
free ( pIfreqList );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is an interface that supports
|
||||
* broadcast fetch the broadcast address.
|
||||
*
|
||||
* Otherwise if this is a point to point
|
||||
* interface then use the destination address.
|
||||
*
|
||||
* Otherwise CA will not query through the
|
||||
* interface.
|
||||
*/
|
||||
if ( pIfreqList->ifr_flags & IFF_BROADCAST ) {
|
||||
osiSockAddr baddr;
|
||||
status = socket_ioctl (socket, SIOCGIFBRDADDR, pIfreqList);
|
||||
if ( status ) {
|
||||
errlogPrintf ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\": bcast addr fetch fail\n", pIfreqList->ifr_name);
|
||||
free ( pNewNode );
|
||||
continue;
|
||||
}
|
||||
baddr.sa = pIfreqList->ifr_broadaddr;
|
||||
if (baddr.ia.sin_family==AF_INET && baddr.ia.sin_addr.s_addr != INADDR_ANY) {
|
||||
pNewNode->addr.sa = pIfreqList->ifr_broadaddr;
|
||||
ifDepenDebugPrintf ( ( "found broadcast addr = %x\n", ntohl ( baddr.ia.sin_addr.s_addr ) ) );
|
||||
} else {
|
||||
ifDepenDebugPrintf ( ( "Ignoring broadcast addr = %x\n", ntohl ( baddr.ia.sin_addr.s_addr ) ) );
|
||||
free ( pNewNode );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#if defined (IFF_POINTOPOINT)
|
||||
else if ( pIfreqList->ifr_flags & IFF_POINTOPOINT ) {
|
||||
status = socket_ioctl ( socket, SIOCGIFDSTADDR, pIfreqList);
|
||||
if ( status ) {
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\": pt to pt addr fetch fail\n", pIfreqList->ifr_name) );
|
||||
free ( pNewNode );
|
||||
continue;
|
||||
}
|
||||
pNewNode->addr.sa = pIfreqList->ifr_dstaddr;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
ifDepenDebugPrintf ( ( "osiSockDiscoverBroadcastAddresses(): net intf \"%s\": not point to point or bcast?\n", pIfreqList->ifr_name ) );
|
||||
free ( pNewNode );
|
||||
continue;
|
||||
}
|
||||
|
||||
ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" found\n", pIfreqList->ifr_name) );
|
||||
|
||||
/*
|
||||
* LOCK applied externally
|
||||
*/
|
||||
ellAdd ( pList, &pNewNode->node );
|
||||
}
|
||||
|
||||
free ( pIfreqList );
|
||||
}
|
||||
|
||||
/*
|
||||
* osiLocalAddr ()
|
||||
*/
|
||||
static void osiLocalAddrOnce (void *raw)
|
||||
{
|
||||
SOCKET *psocket = raw;
|
||||
const unsigned nelem = 100;
|
||||
osiSockAddr addr;
|
||||
int status;
|
||||
struct ifconf ifconf;
|
||||
struct ifreq *pIfreqList;
|
||||
struct ifreq *pifreq;
|
||||
struct ifreq *pIfreqListEnd;
|
||||
struct ifreq *pnextifreq;
|
||||
|
||||
memset ( (void *) &addr, '\0', sizeof ( addr ) );
|
||||
addr.sa.sa_family = AF_UNSPEC;
|
||||
|
||||
pIfreqList = (struct ifreq *) calloc ( nelem, sizeof(*pIfreqList) );
|
||||
if ( ! pIfreqList ) {
|
||||
errlogPrintf ( "osiLocalAddr(): no memory to complete request\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ifconf.ifc_len = nelem * sizeof ( *pIfreqList );
|
||||
ifconf.ifc_req = pIfreqList;
|
||||
status = socket_ioctl ( *psocket, SIOCGIFCONF, &ifconf );
|
||||
if ( status < 0 || ifconf.ifc_len == 0 ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf (
|
||||
"osiLocalAddr(): SIOCGIFCONF ioctl failed because \"%s\"\n",
|
||||
sockErrBuf );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pIfreqListEnd = (struct ifreq *) ( ifconf.ifc_len + (char *) ifconf.ifc_req );
|
||||
pIfreqListEnd--;
|
||||
|
||||
for ( pifreq = ifconf.ifc_req; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) {
|
||||
osiSockAddr addrCpy;
|
||||
uint32_t current_ifreqsize;
|
||||
|
||||
/*
|
||||
* find the next if req
|
||||
*/
|
||||
pnextifreq = ifreqNext ( pifreq );
|
||||
|
||||
/* determine ifreq size */
|
||||
current_ifreqsize = ifreqSize ( pifreq );
|
||||
/* copy current ifreq to aligned bufferspace (to start of pIfreqList buffer) */
|
||||
memmove(pIfreqList, pifreq, current_ifreqsize);
|
||||
|
||||
if ( pIfreqList->ifr_addr.sa_family != AF_INET ) {
|
||||
ifDepenDebugPrintf ( ("osiLocalAddr(): interface %s was not AF_INET\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
addrCpy.sa = pIfreqList->ifr_addr;
|
||||
|
||||
status = socket_ioctl ( *psocket, SIOCGIFFLAGS, pIfreqList );
|
||||
if ( status < 0 ) {
|
||||
errlogPrintf ( "osiLocalAddr(): net intf flags fetch for %s failed\n", pIfreqList->ifr_name );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! ( pIfreqList->ifr_flags & IFF_UP ) ) {
|
||||
ifDepenDebugPrintf ( ("osiLocalAddr(): net intf %s was down\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* dont use the loop back interface
|
||||
*/
|
||||
if ( pIfreqList->ifr_flags & IFF_LOOPBACK ) {
|
||||
ifDepenDebugPrintf ( ("osiLocalAddr(): ignoring loopback interface: %s\n", pIfreqList->ifr_name) );
|
||||
continue;
|
||||
}
|
||||
|
||||
ifDepenDebugPrintf ( ("osiLocalAddr(): net intf %s found\n", pIfreqList->ifr_name) );
|
||||
|
||||
osiLocalAddrResult = addrCpy;
|
||||
free ( pIfreqList );
|
||||
return;
|
||||
}
|
||||
|
||||
errlogPrintf (
|
||||
"osiLocalAddr(): only loopback found\n");
|
||||
fail:
|
||||
/* fallback to loopback */
|
||||
memset ( (void *) &addr, '\0', sizeof ( addr ) );
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
osiLocalAddrResult = addr;
|
||||
|
||||
free ( pIfreqList );
|
||||
}
|
||||
|
||||
|
||||
LIBCOM_API osiSockAddr epicsStdCall osiLocalAddr (SOCKET socket)
|
||||
{
|
||||
epicsThreadOnce(&osiLocalAddrId, osiLocalAddrOnce, &socket);
|
||||
return osiLocalAddrResult;
|
||||
}
|
||||
Reference in New Issue
Block a user