Adding a FPE-handler for Darwin

--HG--
branch : bgschaid/minorAdditionsBranch
This commit is contained in:
Bernhard F.W. Gschaider 2013-11-08 00:42:49 +01:00
parent 2c4e17cdbf
commit caf9efd208
4 changed files with 157 additions and 4 deletions

View file

@ -45,6 +45,12 @@ License
# include <sigfpe.h>
#elif defined(__APPLE__)
// # include <fenv.h>
#include <xmmintrin.h>
#include <mach/mach.h>
#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<uint32_t*>(result);
# else
const uint64_t sNAN = 0x7ff7ffffffffffffllu;
uint64_t* dPtr = reinterpret_cast<uint64_t*>(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
}
}

View file

@ -55,6 +55,15 @@ SourceFiles
# define LINUX_GNUC
#endif
#ifdef __APPLE__
#include <malloc/malloc.h>
// 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);

View file

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

View file

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