ENH: extend sigFpe::fillNan() interfaces

- provide separate float/double UList interfaces, which improves
  flexibility (eg, with SPDP)

- sigFpe::fillNan_if() interface, for filling in when using alternative
  memory allocators
This commit is contained in:
Mark Olesen
2025-03-31 13:36:18 +02:00
parent e720f823d3
commit e121db6e86
34 changed files with 174 additions and 127 deletions

View File

@ -1,3 +1,3 @@
Test-sigFpe.C Test-sigFpe.cxx
EXE = $(FOAM_USER_APPBIN)/Test-sigFpe EXE = $(FOAM_USER_APPBIN)/Test-sigFpe

View File

@ -3,13 +3,13 @@ MSwindows.C
cpuInfo/cpuInfo.C cpuInfo/cpuInfo.C
memInfo/memInfo.C memInfo/memInfo.C
signals/sigFpe.C signals/sigFpe.cxx
signals/sigInt.C signals/sigInt.cxx
signals/sigQuit.C signals/sigQuit.cxx
signals/sigSegv.C signals/sigSegv.cxx
signals/sigStopAtWriteNow.C signals/sigStopAtWriteNow.cxx
signals/sigWriteNow.C signals/sigWriteNow.cxx
signals/timer.C signals/timer.cxx
fileStat/fileStat.C fileStat/fileStat.C

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2023 OpenCFD Ltd. Copyright (C) 2018-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -50,13 +50,15 @@ Description
restores original). The class behaves as a singleton. restores original). The class behaves as a singleton.
SourceFiles SourceFiles
sigFpe.C sigFpe.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef Foam_sigFpe_H #ifndef Foam_sigFpe_H
#define Foam_sigFpe_H #define Foam_sigFpe_H
#include <algorithm>
#include <limits>
#include <cstddef> // For std::size_t #include <cstddef> // For std::size_t
#include "scalarFwd.H" #include "scalarFwd.H"
@ -96,6 +98,23 @@ class sigFpe
//- Handler for caught signals - ends job and prints stack //- Handler for caught signals - ends job and prints stack
static void sigHandler(int); static void sigHandler(int);
//- Fill (float | double) buffer with signalling NaN
template<class FloatType>
inline static void fill_with_NaN(FloatType* buf, size_t count)
{
if (buf && count)
{
const auto val =
std::numeric_limits<FloatType>::signaling_NaN();
// [float|double] so do not need std::uninitialized_fill_n()
// Can dispatch with
// - std::execution::par_unseq
// - std::execution::unseq
std::fill_n(buf, count, val);
}
}
public: public:
@ -124,6 +143,15 @@ public:
//- True if NaN memory initialisation is currently active. //- True if NaN memory initialisation is currently active.
static bool nanActive() noexcept { return nanActive_; } static bool nanActive() noexcept { return nanActive_; }
//- Set NaN memory initialisation on/off.
// \return the previous value
static bool nanActive(bool on) noexcept
{
bool old(nanActive_);
nanActive_ = on;
return old;
}
//- Activate SIGFPE handler when FOAM_SIGFPE is enabled. //- Activate SIGFPE handler when FOAM_SIGFPE is enabled.
//- Activate fill memory with signaling_NaN when FOAM_SETNAN is enabled //- Activate fill memory with signaling_NaN when FOAM_SETNAN is enabled
static void set(bool verbose=false); static void set(bool verbose=false);
@ -131,11 +159,37 @@ public:
//- Deactivate SIGFPE handler and NaN memory initialisation //- Deactivate SIGFPE handler and NaN memory initialisation
static void unset(bool verbose=false); static void unset(bool verbose=false);
//- Fill data block with signaling_NaN values
static void fillNan(char* buf, size_t count);
//- Fill data block with signaling_NaN values //- Fill data block with signaling_NaN values if nanActive().
static void fillNan(UList<scalar>& list); //- Does a reinterpret to \c Foam::scalar
inline static void fillNan_if(void* buf, size_t count)
{
if (nanActive_)
{
fill_with_NaN
(
reinterpret_cast<Foam::scalar*>(buf),
(count/sizeof(Foam::scalar))
);
}
}
//- Fill data block with signaling_NaN values.
//- Does a reinterpret to \c Foam::scalar
static void fillNan(char* buf, size_t count)
{
fill_with_NaN
(
reinterpret_cast<Foam::scalar*>(buf),
(count/sizeof(Foam::scalar))
);
}
//- Fill data block with (float) signaling_NaN values
static void fillNan(UList<float>& list);
//- Fill data block with (double) signaling_NaN values
static void fillNan(UList<double>& list);
// Helpers // Helpers

View File

@ -36,11 +36,9 @@ License
#include "Switch.H" #include "Switch.H"
#include <float.h> // For *fp functions #include <float.h> // For *fp functions
#include <algorithm>
#include <limits>
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -196,37 +194,15 @@ void Foam::sigFpe::unset(bool verbose)
} }
void Foam::sigFpe::fillNan(char* buf, size_t count) void Foam::sigFpe::fillNan(UList<float>& list)
{ {
if (!buf || !count) return; sigFpe::fill_with_NaN(list.data(), list.size());
// Fill with signaling_NaN
const scalar val = std::numeric_limits<scalar>::signaling_NaN();
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
reinterpret_cast<scalar*>(buf), (count/sizeof(scalar)), val
);
} }
void Foam::sigFpe::fillNan(UList<scalar>& list) void Foam::sigFpe::fillNan(UList<double>& list)
{ {
if (list.empty()) return; sigFpe::fill_with_NaN(list.data(), list.size());
// Fill with signaling_NaN
const scalar val = std::numeric_limits<scalar>::signaling_NaN();
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
list.data(), list.size(), val
);
} }

View File

@ -41,7 +41,7 @@ See also
Foam::JobInfo Foam::JobInfo
SourceFiles SourceFiles
sigInt.C sigInt.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -33,7 +33,7 @@ License
#include "IOstreams.H" #include "IOstreams.H"
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -40,7 +40,7 @@ See also
Foam::JobInfo Foam::JobInfo
SourceFiles SourceFiles
sigQuit.C sigQuit.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -33,7 +33,7 @@ License
#include "IOstreams.H" #include "IOstreams.H"
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// NOTE: SIGBREAK is the best alternative to SIGQUIT on windows // NOTE: SIGBREAK is the best alternative to SIGQUIT on windows

View File

@ -40,7 +40,7 @@ See also
Foam::JobInfo Foam::JobInfo
SourceFiles SourceFiles
sigSegv.C sigSegv.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -32,7 +32,7 @@ License
#include "IOstreams.H" #include "IOstreams.H"
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -32,7 +32,7 @@ Description
The interrupt is defined by OptimisationSwitches::stopAtWriteNowSignal The interrupt is defined by OptimisationSwitches::stopAtWriteNowSignal
SourceFiles SourceFiles
sigStopAtWriteNow.C sigStopAtWriteNow.cxx
See also See also
Foam::JobInfo Foam::JobInfo

View File

@ -34,7 +34,7 @@ License
#include "Time.H" #include "Time.H"
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -32,7 +32,7 @@ Description
The interrupt is defined by OptimisationSwitches::writeNowSignal The interrupt is defined by OptimisationSwitches::writeNowSignal
SourceFiles SourceFiles
sigWriteNow.C sigWriteNow.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -33,7 +33,7 @@ License
#include "Time.H" #include "Time.H"
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -27,7 +27,7 @@ Description
File-local code for setting/resetting signal handlers. File-local code for setting/resetting signal handlers.
SourceFiles SourceFiles
signalMacros.C signalMacros.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -57,7 +57,7 @@ Note
?something to do with stack frames. ?something to do with stack frames.
SourceFiles SourceFiles
timer.C timer.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -39,7 +39,7 @@ License
#include <windows.h> #include <windows.h>
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
#undef SIGALRM #undef SIGALRM
#define SIGALRM 14 #define SIGALRM 14

View File

@ -4,13 +4,13 @@ cpuInfo/cpuInfo.C
cpuTime/cpuTimePosix.C cpuTime/cpuTimePosix.C
memInfo/memInfo.C memInfo/memInfo.C
signals/sigFpe.C signals/sigFpe.cxx
signals/sigSegv.C signals/sigSegv.cxx
signals/sigInt.C signals/sigInt.cxx
signals/sigQuit.C signals/sigQuit.cxx
signals/sigStopAtWriteNow.C signals/sigStopAtWriteNow.cxx
signals/sigWriteNow.C signals/sigWriteNow.cxx
signals/timer.C signals/timer.cxx
fileStat/fileStat.C fileStat/fileStat.C

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2023 OpenCFD Ltd. Copyright (C) 2018-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -50,13 +50,15 @@ Description
restores original). The class behaves as a singleton. restores original). The class behaves as a singleton.
SourceFiles SourceFiles
sigFpe.C sigFpe.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef Foam_sigFpe_H #ifndef Foam_sigFpe_H
#define Foam_sigFpe_H #define Foam_sigFpe_H
#include <algorithm>
#include <limits>
#include <cstddef> // For std::size_t #include <cstddef> // For std::size_t
#include "scalarFwd.H" #include "scalarFwd.H"
@ -96,6 +98,23 @@ class sigFpe
//- Handler for caught signals - ends job and prints stack //- Handler for caught signals - ends job and prints stack
static void sigHandler(int); static void sigHandler(int);
//- Fill (float | double) buffer with signalling NaN
template<class FloatType>
inline static void fill_with_NaN(FloatType* buf, size_t count)
{
if (buf && count)
{
const auto val =
std::numeric_limits<FloatType>::signaling_NaN();
// [float|double] so do not need std::uninitialized_fill_n()
// Can dispatch with
// - std::execution::par_unseq
// - std::execution::unseq
std::fill_n(buf, count, val);
}
}
public: public:
@ -124,6 +143,15 @@ public:
//- True if NaN memory initialisation is currently active. //- True if NaN memory initialisation is currently active.
static bool nanActive() noexcept { return nanActive_; } static bool nanActive() noexcept { return nanActive_; }
//- Set NaN memory initialisation on/off.
// \return the previous value
static bool nanActive(bool on) noexcept
{
bool old(nanActive_);
nanActive_ = on;
return old;
}
//- Activate SIGFPE handler when FOAM_SIGFPE is enabled. //- Activate SIGFPE handler when FOAM_SIGFPE is enabled.
//- Activate fill memory with signaling_NaN when FOAM_SETNAN is enabled //- Activate fill memory with signaling_NaN when FOAM_SETNAN is enabled
static void set(bool verbose=false); static void set(bool verbose=false);
@ -131,11 +159,36 @@ public:
//- Deactivate SIGFPE handler and NaN memory initialisation //- Deactivate SIGFPE handler and NaN memory initialisation
static void unset(bool verbose=false); static void unset(bool verbose=false);
//- Fill data block with signaling_NaN values //- Fill data block with signaling_NaN values if nanActive().
static void fillNan(char* buf, size_t count); //- Does a reinterpret to \c Foam::scalar
static void fillNan_if(void* buf, size_t count)
{
if (nanActive_)
{
fill_with_NaN
(
reinterpret_cast<Foam::scalar*>(buf),
(count/sizeof(Foam::scalar))
);
}
}
//- Fill data block with signaling_NaN values //- Fill data block with signaling_NaN values.
static void fillNan(UList<scalar>& list); //- Does a reinterpret to \c Foam::scalar
static void fillNan(char* buf, size_t count)
{
fill_with_NaN
(
reinterpret_cast<Foam::scalar*>(buf),
(count/sizeof(Foam::scalar))
);
}
//- Fill data block with (float) signaling_NaN values
static void fillNan(UList<float>& list);
//- Fill data block with (double) signaling_NaN values
static void fillNan(UList<double>& list);
// Helpers // Helpers

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2016-2023 OpenCFD Ltd. Copyright (C) 2016-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -33,11 +33,9 @@ License
#include "IOstreams.H" #include "IOstreams.H"
#include "UList.H" #include "UList.H"
#include "Switch.H" #include "Switch.H"
#include <algorithm>
#include <limits>
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
#if defined(__linux__) && defined(__GNUC__) #if defined(__linux__) && defined(__GNUC__)
#ifndef __USE_GNU #ifndef __USE_GNU
@ -91,24 +89,12 @@ extern "C"
// Call the low-level GLIBC malloc function // Call the low-level GLIBC malloc function
void* ptr = __libc_malloc(size); void* ptr = __libc_malloc(size);
if (Foam::sigFpe::nanActive()) // Optionally fill with NaN (depends on current flags)
{ Foam::sigFpe::fillNan_if(ptr, size);
// Fill with signaling_NaN
const auto val = std::numeric_limits<Foam::scalar>::signaling_NaN();
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
reinterpret_cast<Foam::scalar*>(ptr),
(size/sizeof(Foam::scalar)),
val
);
}
return ptr; return ptr;
} }
} // End extern C } // End extern C
#endif // __linux__ #endif // __linux__
@ -248,37 +234,15 @@ void Foam::sigFpe::unset(bool verbose)
} }
void Foam::sigFpe::fillNan(char* buf, size_t count) void Foam::sigFpe::fillNan(UList<float>& list)
{ {
if (!buf || !count) return; sigFpe::fill_with_NaN(list.data(), list.size());
// Fill with signaling_NaN
const auto val = std::numeric_limits<scalar>::signaling_NaN();
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
reinterpret_cast<scalar*>(buf), (count/sizeof(scalar)), val
);
} }
void Foam::sigFpe::fillNan(UList<scalar>& list) void Foam::sigFpe::fillNan(UList<double>& list)
{ {
if (list.empty()) return; sigFpe::fill_with_NaN(list.data(), list.size());
// Fill with signaling_NaN
const auto val = std::numeric_limits<scalar>::signaling_NaN();
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
list.data(), list.size(), val
);
} }

View File

@ -41,7 +41,7 @@ See also
Foam::JobInfo Foam::JobInfo
SourceFiles SourceFiles
sigInt.C sigInt.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -32,7 +32,7 @@ License
#include "IOstreams.H" #include "IOstreams.H"
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -40,7 +40,7 @@ See also
Foam::JobInfo Foam::JobInfo
SourceFiles SourceFiles
sigQuit.C sigQuit.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -32,7 +32,7 @@ License
#include "IOstreams.H" #include "IOstreams.H"
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -40,7 +40,7 @@ See also
Foam::JobInfo Foam::JobInfo
SourceFiles SourceFiles
sigSegv.C sigSegv.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -32,7 +32,7 @@ License
#include "IOstreams.H" #include "IOstreams.H"
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -32,7 +32,7 @@ Description
The interrupt is defined by OptimisationSwitches::stopAtWriteNowSignal The interrupt is defined by OptimisationSwitches::stopAtWriteNowSignal
SourceFiles SourceFiles
sigStopAtWriteNow.C sigStopAtWriteNow.cxx
See also See also
Foam::JobInfo Foam::JobInfo

View File

@ -34,7 +34,7 @@ License
#include "Time.H" #include "Time.H"
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -32,7 +32,7 @@ Description
The interrupt is defined by OptimisationSwitches::writeNowSignal The interrupt is defined by OptimisationSwitches::writeNowSignal
SourceFiles SourceFiles
sigWriteNow.C sigWriteNow.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -32,7 +32,7 @@ License
#include "IOstreams.H" #include "IOstreams.H"
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -27,7 +27,7 @@ Description
File-local code for setting/resetting signal handlers. File-local code for setting/resetting signal handlers.
SourceFiles SourceFiles
signalMacros.C signalMacros.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -57,7 +57,7 @@ Note
?something to do with stack frames. ?something to do with stack frames.
SourceFiles SourceFiles
timer.C timer.cxx
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/

View File

@ -33,7 +33,7 @@ License
#include <unistd.h> #include <unistd.h>
// File-local functions // File-local functions
#include "signalMacros.C" #include "signalMacros.cxx"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //