diff --git a/src/OSspecific/POSIX/signals/sigFpe.C b/src/OSspecific/POSIX/signals/sigFpe.C index 8c1a20eb4..d990cd248 100644 --- a/src/OSspecific/POSIX/signals/sigFpe.C +++ b/src/OSspecific/POSIX/signals/sigFpe.C @@ -45,6 +45,12 @@ License # include +#elif defined(__APPLE__) + +// # include +#include +#include + #endif @@ -102,10 +108,40 @@ void* Foam::sigFpe::my_malloc_hook(size_t size, const void *caller) return result; } +#elif defined(__APPLE__) + +void *(*Foam::sigFpe::system_malloc_)(malloc_zone_t *zone, size_t size)=NULL; + +void* Foam::sigFpe::nan_malloc_(malloc_zone_t *zone, size_t size) +{ + void *result=system_malloc_(zone,size); + + // initialize to signalling NaN +# ifdef WM_SP + + const uint32_t sNAN = 0x7ff7fffflu; + uint32_t* dPtr = reinterpret_cast(result); + +# else + + const uint64_t sNAN = 0x7ff7ffffffffffffllu; + uint64_t* dPtr = reinterpret_cast(result); + +# endif + + const size_t nScalars = size/sizeof(scalar); + for (size_t i = 0; i < nScalars; ++i) + { + *dPtr++ = sNAN; + } + + return result; +} + #endif -#ifdef LINUX_GNUC +#if defined(LINUX_GNUC) || defined(__APPLE__) void Foam::sigFpe::sigFpeHandler(int) { @@ -170,6 +206,44 @@ Foam::sigFpe::~sigFpe() __malloc_hook = old_malloc_hook; } + # elif defined(__APPLE__) + + if(system_malloc_!=NULL) { + malloc_zone_t *zone = malloc_default_zone(); + if(zone==NULL) { + FatalErrorIn("Foam__sigFpe::set") + << "Could not get malloc_default_zone()." << endl + << "Seems like this version of Mac OS X doesn't support FOAM_SETNAN" + << endl + << exit(FatalError); + + } + + if(zone->version>=8) + { + vm_protect( + mach_task_self(), + (uintptr_t)zone, + sizeof(malloc_zone_t), + 0, + VM_PROT_READ | VM_PROT_WRITE + );//remove the write protection + } + zone->malloc=system_malloc_; + system_malloc_=NULL; + if(zone->version==8) + { + vm_protect( + mach_task_self(), + (uintptr_t)zone, + sizeof(malloc_zone_t), + 0, + VM_PROT_READ + );//put the write protection back + } + + } + # endif } } @@ -240,6 +314,26 @@ void Foam::sigFpe::set(const bool verbose) NULL ); +# elif defined(__APPLE__) + + struct sigaction newAction; + newAction.sa_handler = sigFpeHandler; + newAction.sa_flags = SA_NODEFER; + sigemptyset(&newAction.sa_mask); + if (sigaction(SIGFPE, &newAction, &oldAction_) < 0) + { + FatalErrorIn + ( + "Foam::sigFpe::set()" + ) << "Cannot set SIGFPE trapping" + << abort(FatalError); + } + _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID); + _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO); + + _mm_setcsr( _MM_MASK_MASK &~ + (_MM_MASK_OVERFLOW|_MM_MASK_INVALID|_MM_MASK_DIV_ZERO) ); + # endif } @@ -257,6 +351,48 @@ void Foam::sigFpe::set(const bool verbose) // Set our malloc __malloc_hook = Foam::sigFpe::my_malloc_hook; +#elif defined(__APPLE__) + + if(system_malloc_!=NULL) { + FatalErrorIn("Foam__sigFpe::set") + << "system_malloc_ already reset." << endl + << "This should never happen" + << endl + << exit(FatalError); + } + + malloc_zone_t *zone = malloc_default_zone(); + if(zone==NULL) { + FatalErrorIn("Foam__sigFpe::set") + << "Could not get malloc_default_zone()." << endl + << "Seems like this version of Mac OS X doesn't support FOAM_SETNAN" + << endl + << exit(FatalError); + } + // According to http://bkdc.ubiquity.ro/2011/07/how-to-set-malloc-hooks-in-osx-lion-107.html + if(zone->version>=8) + { + vm_protect( + mach_task_self(), + (uintptr_t)zone, + sizeof(malloc_zone_t), + 0, + VM_PROT_READ | VM_PROT_WRITE + );//remove the write protection + } + system_malloc_=zone->malloc; + zone->malloc=Foam::sigFpe::nan_malloc_; + if(zone->version==8) + { + vm_protect( + mach_task_self(), + (uintptr_t)zone, + sizeof(malloc_zone_t), + 0, + VM_PROT_READ + );//put the write protection back + } + # endif } } diff --git a/src/OSspecific/POSIX/signals/sigFpe.H b/src/OSspecific/POSIX/signals/sigFpe.H index d50eed8ab..5dd921ecb 100644 --- a/src/OSspecific/POSIX/signals/sigFpe.H +++ b/src/OSspecific/POSIX/signals/sigFpe.H @@ -55,6 +55,15 @@ SourceFiles # define LINUX_GNUC #endif +#ifdef __APPLE__ +#include + +// these are defined by the mach-headers and would break compilation of Switch.H +#undef TRUE +#undef FALSE + +#endif + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam @@ -79,12 +88,20 @@ class sigFpe //- nan malloc function. From malloc_hook manpage. static void* my_malloc_hook(size_t size, const void *caller); +#elif defined (__APPLE__) + + //- pointer to the original malloc that is overrided + static void *(*system_malloc_)(malloc_zone_t *zone, size_t size); + + //- the overriding handler + static void* nan_malloc_(malloc_zone_t *zone, size_t size); + # endif // Static data members -# ifdef LINUX_GNUC +# if defined(LINUX_GNUC) || defined(__APPLE__) //- Handler for caught signals static void sigFpeHandler(int); diff --git a/wmake/rules/darwinIntel64Gcc/c b/wmake/rules/darwinIntel64Gcc/c index 7d81ffc19..b05a7379c 100644 --- a/wmake/rules/darwinIntel64Gcc/c +++ b/wmake/rules/darwinIntel64Gcc/c @@ -2,7 +2,7 @@ cWARN = -Wall -cc = $(WM_CC) $(WM_CXXFLAGS) +cc = $(WM_CC) $(WM_CXXFLAGS) -fsignaling-nans -ftrapping-math include $(RULES)/c$(WM_COMPILE_OPTION) diff --git a/wmake/rules/darwinIntel64Gcc/c++ b/wmake/rules/darwinIntel64Gcc/c++ index b705ae3a2..c539e92eb 100644 --- a/wmake/rules/darwinIntel64Gcc/c++ +++ b/wmake/rules/darwinIntel64Gcc/c++ @@ -2,7 +2,7 @@ c++WARN = -Wall -Wextra -Wno-unused-parameter -Wold-style-cast -Wno-overloaded-virtual -Wno-unsequenced -Wno-c++11-extensions -Wno-unused-comparison -CC = $(WM_CXX) $(WM_CXXFLAGS) +CC = $(WM_CXX) $(WM_CXXFLAGS) -fsignaling-nans -ftrapping-math include $(RULES)/c++$(WM_COMPILE_OPTION)