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

View File

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

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -50,13 +50,15 @@ Description
restores original). The class behaves as a singleton.
SourceFiles
sigFpe.C
sigFpe.cxx
\*---------------------------------------------------------------------------*/
#ifndef Foam_sigFpe_H
#define Foam_sigFpe_H
#include <algorithm>
#include <limits>
#include <cstddef> // For std::size_t
#include "scalarFwd.H"
@ -96,6 +98,23 @@ class sigFpe
//- Handler for caught signals - ends job and prints stack
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:
@ -124,6 +143,15 @@ public:
//- True if NaN memory initialisation is currently active.
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 fill memory with signaling_NaN when FOAM_SETNAN is enabled
static void set(bool verbose=false);
@ -131,11 +159,37 @@ public:
//- Deactivate SIGFPE handler and NaN memory initialisation
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
static void fillNan(UList<scalar>& list);
//- Fill data block with signaling_NaN values if nanActive().
//- 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

View File

@ -36,11 +36,9 @@ License
#include "Switch.H"
#include <float.h> // For *fp functions
#include <algorithm>
#include <limits>
// File-local functions
#include "signalMacros.C"
#include "signalMacros.cxx"
// * * * * * * * * * * * * * * 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;
// 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
);
sigFpe::fill_with_NaN(list.data(), list.size());
}
void Foam::sigFpe::fillNan(UList<scalar>& list)
void Foam::sigFpe::fillNan(UList<double>& list)
{
if (list.empty()) return;
// 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
);
sigFpe::fill_with_NaN(list.data(), list.size());
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -50,13 +50,15 @@ Description
restores original). The class behaves as a singleton.
SourceFiles
sigFpe.C
sigFpe.cxx
\*---------------------------------------------------------------------------*/
#ifndef Foam_sigFpe_H
#define Foam_sigFpe_H
#include <algorithm>
#include <limits>
#include <cstddef> // For std::size_t
#include "scalarFwd.H"
@ -96,6 +98,23 @@ class sigFpe
//- Handler for caught signals - ends job and prints stack
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:
@ -124,6 +143,15 @@ public:
//- True if NaN memory initialisation is currently active.
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 fill memory with signaling_NaN when FOAM_SETNAN is enabled
static void set(bool verbose=false);
@ -131,11 +159,36 @@ public:
//- Deactivate SIGFPE handler and NaN memory initialisation
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 if nanActive().
//- 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
static void fillNan(UList<scalar>& list);
//- 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

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2016-2023 OpenCFD Ltd.
Copyright (C) 2016-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,11 +33,9 @@ License
#include "IOstreams.H"
#include "UList.H"
#include "Switch.H"
#include <algorithm>
#include <limits>
// File-local functions
#include "signalMacros.C"
#include "signalMacros.cxx"
#if defined(__linux__) && defined(__GNUC__)
#ifndef __USE_GNU
@ -91,24 +89,12 @@ extern "C"
// Call the low-level GLIBC malloc function
void* ptr = __libc_malloc(size);
if (Foam::sigFpe::nanActive())
{
// 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
);
}
// Optionally fill with NaN (depends on current flags)
Foam::sigFpe::fillNan_if(ptr, size);
return ptr;
}
} // End extern C
#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;
// 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
);
sigFpe::fill_with_NaN(list.data(), list.size());
}
void Foam::sigFpe::fillNan(UList<scalar>& list)
void Foam::sigFpe::fillNan(UList<double>& list)
{
if (list.empty()) return;
// 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
);
sigFpe::fill_with_NaN(list.data(), list.size());
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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