mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-06 00:13:33 +00:00
Fixed semaphores on MacOS
This commit is contained in:
@@ -109,6 +109,17 @@ char ILibScratchPad[4096]; // General buffer
|
||||
char ILibScratchPad2[65536]; // Often used for UDP packet processing
|
||||
void* gILibChain = NULL; // Global Chain Instance used for Remote Logging when a chain instance isn't otherwise exposed
|
||||
|
||||
#define ILibChain_SIGMAX 32
|
||||
ILibLinkedList g_signalHandlers[ILibChain_SIGMAX] = { NULL };
|
||||
typedef struct ILibChain_SignalHandlerData
|
||||
{
|
||||
ILibChain_Link link;
|
||||
int ipc[2];
|
||||
int signum;
|
||||
ILibChain_SignalHandler handler;
|
||||
void *user;
|
||||
}ILibChain_SignalHandlerData;
|
||||
|
||||
#define INET_SOCKADDR_LENGTH(x) ((x==AF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)))
|
||||
|
||||
long long ILibGetUptime();
|
||||
@@ -333,151 +344,28 @@ int ILibGetLocalIPAddressNetMask(unsigned int address)
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
void* semaphore_table[2048] = { 0 };
|
||||
void ILibDispatchSemaphore_Init(sem_t* s, int pShared, int value)
|
||||
{
|
||||
dispatch_semaphore_t ds;
|
||||
int i;
|
||||
for (i = 0; i < 2048; ++i)
|
||||
{
|
||||
if (semaphore_table[i] == NULL)
|
||||
{
|
||||
// This index is free
|
||||
ds = dispatch_semaphore_create((long)value);
|
||||
semaphore_table[i] = (void*)ds;
|
||||
((int*)s)[0] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*s = dispatch_semaphore_create((long)value);
|
||||
}
|
||||
void ILibDispatchSemaphore_Destroy(sem_t* s)
|
||||
{
|
||||
int i = ((int*)s)[0];
|
||||
dispatch_semaphore_t ds = (dispatch_semaphore_t)semaphore_table[i];
|
||||
semaphore_table[i] = NULL;
|
||||
if (ds != NULL)
|
||||
{
|
||||
dispatch_release(ds);
|
||||
}
|
||||
dispatch_release(((dispatch_semaphore_t*)s)[0]);
|
||||
}
|
||||
void ILibDispatchSemaphore_wait(sem_t* s)
|
||||
{
|
||||
dispatch_semaphore_wait((dispatch_semaphore_t)semaphore_table[((int*)s)[0]], DISPATCH_TIME_FOREVER);
|
||||
dispatch_semaphore_wait(((dispatch_semaphore_t*)s)[0], DISPATCH_TIME_FOREVER);
|
||||
}
|
||||
void ILibDispatchSemaphore_trywait(sem_t* s)
|
||||
{
|
||||
dispatch_semaphore_wait((dispatch_semaphore_t)semaphore_table[((int*)s)[0]], DISPATCH_TIME_NOW);
|
||||
dispatch_semaphore_wait(((dispatch_semaphore_t*)s)[0], DISPATCH_TIME_NOW);
|
||||
}
|
||||
void ILibDispatchSemaphore_post(sem_t* s)
|
||||
{
|
||||
dispatch_semaphore_signal((dispatch_semaphore_t)semaphore_table[((int*)s)[0]]);
|
||||
dispatch_semaphore_signal(((dispatch_semaphore_t*)s)[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
#if defined(__APPLE__)
|
||||
// #if defined (__IPHONE_OS_VERSION_MIN_REQUIRED) // lame check for iPhone
|
||||
|
||||
// several places the same check for interface, two functions identical, but returning
|
||||
// slightly different form of interfaces
|
||||
|
||||
// Helper functions
|
||||
typedef void * (* FN_GETMEM) (int ctr);
|
||||
typedef void (* FN_STOREVAL) (int ctr, void * p, struct ifaddrs * ifa);
|
||||
|
||||
static int IsMacIPv4Address (struct ifaddrs * ifa);
|
||||
static int GetMacIPv4AddressesCount (struct ifaddrs * ifa);
|
||||
static void StoreValInt (int ctr, void * p, struct ifaddrs * ifa);
|
||||
static void * GetAddressMemInt (int ctr);
|
||||
static void StoreValStruct (int ctr, void * p, struct ifaddrs * ifa);
|
||||
static void * GetAddressMemStruct (int ctr);
|
||||
|
||||
int IsMacIPv4Address(struct ifaddrs * ifa)
|
||||
{
|
||||
// This should pick up eth0.. (desktop) or en0.. (mac / iphone)
|
||||
#if defined (__IPHONE_OS_VERSION_MIN_REQUIRED)
|
||||
return (ifa->ifa_addr->sa_family == AF_INET && // is it IP4
|
||||
strncmp (ifa->ifa_name, "pdp_ip", 6) != 0 && // iPhone is using it for 3G
|
||||
strncmp (ifa->ifa_name, "lo0", 3) != 0); // is it not lo0
|
||||
#else
|
||||
return (ifa->ifa_addr->sa_family == AF_INET && // is it IP4
|
||||
strncmp (ifa->ifa_name, "lo0", 3) != 0); // is it not lo0
|
||||
#endif
|
||||
}
|
||||
|
||||
int GetMacIPv4AddressesCount(struct ifaddrs * pifa)
|
||||
{
|
||||
int ctr = 0;
|
||||
while (pifa != NULL)
|
||||
{
|
||||
if (IsMacIPv4Address (pifa)) ctr++;
|
||||
pifa = pifa->ifa_next;
|
||||
}
|
||||
return ctr;
|
||||
}
|
||||
|
||||
void StoreValInt(int ctr, void * p, struct ifaddrs * pifa)
|
||||
{
|
||||
if (!p || !pifa) return;
|
||||
*((int *)p + ctr) = ((struct sockaddr_in *)pifa->ifa_addr)->sin_addr.s_addr;
|
||||
}
|
||||
|
||||
void* GetAddressMemInt(int ctr)
|
||||
{
|
||||
int * p;
|
||||
if (0 >= ctr) return NULL;
|
||||
if ((p = (int *)malloc (sizeof (int) * ctr)) == NULL) ILIBCRITICALEXIT(254);
|
||||
return (void *)p;
|
||||
}
|
||||
|
||||
void StoreValStruct(int ctr, void * p, struct ifaddrs * pifa)
|
||||
{
|
||||
if (!p || !pifa) return;
|
||||
memcpy ((struct sockaddr_in *)p + ctr, (struct sockaddr_in *)pifa->ifa_addr, sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
void* GetAddressMemStruct(int ctr)
|
||||
{
|
||||
struct sockaddr_in *p;
|
||||
if (0 >= ctr) return NULL;
|
||||
if ((p = (struct sockaddr_in *)malloc (sizeof (struct sockaddr_in) * ctr)) == NULL) ILIBCRITICALEXIT(254);
|
||||
return (void *)p;
|
||||
}
|
||||
|
||||
int GetMacIPv4Addresses(void** pp, FN_GETMEM fnGetMem, FN_STOREVAL fnStoreVal)
|
||||
{
|
||||
int ctr = 0;
|
||||
struct ifaddrs * ifaddr, * ifa;
|
||||
*pp = NULL;
|
||||
|
||||
if (getifaddrs(&ifaddr) != 0) return 0;
|
||||
|
||||
// Count valid IPv4 interfaces
|
||||
if (0 < (ctr = GetMacIPv4AddressesCount (ifaddr)))
|
||||
{
|
||||
*pp = (*fnGetMem)(ctr);
|
||||
|
||||
ctr = 0;
|
||||
ifa = ifaddr;
|
||||
// Copy valid IPv4 interfaces addresses
|
||||
while (NULL != ifa)
|
||||
{
|
||||
if (IsMacIPv4Address(ifa))
|
||||
{
|
||||
(*fnStoreVal)(ctr, *pp, ifa);
|
||||
ctr++;
|
||||
}
|
||||
|
||||
ifa = ifa->ifa_next;
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
return ctr;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
//! Fetches the list of valid IPv4 adapters
|
||||
/*!
|
||||
\param[out] addresslist sockaddr_in array of adapters
|
||||
@@ -648,78 +536,6 @@ int ILibGetLocalIPv4AddressList(struct sockaddr_in** addresslist, int includeloo
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
// Get the list of valid IPv6 adapters, skip loopback and other junk adapters.
|
||||
int ILibGetLocalIPv6AddressList(struct sockaddr_in6** addresslist)
|
||||
{
|
||||
#if defined(WINSOCK2)
|
||||
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
|
||||
PIP_ADAPTER_ADDRESSES pAddressesPtr = NULL;
|
||||
PIP_ADAPTER_UNICAST_ADDRESS_LH AddrPtr;
|
||||
ULONG outBufLen = sizeof(IP_ADAPTER_ADDRESSES);
|
||||
int AddrCount = 0;
|
||||
struct sockaddr_in6 *ptr;
|
||||
|
||||
// Perform first call
|
||||
pAddresses = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen);
|
||||
if (GetAdaptersAddresses(AF_INET6, GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
free(pAddresses);
|
||||
pAddresses = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen);
|
||||
}
|
||||
|
||||
// Perform second call
|
||||
if (GetAdaptersAddresses(AF_INET6, GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST, NULL, pAddresses, &outBufLen) != NO_ERROR)
|
||||
{
|
||||
free(pAddresses);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Count the total number of local IPv6 addresses
|
||||
pAddressesPtr = pAddresses;
|
||||
while (pAddressesPtr != NULL)
|
||||
{
|
||||
// Skip any loopback adapters
|
||||
if (pAddressesPtr->PhysicalAddressLength != 0 && pAddressesPtr->NoMulticast == 0)
|
||||
{
|
||||
// For each adapter
|
||||
AddrPtr = pAddressesPtr->FirstUnicastAddress;
|
||||
while (AddrPtr != NULL)
|
||||
{
|
||||
AddrCount++;
|
||||
AddrPtr = AddrPtr->Next;
|
||||
}
|
||||
}
|
||||
pAddressesPtr = pAddressesPtr->Next;
|
||||
}
|
||||
|
||||
// Allocate the array of IPv6 addresses
|
||||
*addresslist = ptr = malloc(AddrCount * sizeof(struct sockaddr_in6));
|
||||
|
||||
// Copy each address into the array
|
||||
pAddressesPtr = pAddresses;
|
||||
while (pAddressesPtr != NULL)
|
||||
{
|
||||
// Skip any loopback adapters
|
||||
if (pAddressesPtr->PhysicalAddressLength != 0 && pAddressesPtr->NoMulticast == 0)
|
||||
{
|
||||
// For each adapter
|
||||
AddrPtr = pAddressesPtr->FirstUnicastAddress;
|
||||
while (AddrPtr != NULL)
|
||||
{
|
||||
memcpy(ptr, AddrPtr->Address.lpSockaddr, sizeof(struct sockaddr_in6));
|
||||
ptr++;
|
||||
AddrPtr = AddrPtr->Next;
|
||||
}
|
||||
}
|
||||
pAddressesPtr = pAddressesPtr->Next;
|
||||
}
|
||||
|
||||
free(pAddresses);
|
||||
return AddrCount;
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
//! Get the list of valid IPv6 adapter indexes, skip loopback and other junk adapters.
|
||||
/*!
|
||||
@@ -1709,6 +1525,162 @@ void ILibChain_SafeAddSink(void *object)
|
||||
free(data);
|
||||
}
|
||||
|
||||
#ifdef _POSIX
|
||||
void ILibChain_SignalSink(int signum)
|
||||
{
|
||||
if (g_signalHandlers[signum] != NULL)
|
||||
{
|
||||
void *node = ILibLinkedList_GetNode_Head(g_signalHandlers[signum]);
|
||||
while (node != NULL)
|
||||
{
|
||||
ignore_result(write(((ILibChain_SignalHandlerData*)ILibLinkedList_GetDataFromNode(node))->ipc[1], " ", 1));
|
||||
node = ILibLinkedList_GetNextNode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ILibChain_SignalHandler_DestroySelect(void* object)
|
||||
{
|
||||
ILibChain_SignalHandlerData *data = (ILibChain_SignalHandlerData*)object;
|
||||
void *node;
|
||||
struct sigaction action;
|
||||
struct sigaction ignore;
|
||||
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
sigemptyset(&ignore.sa_mask);
|
||||
ignore.sa_flags = 0;
|
||||
|
||||
if (sigaction(data->signum, &ignore, &action) == 0)
|
||||
{
|
||||
close(data->ipc[0]);
|
||||
close(data->ipc[1]);
|
||||
|
||||
if (g_signalHandlers[data->signum] != NULL)
|
||||
{
|
||||
node = ILibLinkedList_GetNode_Search(g_signalHandlers[data->signum], NULL, data);
|
||||
if (node != NULL) { ILibLinkedList_Remove(node); }
|
||||
if (ILibLinkedList_GetCount(g_signalHandlers[data->signum]) == 0)
|
||||
{
|
||||
ILibLinkedList_Destroy(g_signalHandlers[data->signum]);
|
||||
g_signalHandlers[data->signum] = NULL;
|
||||
}
|
||||
}
|
||||
sigaction(data->signum, &action, NULL);
|
||||
}
|
||||
}
|
||||
void ILibChain_SignalHandler_PostSelect(void* object, int slct, fd_set *readset, fd_set *writeset, fd_set *errorset)
|
||||
{
|
||||
int vX;
|
||||
ILibChain_SignalHandlerData *data = (ILibChain_SignalHandlerData*)object;
|
||||
if (FD_ISSET(data->ipc[0], readset))
|
||||
{
|
||||
while ((vX = read(data->ipc[0], ILibScratchPad, sizeof(ILibScratchPad))) > 0); // Empty the pipe
|
||||
if (data->handler != NULL) { data->handler(data->link.ParentChain, data->signum, data->user); } // Dispatch the signal
|
||||
}
|
||||
|
||||
UNREFERENCED_PARAMETER(slct);
|
||||
UNREFERENCED_PARAMETER(writeset);
|
||||
UNREFERENCED_PARAMETER(errorset);
|
||||
}
|
||||
void ILibChain_SignalHandler_PreSelect(void* object, fd_set *readset, fd_set *writeset, fd_set *errorset, int* blocktime)
|
||||
{
|
||||
ILibChain_SignalHandlerData *data = (ILibChain_SignalHandlerData*)object;
|
||||
FD_SET(data->ipc[0], readset);
|
||||
|
||||
UNREFERENCED_PARAMETER(writeset);
|
||||
UNREFERENCED_PARAMETER(errorset);
|
||||
UNREFERENCED_PARAMETER(blocktime);
|
||||
}
|
||||
int ILibChain_RemoveSignalHandler_Finder(void* obj1, void *obj2)
|
||||
{
|
||||
ILibChain_SignalHandlerData *data = (ILibChain_SignalHandlerData*)obj1;
|
||||
void **data2 = (void**)obj2;
|
||||
|
||||
if (data->handler == data2[0] && data->user == data2[1])
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
int ILibChain_RemoveSignalHandler(void *chain, int signum, ILibChain_SignalHandler handler, void *user)
|
||||
{
|
||||
if (signum > (ILibChain_SIGMAX - 1)) { return(-1); }
|
||||
void *matchWith[2] = { handler, user };
|
||||
struct sigaction action, ignore;
|
||||
void *node;
|
||||
int ret = -1;
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
sigemptyset(&ignore.sa_mask);
|
||||
ignore.sa_flags = 0;
|
||||
|
||||
if (sigaction(signum, &ignore, &action) == 0)
|
||||
{
|
||||
if (g_signalHandlers[signum] != NULL)
|
||||
{
|
||||
node = ILibLinkedList_GetNode_Search(g_signalHandlers[signum], ILibChain_RemoveSignalHandler_Finder, (void*)matchWith);
|
||||
if (node != NULL)
|
||||
{
|
||||
ILibChain_SafeRemove(chain, ILibLinkedList_GetDataFromNode(node));
|
||||
ILibLinkedList_Remove(node);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
sigaction(signum, &action, NULL);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
int ILibChain_AddSignalHandler(void *chain, int signum, ILibChain_SignalHandler handler, void *user)
|
||||
{
|
||||
ILibChain_SignalHandlerData *data = NULL;
|
||||
struct sigaction action, ignore;
|
||||
int ret = -1;
|
||||
if (signum > (ILibChain_SIGMAX - 1)) { return(ret); }
|
||||
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
sigemptyset(&ignore.sa_mask);
|
||||
ignore.sa_flags = 0;
|
||||
|
||||
|
||||
if (sigaction(signum, &ignore, NULL) == 0)
|
||||
{
|
||||
if (g_signalHandlers[signum] == NULL) { g_signalHandlers[signum] = ILibLinkedList_Create(); }
|
||||
data = (ILibChain_SignalHandlerData*)ILibChain_Link_Allocate(sizeof(ILibChain_SignalHandlerData), 0);
|
||||
data->link.MetaData = "ILibChain_SignalHandler";
|
||||
data->link.PreSelectHandler = ILibChain_SignalHandler_PreSelect;
|
||||
data->link.PostSelectHandler = ILibChain_SignalHandler_PostSelect;
|
||||
data->link.DestroyHandler = ILibChain_SignalHandler_DestroySelect;
|
||||
data->signum = signum;
|
||||
data->user = user;
|
||||
data->handler = handler;
|
||||
if (pipe(data->ipc) == 0)
|
||||
{
|
||||
fcntl(data->ipc[0], F_SETFL, O_NONBLOCK);
|
||||
ILibLinkedList_AddTail(g_signalHandlers[signum], data);
|
||||
ILibChain_SafeAdd(chain, data);
|
||||
|
||||
action.sa_handler = ILibChain_SignalSink;
|
||||
sigemptyset(&action.sa_mask);
|
||||
action.sa_flags = 0;
|
||||
if (sigaction(signum, &action, NULL) == 0)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
ILibChain_SafeRemove(chain, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ILibChain_FreeLink(data);
|
||||
}
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! \fn void ILibChain_SafeAdd(void *chain, void *object)
|
||||
\brief Dynamically add a link to a chain that is already running.
|
||||
\par
|
||||
@@ -2121,6 +2093,7 @@ ILibExportMethod void ILibChain_Continue(void *Chain, ILibChain_Link **modules,
|
||||
chain->node = ILibLinkedList_GetNextNode(chain->node);
|
||||
}
|
||||
}
|
||||
|
||||
ILibRemoteLogging_printf(ILibChainGetLogger(chain), ILibRemoteLogging_Modules_Microstack_Generic, ILibRemoteLogging_Flags_VerbosityLevel_1, "ContinueChain...Ending...");
|
||||
|
||||
root->continuationState = ILibChain_ContinuationState_INACTIVE;
|
||||
|
||||
@@ -137,7 +137,7 @@ struct sockaddr_in6;
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <semaphore.h>
|
||||
#define sem_t dispatch_semaphore_t
|
||||
#define sem_init(x,pShared,InitValue) ILibDispatchSemaphore_Init((x), pShared, InitValue)
|
||||
#define sem_destroy(x) ILibDispatchSemaphore_Destroy(x)
|
||||
#define sem_wait(x) ILibDispatchSemaphore_wait(x)
|
||||
@@ -918,10 +918,13 @@ int ILibIsRunningOnChainThread(void* chain);
|
||||
\brief Chaining Methods
|
||||
\{
|
||||
*/
|
||||
typedef void(*ILibChain_SignalHandler)(void *chain, int signum, void *user);
|
||||
ILibExportMethod void *ILibCreateChain();
|
||||
void *ILibCreateChainEx(int extraMemorySize);
|
||||
void ILibAddToChain(void *chain, void *object);
|
||||
void *ILibGetBaseTimer(void *chain);
|
||||
int ILibChain_AddSignalHandler(void *chain, int signum, ILibChain_SignalHandler, void *user);
|
||||
int ILibChain_RemoveSignalHandler(void *chain, int signum, ILibChain_SignalHandler, void *user);
|
||||
void ILibChain_SafeAdd(void *chain, void *object);
|
||||
void ILibChain_SafeRemove(void *chain, void *object);
|
||||
void ILibChain_SafeRemoveEx(void *chain, void *object);
|
||||
|
||||
Reference in New Issue
Block a user