From 34a104d1ade420cd029c48f31b94bfb8139afd6f Mon Sep 17 00:00:00 2001 From: "HARMEL, Bernard" Date: Mon, 26 Feb 2024 16:14:04 +0100 Subject: [PATCH] clean up bofsystem --- lib/CMakeLists.txt | 1 + lib/include/bofstd/bofbuffer.h | 354 ++ lib/include/bofstd/boffs.h | 6 + lib/include/bofstd/bofsystem.h | 665 +--- lib/src/bofsystem.cpp | 3267 ++++++++--------- {lib/src => oldies}/bofthreadapi.cpp | 0 {lib/include/bofstd => oldies}/bofthreadapi.h | 0 {lib/src => oldies}/bofthreadgeneric.cpp | 0 .../bofstd => oldies}/bofthreadgeneric.h | 0 tests/src/main.cpp | 1 + tests/src/ut_system.cpp | 4 +- 11 files changed, 1950 insertions(+), 2348 deletions(-) create mode 100644 lib/include/bofstd/bofbuffer.h rename {lib/src => oldies}/bofthreadapi.cpp (100%) rename {lib/include/bofstd => oldies}/bofthreadapi.h (100%) rename {lib/src => oldies}/bofthreadgeneric.cpp (100%) rename {lib/include/bofstd => oldies}/bofthreadgeneric.h (100%) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 60ec8a45..58f5cd8c 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -212,6 +212,7 @@ set(SOCKIO_FILES ) set(SYSTEM_FILES + include/bofstd/bofbuffer.h include/bofstd/bofsystem.h src/bofsystem.cpp include/bofstd/bofscopeguard.h diff --git a/lib/include/bofstd/bofbuffer.h b/lib/include/bofstd/bofbuffer.h new file mode 100644 index 00000000..e7af6a08 --- /dev/null +++ b/lib/include/bofstd/bofbuffer.h @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2000-2020, Onbings All rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + * PURPOSE. + * + * This module defines the bofbuffer interface. + * + * Name: bofbuffer.h + * Author: Bernard HARMEL: b.harmel@gmail.com + * Revision: 1.0 + * + * Rem: Nothing + * + * History: + * + * V 1.00 Jan 19 2017 BHA : Initial release + */ +#pragma once +#include +#include + +BEGIN_BOF_NAMESPACE() +enum class BOF_BUFFER_ALLOCATE_ZONE : uint32_t +{ + BOF_BUFFER_ALLOCATE_ZONE_RAM = 0, + BOF_BUFFER_ALLOCATE_ZONE_HUGE_PAGE, + // CMA, ///< Contiguous Memory Allocator +}; +struct BOF_BUFFER_ALLOCATE_HEADER +{ + BOF_BUFFER_ALLOCATE_ZONE AllocateZone_E; + // uint32_t SizeInByte_U32; + int Io_i; + bool Locked_B; + char pHugePath_c[128]; + + BOF_BUFFER_ALLOCATE_HEADER() + { + Reset(); + } + + void Reset() + { + AllocateZone_E = BOF_BUFFER_ALLOCATE_ZONE::BOF_BUFFER_ALLOCATE_ZONE_RAM; + // SizeInByte_U32=0; + Io_i = -1; + Locked_B = false; + pHugePath_c[0] = 0; + } +}; +enum BOF_BUFFER_DELETER +{ + BOF_BUFFER_DELETER_NONE = 0, + BOF_BUFFER_DELETER_FREE, + BOF_BUFFER_DELETER_ALIGNED_FREE, + BOF_BUFFER_DELETER_DELETE +}; +struct BOF_BUFFER; +BOFSTD_EXPORT BOFERR Bof_AlignedMemFree(BOF::BOF_BUFFER &_rBuffer_X); +struct BOF_BUFFER +{ + BOF_BUFFER_DELETER Deleter_E; + uint64_t Offset_U64; // For seek + uint64_t Size_U64; + uint64_t Capacity_U64; + void *pUser; // Used by Bof_AlignedMemAlloc for example + uint8_t *pData_U8; + mutable std::mutex Mtx; + + BOF_BUFFER() + { + // for ReleaseStorage in Reset + Deleter_E = BOF_BUFFER_DELETER_NONE; + pUser = nullptr; + Offset_U64 = 0; + Size_U64 = 0; + Capacity_U64 = 0; + pData_U8 = nullptr; + // Reset(); + } + /* Use SetStorage + BOF_BUFFER(uint64_t _Capacity_U64, uint64_t _Size_U64, uint8_t *_pData_U8, bool _MustBeDeleted_B) + { + SetStorage(_Capacity_U64, _Size_U64, _pData_U8); + MustBeDeleted_B = _MustBeDeleted_B; + MustBeFreeed_B = false; + } + */ + ~BOF_BUFFER() + { + Reset(); + } + // Copy constructor as we use mutable std::mutex https://stackoverflow.com/questions/30340029/copy-class-with-stdmutex + BOF_BUFFER(const BOF_BUFFER &_rOther_X) + { + std::lock_guard Lock(Mtx); + Deleter_E = BOF_BUFFER_DELETER_NONE; // Only one deleter _rOther_X.MustBeDeleted_B; + pUser = _rOther_X.pUser; + Offset_U64 = _rOther_X.Offset_U64; + Size_U64 = _rOther_X.Size_U64; + Capacity_U64 = _rOther_X.Capacity_U64; + pData_U8 = _rOther_X.pData_U8; + } + BOF_BUFFER &operator=(const BOF_BUFFER &_rOther_X) + { + std::lock_guard Lock(Mtx); + Deleter_E = BOF_BUFFER_DELETER_NONE; // Only one deleter _rOther_X.MustBeDeleted_B; + pUser = _rOther_X.pUser; + Offset_U64 = _rOther_X.Offset_U64; + Size_U64 = _rOther_X.Size_U64; + Capacity_U64 = _rOther_X.Capacity_U64; + pData_U8 = _rOther_X.pData_U8; + return *this; + } + BOF_BUFFER &operator=(const BOF_BUFFER &&_rrOther_X) noexcept + { + std::lock_guard Lock(Mtx); + Deleter_E = BOF_BUFFER_DELETER_NONE; // Only one deleter _rOther_X.MustBeDeleted_B; + pUser = _rrOther_X.pUser; + Offset_U64 = _rrOther_X.Offset_U64; + Size_U64 = _rrOther_X.Size_U64; + Capacity_U64 = _rrOther_X.Capacity_U64; + pData_U8 = _rrOther_X.pData_U8; + return *this; + } + void Reset() + { + if (pData_U8) + { + //printf("WARNING: Resetting an 'active' BOF_BUFFER\n"); + } + ReleaseStorage(); + std::lock_guard Lock(Mtx); + Deleter_E = BOF_BUFFER_DELETER_NONE; + pUser = nullptr; + Offset_U64 = 0; + Size_U64 = 0; + Capacity_U64 = 0; + pData_U8 = nullptr; + } + + void Clear() + { + std::lock_guard Lock(Mtx); + Offset_U64 = 0; + Size_U64 = 0; + } + uint8_t *SetStorage(uint64_t _Capacity_U64, uint64_t _Size_U64, uint8_t *_pData_U8) + { + BOF_ASSERT(_Capacity_U64 < 0x100000000); // For the moment + ReleaseStorage(); + + Deleter_E = BOF_BUFFER_DELETER_NONE; + if (_pData_U8) + { + pData_U8 = _pData_U8; // Caller can set Deleter_E if needed + } + else + { + pData_U8 = AllocStorage(_Capacity_U64); // Will set MustBeDeleted_B to true + } + std::lock_guard Lock(Mtx); + Capacity_U64 = _Capacity_U64; + + Offset_U64 = 0; + if (_Size_U64 <= _Capacity_U64) + { + Size_U64 = _Size_U64; + } + else + { + Size_U64 = 0; + } + return pData_U8; + } + + uint64_t RemainToWrite() + { + // Called by read/write std::lock_guard Lock(Mtx); + return (Size_U64 <= Capacity_U64) ? Capacity_U64 - Size_U64 : 0; + } + uint64_t RemainToRead() + { + // Called by read/write std::lock_guard Lock(Mtx); + return (Offset_U64 < Size_U64) ? Size_U64 - Offset_U64 : 0; + } + uint8_t *Pos() + { + uint8_t *pRts_U8 = nullptr; + + std::lock_guard Lock(Mtx); + if (IsValid()) + { + pRts_U8 = &pData_U8[Size_U64]; + } + return pRts_U8; + } + uint8_t *SeekAbs(uint64_t _Offset_U64, uint64_t &_rRemain_U64) + { + uint8_t *pRts_U8 = nullptr; + + std::lock_guard Lock(Mtx); + if (_Offset_U64 <= Size_U64) + { + Offset_U64 = _Offset_U64; + _rRemain_U64 = Size_U64 - Offset_U64; + pRts_U8 = &pData_U8[Offset_U64]; + } + return pRts_U8; + } + uint8_t *SeekRel(int64_t _Amount_S64, uint64_t &_rRemain_U64) + { + uint8_t *pRts_U8 = nullptr; + uint64_t NewOffset_U64; + + std::lock_guard Lock(Mtx); + NewOffset_U64 = Offset_U64 + _Amount_S64; + if (NewOffset_U64 <= Size_U64) + { + Offset_U64 = NewOffset_U64; + _rRemain_U64 = Size_U64 - Offset_U64; + pRts_U8 = &pData_U8[Offset_U64]; + } + return pRts_U8; + } + uint8_t *Read(uint64_t _Size_U64, uint64_t &_rNbRead_U64) + { + uint8_t *pRts_U8 = nullptr; + uint64_t Remain_U64; + + std::lock_guard Lock(Mtx); + _rNbRead_U64 = 0; + if (IsValid()) + { + Remain_U64 = RemainToRead(); + _rNbRead_U64 = (Remain_U64 < _Size_U64) ? Remain_U64 : _Size_U64; + if (_rNbRead_U64) + { + pRts_U8 = &pData_U8[Offset_U64]; + Offset_U64 += _rNbRead_U64; + } + } + return pRts_U8; + } + uint8_t *Write(uint64_t _Size_U64, const uint8_t *_pData_U8, uint64_t &_rNbWritten_U64) + { + uint8_t *pRts_U8 = nullptr; + uint64_t Free_U64; + + std::lock_guard Lock(Mtx); + _rNbWritten_U64 = 0; + if ((IsValid()) && (_pData_U8)) + { + Free_U64 = RemainToWrite(); + _rNbWritten_U64 = (_Size_U64 < Free_U64) ? _Size_U64 : Free_U64; + if (_rNbWritten_U64) + { + memcpy(&pData_U8[Size_U64], _pData_U8, static_cast(_rNbWritten_U64)); + Size_U64 += _rNbWritten_U64; + pRts_U8 = &pData_U8[Size_U64]; + } + } + return pRts_U8; + } + bool Memset(const uint8_t _Val_U8, uint64_t _Size_U64, uint64_t _Offset_U64) + { + bool Rts_B = false; + + std::lock_guard Lock(Mtx); + if (IsValid()) + { + if ((_Offset_U64 < Capacity_U64) && ((_Size_U64 + _Offset_U64) < Capacity_U64)) + { + memset(&pData_U8[_Offset_U64], _Val_U8, _Size_U64); + Rts_B = true; + } + } + return Rts_B; + } + bool IsValid() + { + bool Rts_B = false; + + // Called by read/write std::lock_guard Lock(Mtx); + if ((pData_U8) && (Capacity_U64)) + { + if ((Size_U64 <= Capacity_U64) && (Offset_U64 <= Size_U64)) + { + Rts_B = true; + } + } + return Rts_B; + } + + bool IsNull() + { + bool Rts_B = true; + + // Called by read/write std::lock_guard Lock(Mtx); + if ((pData_U8) && (Capacity_U64)) + { + Rts_B = false; + } + return Rts_B; + } + + uint8_t *AllocStorage(uint64_t _Capacity_U64) + { + BOF_ASSERT(_Capacity_U64 < 0x100000000); // For the moment + ReleaseStorage(); + + uint8_t *pRts = new uint8_t[static_cast(_Capacity_U64)]; + + if (pRts) + { + std::lock_guard Lock(Mtx); + Deleter_E = BOF_BUFFER_DELETER_DELETE; + Capacity_U64 = _Capacity_U64; + Offset_U64 = 0; + Size_U64 = 0; + pData_U8 = pRts; + } + return pRts; + } + void ReleaseStorage() + { + std::lock_guard Lock(Mtx); + switch (Deleter_E) + { + default: + case BOF_BUFFER_DELETER_NONE: + break; + case BOF_BUFFER_DELETER_DELETE: + BOF_SAFE_DELETE_ARRAY(pData_U8); + break; + case BOF_BUFFER_DELETER_FREE: + BOF_SAFE_FREE(pData_U8); + break; + case BOF_BUFFER_DELETER_ALIGNED_FREE: + Bof_AlignedMemFree(*this); + break; + } + Deleter_E = BOF_BUFFER_DELETER_NONE; + pData_U8 = nullptr; + Capacity_U64 = 0; + Offset_U64 = 0; + Size_U64 = 0; + } +}; + +END_BOF_NAMESPACE() \ No newline at end of file diff --git a/lib/include/bofstd/boffs.h b/lib/include/bofstd/boffs.h index eedfabc1..aa480312 100644 --- a/lib/include/bofstd/boffs.h +++ b/lib/include/bofstd/boffs.h @@ -29,6 +29,12 @@ #include BEGIN_BOF_NAMESPACE() +enum class BOF_SEEK_METHOD : uint32_t +{ + BOF_SEEK_BEGIN = 0, /*! The starting point is zero or the beginning of the file.*/ + BOF_SEEK_CURRENT, /*! The starting point is the current value of the file pointer.*/ + BOF_SEEK_END /*! The starting point is the current end-of-file position*/ +}; enum class BOF_FILE_PERMISSION : uint32_t { diff --git a/lib/include/bofstd/bofsystem.h b/lib/include/bofstd/bofsystem.h index 38892f06..fa988a13 100644 --- a/lib/include/bofstd/bofsystem.h +++ b/lib/include/bofstd/bofsystem.h @@ -20,6 +20,7 @@ */ #pragma once #include +#include #include #include @@ -28,17 +29,17 @@ #include BEGIN_BOF_NAMESPACE() - #define BOF_MS_TO_S(v) (static_cast((v) / 1e3)) #define BOF_MS_TO_US(v) (static_cast((v)*1e3)) -#define BOF_NANO_TO_MS(v) (static_cast((v) / 1e6)) -#define BOF_NANO_TO_S(v) (static_cast((v) / 1e9)) +#define BOF_NS_TO_MS(v) (static_cast((v) / 1e6)) +#define BOF_NS_TO_S(v) (static_cast((v) / 1e9)) #define BOF_S_TO_MS(v) (static_cast((v)*1e3)) #define BOF_MS_TO_US(v) (static_cast((v)*1e3)) -#define BOF_MS_TO_NANO(v) (static_cast((v)*1e6)) -#define BOF_S_TO_NANO(v) (static_cast((v)*1e9)) +#define BOF_MS_TO_NS(v) (static_cast((v)*1e6)) +#define BOF_S_TO_NS(v) (static_cast((v)*1e9)) #define BOF_INFINITE_TIMEOUT ((uint32_t)-1) + #if defined(_WIN32) #define BOF_IOCTL(fd, req, LenIn, pInBuffer, LenOut, pOutBuffer, Sts) \ { \ @@ -51,399 +52,8 @@ BEGIN_BOF_NAMESPACE() Sts = ioctl(fd, req, pInBuffer); \ } #endif -enum class BOF_SEEK_METHOD : uint32_t -{ - BOF_SEEK_BEGIN = 0, /*! The starting point is zero or the beginning of the file.*/ - BOF_SEEK_CURRENT, /*! The starting point is the current value of the file pointer.*/ - BOF_SEEK_END /*! The starting point is the current end-of-file position*/ -}; -// To use with Bof_InterlockedCompareExchange -enum BOF_COM_RAM_CMD_STATE : uint32_t -{ - BOF_COM_RAM_CMD_STATE_FREE = 0, // ComRam command zone is free - BOF_COM_RAM_CMD_STATE_RESERVED, // Command sender has reserved the command zone to post a new command -> no other one can use this zone when it is in this state - BOF_COM_RAM_CMD_STATE_PENDING, // Command and arg are posted and can be consumed by a client - BOF_COM_RAM_CMD_STATE_PROCESSING, // A client has seen the command and is currently processing - BOF_COM_RAM_CMD_STATE_FINISHED, // Command is finished and result are now available - BOF_COM_RAM_CMD_STATE_RESULT, // Result is read by a client which MUST set the state to BOF_COM_RAM_CMD_STATE_FREE when it has finished -}; - -enum class BOF_BUFFER_ALLOCATE_ZONE : uint32_t -{ - BOF_BUFFER_ALLOCATE_ZONE_RAM = 0, - BOF_BUFFER_ALLOCATE_ZONE_HUGE_PAGE, - // CMA, ///< Contiguous Memory Allocator -}; -struct BOF_BUFFER_ALLOCATE_HEADER -{ - BOF_BUFFER_ALLOCATE_ZONE AllocateZone_E; - // uint32_t SizeInByte_U32; - int Io_i; - bool Locked_B; - char pHugePath_c[128]; - - BOF_BUFFER_ALLOCATE_HEADER() - { - Reset(); - } - - void Reset() - { - AllocateZone_E = BOF_BUFFER_ALLOCATE_ZONE::BOF_BUFFER_ALLOCATE_ZONE_RAM; - // SizeInByte_U32=0; - Io_i = -1; - Locked_B = false; - pHugePath_c[0] = 0; - } -}; -enum BOF_BUFFER_DELETER -{ - BOF_BUFFER_DELETER_NONE = 0, - BOF_BUFFER_DELETER_FREE, - BOF_BUFFER_DELETER_ALIGNED_FREE, - BOF_BUFFER_DELETER_DELETE -}; -struct BOF_BUFFER; -BOFSTD_EXPORT BOFERR Bof_AlignedMemFree(BOF::BOF_BUFFER &_rBuffer_X); -struct BOF_BUFFER -{ - BOF_BUFFER_DELETER Deleter_E; - uint64_t Offset_U64; // For seek - uint64_t Size_U64; - uint64_t Capacity_U64; - void *pUser; // Used by Bof_AlignedMemAlloc for example - uint8_t *pData_U8; - mutable std::mutex Mtx; - - BOF_BUFFER() - { - // for ReleaseStorage in Reset - Deleter_E = BOF_BUFFER_DELETER_NONE; - pUser = nullptr; - Offset_U64 = 0; - Size_U64 = 0; - Capacity_U64 = 0; - pData_U8 = nullptr; - // Reset(); - } - /* Use SetStorage - BOF_BUFFER(uint64_t _Capacity_U64, uint64_t _Size_U64, uint8_t *_pData_U8, bool _MustBeDeleted_B) - { - SetStorage(_Capacity_U64, _Size_U64, _pData_U8); - MustBeDeleted_B = _MustBeDeleted_B; - MustBeFreeed_B = false; - } - */ - ~BOF_BUFFER() - { - Reset(); - } - // Copy constructor as we use mutable std::mutex https://stackoverflow.com/questions/30340029/copy-class-with-stdmutex - BOF_BUFFER(const BOF_BUFFER &_rOther_X) - { - std::lock_guard Lock(Mtx); - Deleter_E = BOF_BUFFER_DELETER_NONE; // Only one deleter _rOther_X.MustBeDeleted_B; - pUser = _rOther_X.pUser; - Offset_U64 = _rOther_X.Offset_U64; - Size_U64 = _rOther_X.Size_U64; - Capacity_U64 = _rOther_X.Capacity_U64; - pData_U8 = _rOther_X.pData_U8; - } - BOF_BUFFER &operator=(const BOF_BUFFER &_rOther_X) - { - std::lock_guard Lock(Mtx); - Deleter_E = BOF_BUFFER_DELETER_NONE; // Only one deleter _rOther_X.MustBeDeleted_B; - pUser = _rOther_X.pUser; - Offset_U64 = _rOther_X.Offset_U64; - Size_U64 = _rOther_X.Size_U64; - Capacity_U64 = _rOther_X.Capacity_U64; - pData_U8 = _rOther_X.pData_U8; - return *this; - } - BOF_BUFFER &operator=(const BOF_BUFFER &&_rrOther_X) noexcept - { - std::lock_guard Lock(Mtx); - Deleter_E = BOF_BUFFER_DELETER_NONE; // Only one deleter _rOther_X.MustBeDeleted_B; - pUser = _rrOther_X.pUser; - Offset_U64 = _rrOther_X.Offset_U64; - Size_U64 = _rrOther_X.Size_U64; - Capacity_U64 = _rrOther_X.Capacity_U64; - pData_U8 = _rrOther_X.pData_U8; - return *this; - } - void Reset() - { - if (pData_U8) - { - //printf("WARNING: Resetting an 'active' BOF_BUFFER\n"); - } - ReleaseStorage(); - std::lock_guard Lock(Mtx); - Deleter_E = BOF_BUFFER_DELETER_NONE; - pUser = nullptr; - Offset_U64 = 0; - Size_U64 = 0; - Capacity_U64 = 0; - pData_U8 = nullptr; - } - - void Clear() - { - std::lock_guard Lock(Mtx); - Offset_U64 = 0; - Size_U64 = 0; - } - uint8_t *SetStorage(uint64_t _Capacity_U64, uint64_t _Size_U64, uint8_t *_pData_U8) - { - BOF_ASSERT(_Capacity_U64 < 0x100000000); // For the moment - ReleaseStorage(); - - Deleter_E = BOF_BUFFER_DELETER_NONE; - if (_pData_U8) - { - pData_U8 = _pData_U8; // Caller can set Deleter_E if needed - } - else - { - pData_U8 = AllocStorage(_Capacity_U64); // Will set MustBeDeleted_B to true - } - std::lock_guard Lock(Mtx); - Capacity_U64 = _Capacity_U64; - - Offset_U64 = 0; - if (_Size_U64 <= _Capacity_U64) - { - Size_U64 = _Size_U64; - } - else - { - Size_U64 = 0; - } - return pData_U8; - } - - uint64_t RemainToWrite() - { - // Called by read/write std::lock_guard Lock(Mtx); - return (Size_U64 <= Capacity_U64) ? Capacity_U64 - Size_U64 : 0; - } - uint64_t RemainToRead() - { - // Called by read/write std::lock_guard Lock(Mtx); - return (Offset_U64 < Size_U64) ? Size_U64 - Offset_U64 : 0; - } - uint8_t *Pos() - { - uint8_t *pRts_U8 = nullptr; - - std::lock_guard Lock(Mtx); - if (IsValid()) - { - pRts_U8 = &pData_U8[Size_U64]; - } - return pRts_U8; - } - uint8_t *SeekAbs(uint64_t _Offset_U64, uint64_t &_rRemain_U64) - { - uint8_t *pRts_U8 = nullptr; - - std::lock_guard Lock(Mtx); - if (_Offset_U64 <= Size_U64) - { - Offset_U64 = _Offset_U64; - _rRemain_U64 = Size_U64 - Offset_U64; - pRts_U8 = &pData_U8[Offset_U64]; - } - return pRts_U8; - } - uint8_t *SeekRel(int64_t _Amount_S64, uint64_t &_rRemain_U64) - { - uint8_t *pRts_U8 = nullptr; - uint64_t NewOffset_U64; - - std::lock_guard Lock(Mtx); - NewOffset_U64 = Offset_U64 + _Amount_S64; - if (NewOffset_U64 <= Size_U64) - { - Offset_U64 = NewOffset_U64; - _rRemain_U64 = Size_U64 - Offset_U64; - pRts_U8 = &pData_U8[Offset_U64]; - } - return pRts_U8; - } - uint8_t *Read(uint64_t _Size_U64, uint64_t &_rNbRead_U64) - { - uint8_t *pRts_U8 = nullptr; - uint64_t Remain_U64; - - std::lock_guard Lock(Mtx); - _rNbRead_U64 = 0; - if (IsValid()) - { - Remain_U64 = RemainToRead(); - _rNbRead_U64 = (Remain_U64 < _Size_U64) ? Remain_U64 : _Size_U64; - if (_rNbRead_U64) - { - pRts_U8 = &pData_U8[Offset_U64]; - Offset_U64 += _rNbRead_U64; - } - } - return pRts_U8; - } - uint8_t *Write(uint64_t _Size_U64, const uint8_t *_pData_U8, uint64_t &_rNbWritten_U64) - { - uint8_t *pRts_U8 = nullptr; - uint64_t Free_U64; - - std::lock_guard Lock(Mtx); - _rNbWritten_U64 = 0; - if ((IsValid()) && (_pData_U8)) - { - Free_U64 = RemainToWrite(); - _rNbWritten_U64 = (_Size_U64 < Free_U64) ? _Size_U64 : Free_U64; - if (_rNbWritten_U64) - { - memcpy(&pData_U8[Size_U64], _pData_U8, static_cast(_rNbWritten_U64)); - Size_U64 += _rNbWritten_U64; - pRts_U8 = &pData_U8[Size_U64]; - } - } - return pRts_U8; - } - bool Memset(const uint8_t _Val_U8, uint64_t _Size_U64, uint64_t _Offset_U64) - { - bool Rts_B = false; - - std::lock_guard Lock(Mtx); - if (IsValid()) - { - if ((_Offset_U64 < Capacity_U64) && ((_Size_U64 + _Offset_U64) < Capacity_U64)) - { - memset(&pData_U8[_Offset_U64], _Val_U8, _Size_U64); - Rts_B = true; - } - } - return Rts_B; - } - bool IsValid() - { - bool Rts_B = false; - - // Called by read/write std::lock_guard Lock(Mtx); - if ((pData_U8) && (Capacity_U64)) - { - if ((Size_U64 <= Capacity_U64) && (Offset_U64 <= Size_U64)) - { - Rts_B = true; - } - } - return Rts_B; - } - - bool IsNull() - { - bool Rts_B = true; - - // Called by read/write std::lock_guard Lock(Mtx); - if ((pData_U8) && (Capacity_U64)) - { - Rts_B = false; - } - return Rts_B; - } - - uint8_t *AllocStorage(uint64_t _Capacity_U64) - { - BOF_ASSERT(_Capacity_U64 < 0x100000000); // For the moment - ReleaseStorage(); - - uint8_t *pRts = new uint8_t[static_cast(_Capacity_U64)]; - - if (pRts) - { - std::lock_guard Lock(Mtx); - Deleter_E = BOF_BUFFER_DELETER_DELETE; - Capacity_U64 = _Capacity_U64; - Offset_U64 = 0; - Size_U64 = 0; - pData_U8 = pRts; - } - return pRts; - } - void ReleaseStorage() - { - std::lock_guard Lock(Mtx); - switch (Deleter_E) - { - default: - case BOF_BUFFER_DELETER_NONE: - break; - case BOF_BUFFER_DELETER_DELETE: - BOF_SAFE_DELETE_ARRAY(pData_U8); - break; - case BOF_BUFFER_DELETER_FREE: - BOF_SAFE_FREE(pData_U8); - break; - case BOF_BUFFER_DELETER_ALIGNED_FREE: - Bof_AlignedMemFree(*this); - break; - } - Deleter_E = BOF_BUFFER_DELETER_NONE; - pData_U8 = nullptr; - Capacity_U64 = 0; - Offset_U64 = 0; - Size_U64 = 0; - } -}; -enum class BOF_ACCESS_SIZE : uint32_t -{ - BOF_ACCESS_SIZE_8 = 0, /*! we access the memory zone using 8 bits byte access.*/ - BOF_ACCESS_SIZE_16, /*! we access the memory zone using 16 bits word access.*/ - BOF_ACCESS_SIZE_32, /*! we access the memory zone using 32 bits long access.*/ - BOF_ACCESS_SIZE_64, /*! we access the memory zone using 64 bits long long access.*/ -}; - -///@return The ascii printable version of the memory zone. -///@remarks For example calling DumpMemoryZone(60, pMemoryZone_U8, 16, ' ', true, 0x12345678,true,true) will produce the following output -///@remarks Virtual <-------------- Binary Data ------------------> <--Ascii Data--> -///@remarks 12345678 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ???????????????? -///@remarks 12345688 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F ???????????????? -///@remarks 12345698 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F !"#$%&'()*+,-./ -///@remarks 123456A8 30 31 32 33 34 35 36 37 38 39 3A 3B 0123456789:; -struct BOF_DUMP_MEMORY_ZONE_PARAM -{ - uint32_t NbItemToDump_U32; ///< Specifies the number of item (uint8_t, uint16_t, uint32_t, uint64_t to dump. - const volatile void *pMemoryZone; ///< Specifies the address of the first byte of the memory zone to dump - uint32_t NbItemPerLine_U32; ///< Specifies the number of data item to dump per line. (max MAX_NBBYTEPERLINE=1024/sizeof(item)) - char Separator_c; ///< Specifies the character to use between each binary data - bool ShowHexaPrefix_B; ///< Specifies if c hexa prefix must be displayed in front of each binary data (virtual offset and binary data value) - bool GenerateVirtualOffset; ///< Specifies if the virtual offset (below) must be generated. - int64_t VirtualOffset_S64; ///< Specifies a pseudo starting counter value which will be displayed as "the address" of each dumped row. if -1 use the pMemoryZone_U8 value - bool GenerateBinaryData_B; ///< Specifies if the binary data must be generated. - bool GenerateAsciiData_B; ///< Specifies if the ascii data must be generated. - bool ReverseEndianness_B; ///< If true reverse byte ordering on an AccessSize_E (below) boundary. - BOF_ACCESS_SIZE AccessSize_E; ///< Specifies how the memory zone must be read - BOF_DUMP_MEMORY_ZONE_PARAM() - { - Reset(); - } - void Reset() - { - NbItemToDump_U32 = 0; - pMemoryZone = nullptr; - NbItemPerLine_U32 = 16; - Separator_c = ' '; - ShowHexaPrefix_B = false; - GenerateVirtualOffset = true; - VirtualOffset_S64 = -1; - GenerateBinaryData_B = true; - GenerateAsciiData_B = true; - ReverseEndianness_B = false; - AccessSize_E = BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_8; - } -}; -const uint32_t BOF_MUTEX_MAGIC = 0x01D654AC; +constexpr uint32_t BOF_MUTEX_MAGIC = 0x01D654AC; struct BOF_MUTEX { uint32_t Magic_U32; @@ -470,8 +80,7 @@ struct BOF_MUTEX } }; -const uint32_t BOF_EVENT_MAGIC = 0x1F564864; - +constexpr uint32_t BOF_EVENT_MAGIC = 0x1F564864; struct BOF_EVENT { uint32_t Magic_U32; @@ -503,8 +112,7 @@ struct BOF_EVENT } }; -const uint32_t BOF_SEMAPHORE_MAGIC = 0xABFF8974; - +constexpr uint32_t BOF_SEMAPHORE_MAGIC = 0xABFF8974; struct BOF_SEMAPHORE { uint32_t Magic_U32; @@ -532,8 +140,7 @@ struct BOF_SEMAPHORE } }; -const uint32_t BOF_CONDITIONAL_VARIABLE_MAGIC = 0xCBFDE456; - +constexpr uint32_t BOF_CONDITIONAL_VARIABLE_MAGIC = 0xCBFDE456; struct BOF_CONDITIONAL_VARIABLE { uint32_t Magic_U32; @@ -559,7 +166,7 @@ struct BOF_CONDITIONAL_VARIABLE } }; -const uint32_t BOF_FILEMAPPING_MAGIC = 0x165464DE; +constexpr uint32_t BOF_FILEMAPPING_MAGIC = 0x165464DE; enum class BOF_ACCESS_TYPE : uint32_t { BOF_ACCESS_NONE = 0x00000000, @@ -620,11 +227,6 @@ enum BOF_THREAD_SCHEDULER_POLICY }; enum BOF_THREAD_PRIORITY { - // BOF_THREAD_PRIORITY_IDLE = 1, - // BOF_THREAD_PRIORITY_TIME_CRITICAL = 99, - // BOF_THREAD_DEFAULT_PRIORITY = 0x7FFFFFFF, - // BOF_THREAD_NONE = 0x7FFFFFFE, - BOF_THREAD_PRIORITY_000 = 0, BOF_THREAD_PRIORITY_001, BOF_THREAD_PRIORITY_002, @@ -728,8 +330,7 @@ enum BOF_THREAD_PRIORITY }; using BofThreadFunction = std::function &_rThreadMustStop_B, void *_pThreadContext)>; -const uint32_t BOF_THREAD_MAGIC = 0xCBE89448; - +constexpr uint32_t BOF_THREAD_MAGIC = 0xCBE89448; struct BOF_THREAD { uint32_t Magic_U32; @@ -830,60 +431,53 @@ struct BOF_SYSTEM_USAGE_INFO uint64_t RemainingSizeInByte_U64; /* Available disk space (specified in Bof_SystemUsageInfo call)*/ } DISK; }; -// !! http://h30499.www3.hp.com/t5/Languages-and-Scripting/migration-to-64-bit-mode-semctl/td-p/3204127#.VUCj4XhV2zl !!!! -typedef union semsetgetval { - int val; /* Value for SETVAL */ -} BOF_SEM_SETGETVAL; - -BOFSTD_EXPORT uint64_t Bof_GenerateSystemVKey(bool _CreateFn_B, const char *_pFn_c, uint8_t _Id_U8); -BOFSTD_EXPORT BOFERR Bof_OpenSharedMemory(const std::string &_rName_S, uint32_t _SizeInByte_U32, BOF_ACCESS_TYPE _AccessType_E, const std::string &_rFallbackSystemVKeySubDir_S, BOF_HANDLE _DriverHandle, BOF_SHARED_MEMORY &_rSharedMemory_X); -BOFSTD_EXPORT bool Bof_IsSharedMemoryValid(BOF_SHARED_MEMORY &_rSharedMemory_X); -BOFSTD_EXPORT BOFERR Bof_CloseSharedMemory(BOF_SHARED_MEMORY &_rSharedMemory_X, bool _RemoveIt_B); //__linux__ Need to call this at least once with _RemoveIt_B=true -BOFSTD_EXPORT BOFERR Bof_CreateSemaphore(const std::string &_rName_S, int32_t _InitialCount_S32, BOF_SEMAPHORE &_rSem_X); -BOFSTD_EXPORT bool Bof_IsSemaphoreValid(BOF_SEMAPHORE &_rSem_X); -BOFSTD_EXPORT BOFERR Bof_SignalSemaphore(BOF_SEMAPHORE &_rSem_X); -BOFSTD_EXPORT BOFERR Bof_WaitForSemaphore(BOF_SEMAPHORE &_rSem_X, uint32_t _TimeoutInMs_U32); -BOFSTD_EXPORT BOFERR Bof_DestroySemaphore(BOF_SEMAPHORE &_rSem_X); - -/** @brief A simple scoped lock type. - * - * A lock_guard controls mutex ownership within a scope, releasing - * ownership in the destructor. - */ -// Mimic std::lock_gard with an on demand Lock op to use with BOF_LOCK_GUARD_MUTEX_ENTER -template -class BofLockGuard +enum class BOF_ACCESS_SIZE : uint32_t { -public: - explicit BofLockGuard(T &_rMtx) - : mrMtx(_rMtx), mLockDone_B(false) - { - } + BOF_ACCESS_SIZE_8 = 0, /*! we access the memory zone using 8 bits byte access.*/ + BOF_ACCESS_SIZE_16, /*! we access the memory zone using 16 bits word access.*/ + BOF_ACCESS_SIZE_32, /*! we access the memory zone using 32 bits long access.*/ + BOF_ACCESS_SIZE_64, /*! we access the memory zone using 64 bits long long access.*/ +}; - void Lock() +///@return The ascii printable version of the memory zone. +///@remarks For example calling DumpMemoryZone(60, pMemoryZone_U8, 16, ' ', true, 0x12345678,true,true) will produce the following output +///@remarks Virtual <-------------- Binary Data ------------------> <--Ascii Data--> +///@remarks 12345678 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ???????????????? +///@remarks 12345688 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F ???????????????? +///@remarks 12345698 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F !"#$%&'()*+,-./ +///@remarks 123456A8 30 31 32 33 34 35 36 37 38 39 3A 3B 0123456789:; +struct BOF_DUMP_MEMORY_ZONE_PARAM +{ + uint32_t NbItemToDump_U32; ///< Specifies the number of item (uint8_t, uint16_t, uint32_t, uint64_t to dump. + const volatile void *pMemoryZone; ///< Specifies the address of the first byte of the memory zone to dump + uint32_t NbItemPerLine_U32; ///< Specifies the number of data item to dump per line. (max MAX_NBBYTEPERLINE=1024/sizeof(item)) + char Separator_c; ///< Specifies the character to use between each binary data + bool ShowHexaPrefix_B; ///< Specifies if c hexa prefix must be displayed in front of each binary data (virtual offset and binary data value) + bool GenerateVirtualOffset; ///< Specifies if the virtual offset (below) must be generated. + int64_t VirtualOffset_S64; ///< Specifies a pseudo starting counter value which will be displayed as "the address" of each dumped row. if -1 use the pMemoryZone_U8 value + bool GenerateBinaryData_B; ///< Specifies if the binary data must be generated. + bool GenerateAsciiData_B; ///< Specifies if the ascii data must be generated. + bool ReverseEndianness_B; ///< If true reverse byte ordering on an AccessSize_E (below) boundary. + BOF_ACCESS_SIZE AccessSize_E; ///< Specifies how the memory zone must be read + BOF_DUMP_MEMORY_ZONE_PARAM() { - if (!mLockDone_B) - { - mrMtx.lock(); - mLockDone_B = true; - } + Reset(); } - - ~BofLockGuard() + void Reset() { - if (mLockDone_B) - { - mrMtx.unlock(); - } + NbItemToDump_U32 = 0; + pMemoryZone = nullptr; + NbItemPerLine_U32 = 16; + Separator_c = ' '; + ShowHexaPrefix_B = false; + GenerateVirtualOffset = true; + VirtualOffset_S64 = -1; + GenerateBinaryData_B = true; + GenerateAsciiData_B = true; + ReverseEndianness_B = false; + AccessSize_E = BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_8; } - - BofLockGuard(const BofLockGuard &) = delete; - BofLockGuard &operator=(const BofLockGuard &) = delete; - -private: - std::atomic mLockDone_B; - T &mrMtx; }; BOFSTD_EXPORT BOFERR Bof_CreateMutex(const std::string &_rName_S, bool _Recursive_B, bool _PriorityInversionAware_B, BOF_MUTEX &_rMtx_X); BOFSTD_EXPORT bool Bof_IsMutexValid(BOF_MUTEX &_rMtx_X); @@ -891,23 +485,6 @@ BOFSTD_EXPORT BOFERR Bof_LockMutex(BOF_MUTEX &_rMtx_X); BOFSTD_EXPORT BOFERR Bof_UnlockMutex(BOF_MUTEX &_rMtx_X); BOFSTD_EXPORT BOFERR Bof_DestroyMutex(BOF_MUTEX &_rMtx_X); -#define BOF_GUARD_MUTEX_ENTER(MultiThreadAware, BofMutex, Sts) \ - { \ - Sts = BOF_ERR_INIT; \ - if ((!MultiThreadAware) || (BofMutex.Magic_U32 == BOF_MUTEX_MAGIC)) \ - { \ - Sts = BOF_ERR_NO_ERROR; \ - BOF::BofLockGuard Lock(BofMutex.Mtx); \ - BOF::BofLockGuard RecursiveLock(BofMutex.RecursiveMtx); \ - if (MultiThreadAware) \ - { \ - BofMutex.Recursive_B ? RecursiveLock.Lock() : Lock.Lock(); \ - } - -#define BOF_GUARD_MUTEX_LEAVE() \ - } \ - } - BOFSTD_EXPORT BOFERR Bof_CreateEvent(const std::string &_rName_S, bool _InitialState_B, uint32_t _MaxNumberToNotify_U32, bool _WaitKeepSignaled_B, bool _NotifyAll_B, BOF_EVENT &_rEvent_X); BOFSTD_EXPORT bool Bof_IsEventValid(BOF_EVENT &_rEvent_X); BOFSTD_EXPORT BOFERR Bof_SignalEvent(BOF_EVENT &_rEvent_X, uint32_t _Instance_U32); @@ -921,6 +498,72 @@ BOFSTD_EXPORT BOFERR Bof_WaitForEventMaskAnd(BOF_EVENT &_rEvent_X, uint32_t _Tim BOFSTD_EXPORT BOFERR Bof_WaitForEventMaskOr(BOF_EVENT &_rEvent_X, uint32_t _TimeoutInMs_U32, uint64_t _EventMask_U64, uint64_t &_rEventGot_U64); BOFSTD_EXPORT BOFERR Bof_DestroyEvent(BOF_EVENT &_rEvent_X); +BOFSTD_EXPORT BOFERR Bof_CreateSemaphore(const std::string &_rName_S, int32_t _InitialCount_S32, BOF_SEMAPHORE &_rSem_X); +BOFSTD_EXPORT bool Bof_IsSemaphoreValid(BOF_SEMAPHORE &_rSem_X); +BOFSTD_EXPORT BOFERR Bof_SignalSemaphore(BOF_SEMAPHORE &_rSem_X); +BOFSTD_EXPORT BOFERR Bof_WaitForSemaphore(BOF_SEMAPHORE &_rSem_X, uint32_t _TimeoutInMs_U32); +BOFSTD_EXPORT BOFERR Bof_DestroySemaphore(BOF_SEMAPHORE &_rSem_X); + +BOFSTD_EXPORT uint64_t Bof_GenerateSystemVKey(bool _CreateFn_B, const char *_pFn_c, uint8_t _Id_U8); +BOFSTD_EXPORT BOFERR Bof_OpenSharedMemory(const std::string &_rName_S, uint32_t _SizeInByte_U32, BOF_ACCESS_TYPE _AccessType_E, const std::string &_rFallbackSystemVKeySubDir_S, BOF_HANDLE _DriverHandle, BOF_SHARED_MEMORY &_rSharedMemory_X); +BOFSTD_EXPORT bool Bof_IsSharedMemoryValid(BOF_SHARED_MEMORY &_rSharedMemory_X); +BOFSTD_EXPORT BOFERR Bof_CloseSharedMemory(BOF_SHARED_MEMORY &_rSharedMemory_X, bool _RemoveIt_B); //__linux__ Need to call this at least once with _RemoveIt_B=true + +template +using BofCvPredicateAndReset = std::function; +template +using BofCvSetter = std::function; + +BOFSTD_EXPORT BOFERR Bof_CreateConditionalVariable(const std::string &_rName_S, bool _NotifyAll_B, BOF_CONDITIONAL_VARIABLE &_rCv_X); +template +BOFERR Bof_SignalConditionalVariable(BOF_CONDITIONAL_VARIABLE &_rCv_X, BofCvSetter _CvSetter, const Args &..._Args) +{ + BOFERR Rts_E = BOF_ERR_INIT; + + if (_rCv_X.Magic_U32 == BOF_CONDITIONAL_VARIABLE_MAGIC) + { + std::unique_lock WaitLock_O(_rCv_X.Mtx); + _CvSetter(_Args...); + _rCv_X.NotifyAll_B ? _rCv_X.Cv.notify_all() : _rCv_X.Cv.notify_one(); + Rts_E = BOF_ERR_NO_ERROR; + } + return Rts_E; +} +template +BOFERR Bof_WaitForConditionalVariable(BOF_CONDITIONAL_VARIABLE &_rCv_X, uint32_t _TimeoutInMs_U32, BofCvPredicateAndReset _CvPredicateAndReset, const Args &..._Args) +{ + BOFERR Rts_E = BOF_ERR_INIT; + + if (_rCv_X.Magic_U32 == BOF_CONDITIONAL_VARIABLE_MAGIC) + { + std::unique_lock WaitLock_O(_rCv_X.Mtx); + // if (_rCv_X.Cv.wait_for(WaitLock_O, std::chrono::milliseconds(_TimeoutInMs_U32), _CvPredicate(_Args...))) + Rts_E = BOF_ERR_NO_ERROR; + std::chrono::system_clock::time_point End = std::chrono::system_clock::now() + std::chrono::milliseconds(_TimeoutInMs_U32); + while (!_CvPredicateAndReset(_Args...)) + { + if (_rCv_X.Cv.wait_until(WaitLock_O, End) == std::cv_status::timeout) + { + Rts_E = _CvPredicateAndReset(_Args...) ? BOF_ERR_NO_ERROR : BOF_ERR_ETIMEDOUT; + break; + } + } + } + return Rts_E; +} +BOFSTD_EXPORT BOFERR Bof_DestroyConditionalVariable(BOF_CONDITIONAL_VARIABLE &_rCv_X); + +BOFSTD_EXPORT BOFERR Bof_GetMemoryState(uint64_t &_rAvailableFreeMemory_U64, uint64_t &_rTotalMemorySize_U64); +//_OsAdvice_i mainly for MADV_DONTFORK option in madvise +BOFSTD_EXPORT BOFERR Bof_LockMem(int _OsAdvice_i, uint64_t _SizeInByte_U64, void *_pData); +BOFSTD_EXPORT BOFERR Bof_UnlockMem(uint64_t _SizeInByte_U64, void *_pData); +BOFSTD_EXPORT bool Bof_AlignedMemCpy8(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32); +BOFSTD_EXPORT bool Bof_AlignedMemCpy16(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32); +BOFSTD_EXPORT bool Bof_AlignedMemCpy32(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32); +BOFSTD_EXPORT BOFERR Bof_AlignedMemAlloc(BOF_BUFFER_ALLOCATE_ZONE _AllocateZone_E, uint32_t _AligmentInByte_U32, uint32_t _SizeInByte_U32, bool _LockIt_B, int _OsAdvice_i, bool _ClearIt_B, BOF_BUFFER &_rAllocatedBuffer_X); +BOFSTD_EXPORT BOFERR Bof_AlignedMemFree(BOF::BOF_BUFFER &_rBuffer_X); +BOFSTD_EXPORT std::string Bof_DumpMemoryZone(const BOF_DUMP_MEMORY_ZONE_PARAM &_rDumpMemoryZoneParam_X); + BOFSTD_EXPORT int32_t Bof_PriorityValueFromThreadPriority(BOF_THREAD_PRIORITY _Priority_E); BOFSTD_EXPORT BOF_THREAD_PRIORITY Bof_ThreadPriorityFromPriorityValue(int32_t _Priority_S32); BOFSTD_EXPORT BOFERR Bof_GetThreadPriorityRange(BOF_THREAD_SCHEDULER_POLICY _ThreadSchedulerPolicy_E, BOF_THREAD_PRIORITY &_rMin_E, BOF_THREAD_PRIORITY &_rMax_E); @@ -934,27 +577,20 @@ BOFSTD_EXPORT BOFERR Bof_CreateThread(const std::string &_rName_S, BofThreadFunc BOFSTD_EXPORT bool Bof_IsThreadValid(BOF_THREAD &_rThread_X); BOFSTD_EXPORT BOFERR Bof_StartThread(BOF_THREAD &_rThread_X, uint32_t _StackSize_U32, uint32_t _ThreadCpuCoreAffinity_U32, BOF_THREAD_SCHEDULER_POLICY _ThreadSchedulerPolicy_E, BOF_THREAD_PRIORITY _ThreadPriority_E, uint32_t _StartStopTimeoutInMs_U32); BOFSTD_EXPORT BOFERR Bof_StopThread(BOF_THREAD &_rThread_X); -BOFSTD_EXPORT BOFERR Bof_GetMemoryState(uint64_t &_rAvailableFreeMemory_U64, uint64_t &_rTotalMemorySize_U64); + +BOFSTD_EXPORT BOFERR Bof_GetLastError(bool _NetError_B, int32_t *_pNativeErrorCode_S32 = nullptr); +BOFSTD_EXPORT bool Bof_PatternCompare(const char *_pString_c, const char *_pPattern_c); BOFSTD_EXPORT uint32_t Bof_InterlockedCompareExchange(volatile uint32_t *_pDestination_U32, uint32_t _ValueToSetIfEqual_U32, uint32_t _CheckIfEqualToThis_U32); // See BOF_COM_RAM_CMD_STATE for example BOFSTD_EXPORT bool Bof_IsPidRunning(uint32_t _Pid_U32); BOFSTD_EXPORT uint32_t Bof_GetCurrentPid(); -BOFSTD_EXPORT BOFERR Bof_GetLastError(bool _NetError_B, int32_t *_pNativeErrorCode_S32 = nullptr); -BOFSTD_EXPORT bool Bof_PatternCompare(const char *_pString_c, const char *_pPattern_c); BOFSTD_EXPORT BOFERR Bof_Exec(const std::string &_rCommand_S, std::string *_pCapturedOutput_S, int32_t &_rExitCode_S32); BOFSTD_EXPORT const char *Bof_GetEnvVar(const char *_pName_c); BOFSTD_EXPORT int Bof_SetEnvVar(const char *_pName_c, const char *_pValue_c, int _Overwrite_i); -//_OsAdvice_i mainly for MADV_DONTFORK option in madvise -BOFSTD_EXPORT BOFERR Bof_LockMem(int _OsAdvice_i, uint64_t _SizeInByte_U64, void *_pData); -BOFSTD_EXPORT BOFERR Bof_UnlockMem(uint64_t _SizeInByte_U64, void *_pData); -BOFSTD_EXPORT bool Bof_AlignedMemCpy8(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32); -BOFSTD_EXPORT bool Bof_AlignedMemCpy16(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32); -BOFSTD_EXPORT bool Bof_AlignedMemCpy32(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32); -BOFSTD_EXPORT BOFERR Bof_AlignedMemAlloc(BOF_BUFFER_ALLOCATE_ZONE _AllocateZone_E, uint32_t _AligmentInByte_U32, uint32_t _SizeInByte_U32, bool _LockIt_B, int _OsAdvice_i, bool _ClearIt_B, BOF_BUFFER &_rAllocatedBuffer_X); -BOFSTD_EXPORT BOFERR Bof_AlignedMemFree(BOF::BOF_BUFFER &_rBuffer_X); -BOFSTD_EXPORT std::string Bof_DumpMemoryZone(const BOF_DUMP_MEMORY_ZONE_PARAM &_rDumpMemoryZoneParam_X); + BOFSTD_EXPORT int32_t Bof_Random(bool _Reset_B, int32_t _MinValue_S32, int32_t _MaxValue_S32); BOFSTD_EXPORT std::string Bof_Random(bool _Reset_B, uint32_t _Size_U32, char _MinValue_c, char _MaxValue_c); BOFSTD_EXPORT std::string Bof_RandomHexa(bool _Reset_B, uint32_t _Size_U32, bool _Upper_B); + BOFSTD_EXPORT BOFERR Bof_ReEvaluateTimeout(uint32_t _Start_U32, uint32_t &_rNewTimeOut_U32); BOFSTD_EXPORT void Bof_MsSleep(uint32_t _Ms_U32); BOFSTD_EXPORT void Bof_UsSleep(uint32_t _Us_U32); @@ -976,7 +612,6 @@ inline char Bof_FilenameSeparator() return '\\'; } #else - inline const char *Bof_Eol() { return "\n"; @@ -986,62 +621,8 @@ inline char Bof_FilenameSeparator() { return '/'; } -void Bof_LockRam_ShowNewPagefaultCount(const char *logtext, const char *allowed_maj, const char *allowed_min); -BOFERR Bof_LockRam(uint32_t _StackSizeInByte_U32, uint64_t _ReserveProcessMemoryInByte_U64); #endif -template -auto Bof_EraseWhere(Container &_Container, SearchFunc &&_Func) -> decltype(_Container.end()) -{ - return _Container.erase(std::remove_if(_Container.begin(), _Container.end(), std::forward(_Func)), _Container.end()); -} - -template -using BofCvPredicateAndReset = std::function; -template -using BofCvSetter = std::function; - -BOFSTD_EXPORT BOFERR Bof_CreateConditionalVariable(const std::string &_rName_S, bool _NotifyAll_B, BOF_CONDITIONAL_VARIABLE &_rCv_X); - -template -BOFERR Bof_SignalConditionalVariable(BOF_CONDITIONAL_VARIABLE &_rCv_X, BofCvSetter _CvSetter, const Args &..._Args) -{ - BOFERR Rts_E = BOF_ERR_INIT; - - if (_rCv_X.Magic_U32 == BOF_CONDITIONAL_VARIABLE_MAGIC) - { - std::unique_lock WaitLock_O(_rCv_X.Mtx); - _CvSetter(_Args...); - _rCv_X.NotifyAll_B ? _rCv_X.Cv.notify_all() : _rCv_X.Cv.notify_one(); - Rts_E = BOF_ERR_NO_ERROR; - } - return Rts_E; -} - -template -BOFERR Bof_WaitForConditionalVariable(BOF_CONDITIONAL_VARIABLE &_rCv_X, uint32_t _TimeoutInMs_U32, BofCvPredicateAndReset _CvPredicateAndReset, const Args &..._Args) -{ - BOFERR Rts_E = BOF_ERR_INIT; - - if (_rCv_X.Magic_U32 == BOF_CONDITIONAL_VARIABLE_MAGIC) - { - std::unique_lock WaitLock_O(_rCv_X.Mtx); - // if (_rCv_X.Cv.wait_for(WaitLock_O, std::chrono::milliseconds(_TimeoutInMs_U32), _CvPredicate(_Args...))) - Rts_E = BOF_ERR_NO_ERROR; - std::chrono::system_clock::time_point End = std::chrono::system_clock::now() + std::chrono::milliseconds(_TimeoutInMs_U32); - while (!_CvPredicateAndReset(_Args...)) - { - if (_rCv_X.Cv.wait_until(WaitLock_O, End) == std::cv_status::timeout) - { - Rts_E = _CvPredicateAndReset(_Args...) ? BOF_ERR_NO_ERROR : BOF_ERR_ETIMEDOUT; - break; - } - } - } - return Rts_E; -} - -BOFSTD_EXPORT BOFERR Bof_DestroyConditionalVariable(BOF_CONDITIONAL_VARIABLE &_rCv_X); BOFSTD_EXPORT BOFERR Bof_SystemUsageInfo(const char *_pDiskName_c, BOF_SYSTEM_USAGE_INFO &_rSystemUsageInfo_X); END_BOF_NAMESPACE() \ No newline at end of file diff --git a/lib/src/bofsystem.cpp b/lib/src/bofsystem.cpp index e2e944a5..e1f4c87d 100644 --- a/lib/src/bofsystem.cpp +++ b/lib/src/bofsystem.cpp @@ -168,772 +168,310 @@ static std::mt19937 S_RandomGenerator(std::random_device{}()); static std::uniform_real_distribution S_RandomFloatDistribution(0.0, 1.0f); static std::atomic S_BofThreadBalance = 0; -// man ftok: _Id_U8 the least significant 8 bits of proj_id (which must be nonzero) -uint64_t Bof_GenerateSystemVKey(bool _CreateFn_B, const char *_pFn_c, uint8_t _Id_U8) +BOFERR Bof_CreateMutex(const std::string &_rName_S, bool _Recursive_B, bool _PriorityInversionAware_B, BOF_MUTEX &_rMtx_X) { - uint64_t Rts_U64 = -1; // IPC_PRIVATE is 0 - char pFn_c[512]; //, *pId_c; - uintptr_t Io; - bool ItIsADirectory_B; + BOFERR Rts_E = BOF_ERR_EEXIST; - if (_Id_U8) + if (_rMtx_X.Magic_U32 != BOF_MUTEX_MAGIC) { - if ((_pFn_c == nullptr) || (_pFn_c[0] == 0)) + _rMtx_X.Reset(); + _rMtx_X.Magic_U32 = BOF_MUTEX_MAGIC; + _rMtx_X.Name_S = _rName_S; + _rMtx_X.Recursive_B = _Recursive_B; +#if defined(_WIN32) +#else + if (_PriorityInversionAware_B) + { + // https://sakhnik.com/2017/07/16/custom-mutex.html + + pthread_mutexattr_t Attributes_X; + // Destroy the underlying mutex + ::pthread_mutex_destroy(_rMtx_X.Mtx.native_handle()); + ::pthread_mutex_destroy(_rMtx_X.RecursiveMtx.native_handle()); + + // Create mutex attribute with desired protocol + pthread_mutexattr_init(&Attributes_X); + pthread_mutexattr_setprotocol(&Attributes_X, PTHREAD_PRIO_INHERIT); + ::pthread_mutex_init(_rMtx_X.Mtx.native_handle(), &Attributes_X); + ::pthread_mutexattr_destroy(&Attributes_X); + + pthread_mutexattr_init(&Attributes_X); + pthread_mutexattr_settype(&Attributes_X, PTHREAD_MUTEX_RECURSIVE); + pthread_mutexattr_setprotocol(&Attributes_X, PTHREAD_PRIO_INHERIT); + ::pthread_mutex_init(_rMtx_X.RecursiveMtx.native_handle(), &Attributes_X); + ::pthread_mutexattr_destroy(&Attributes_X); + } + // BOFERR e=Bof_LockMutex(_rMtx_X); + // e=Bof_LockMutex(_rMtx_X); +#endif + Rts_E = BOF_ERR_NO_ERROR; + } + return Rts_E; +} + +bool Bof_IsMutexValid(BOF_MUTEX &_rMtx_X) +{ + return (_rMtx_X.Magic_U32 == BOF_MUTEX_MAGIC); +} + +BOFERR Bof_LockMutex(BOF_MUTEX &_rMtx_X) +{ + BOFERR Rts_E = BOF_ERR_INIT; + + if (_rMtx_X.Magic_U32 == BOF_MUTEX_MAGIC) + { + Rts_E = BOF_ERR_NO_ERROR; + try { - strcpy(pFn_c, "/dev/null"); // /dev/null is supposed to be present on alll unix station.. - _CreateFn_B = false; + _rMtx_X.Recursive_B ? _rMtx_X.RecursiveMtx.lock() : _rMtx_X.Mtx.lock(); } - else + catch (const std::exception &e) { - strcpy(pFn_c, _pFn_c); + // printf("mutex exception %s\n", e.what()); + Rts_E = BOF_ERR_OPERATION_FAILED; } + } + return Rts_E; +} -#if 0 - if (_Id_U8 == 0) +BOFERR Bof_UnlockMutex(BOF_MUTEX &_rMtx_X) +{ + BOFERR Rts_E = BOF_ERR_INIT; + + if (_rMtx_X.Magic_U32 == BOF_MUTEX_MAGIC) { - // Check if id is set in filename. for example you can specify a path to your app exe such as /usr/mc/ucode followed by a numeric id->/usr/mc/ucode/23 - pId_c = strrchr(pFn_c, '/'); - if (pId_c != nullptr) - { - _Id_U8 = atoi(pId_c + 1); - if (_Id_U8 == 0) - { - _Id_U8 = *(pId_c + 1); // pFn_c[0]; - } - else - { - *pId_c = (char)0; // keep path to existing file and remove id component - // _CreateFn_B = false; //In that case the file must exist and could be on a read only disk - } - } - } -#endif - if (_CreateFn_B) + Rts_E = BOF_ERR_NO_ERROR; + try { - // Bof_CreateFile(BOF::BOF_FILE_PERMISSION_READ_FOR_ALL | BOF::BOF_FILE_PERMISSION_WRITE_FOR_ALL, pFn_c, false, Io); // If it fails, it will also fails on the following line - Bof_CreateFile(BOF_FILE_PERMISSION_DEFAULT_R, pFn_c, false, Io); // If it fails, it will also fails on the following line + _rMtx_X.Recursive_B ? _rMtx_X.RecursiveMtx.unlock() : _rMtx_X.Mtx.unlock(); } - if (Bof_IsPathExist(pFn_c, ItIsADirectory_B)) + catch (const std::exception &e) { -#if defined(_WIN32) - Rts_U64 = 0; -#else - Rts_U64 = (uint64_t)ftok(pFn_c, _Id_U8); // ftok need an exiting filename . -#endif + // printf("mutex exception %s\n", e.what()); + Rts_E = BOF_ERR_OPERATION_FAILED; } } - return Rts_U64; + return Rts_E; } -// TODO: When validated, remove functionS just after in the#if 0 with the old file mapppint api... -// TODO: NMA ? -// BHA->Should use Bof_OpenFileMapping and co in bofportability -// and Bof_CreateFileMapping does not correcly generate SemKey = ftok(pFile_c, (char) Id_i); ->use GenerateSystemVKey -// if app crash shared memory stay active=>this is mainly use by nma to store event name->this should also work with Bof_OpenFileMapping=> a confimer avec nma +BOFERR Bof_DestroyMutex(BOF_MUTEX &_rMtx_X) +{ + BOFERR Rts_E = BOF_ERR_INIT; -BOFERR Bof_OpenSharedMemory(const std::string &_rName_S, uint32_t _SizeInByte_U32, BOF_ACCESS_TYPE _AccessType_E, const std::string &_rFallbackSystemVKeySubDir_S, BOF_HANDLE _DriverHandle, BOF_SHARED_MEMORY &_rSharedMemory_X) + if (_rMtx_X.Magic_U32 == BOF_MUTEX_MAGIC) + { + _rMtx_X.Reset(); + Rts_E = BOF_ERR_NO_ERROR; + } + return Rts_E; +} + +BOFERR Bof_CreateEvent(const std::string &_rName_S, bool _InitialState_B, uint32_t _MaxNumberToNotify_U32, bool _WaitKeepSignaled_B, bool _NotifyAll_B, bool _PriorityInversionAware_B, BOF_EVENT &_rEvent_X) { - BOFERR Rts_E = BOF_ERR_ALREADY_OPENED; + BOFERR Rts_E = BOF_ERR_EEXIST; - if (_rSharedMemory_X.Magic_U32 != BOF_FILEMAPPING_MAGIC) + if (_rEvent_X.Magic_U32 != BOF_EVENT_MAGIC) { - _rSharedMemory_X.Reset(); - _rSharedMemory_X.Name_S = _rName_S; - _rSharedMemory_X.SizeInByte_U32 = _SizeInByte_U32; -#if defined(_WIN32) - // char pName_c[512]; - PSECURITY_DESCRIPTOR pSecurityDescriptor_X; - SECURITY_ATTRIBUTES SecurityAttribute_X; - uint32_t Flag_U32; - Rts_E = BOF_ERR_EACCES; - // Name must start with Global\\->Responsabilities of the caller ! - if ((strncmp(_rSharedMemory_X.Name_S.c_str(), "Global\\", 7)) && (strncmp(_rSharedMemory_X.Name_S.c_str(), "Local\\", 6))) + Rts_E = BOF_ERR_EINVAL; + if ((_MaxNumberToNotify_U32) && (_MaxNumberToNotify_U32 <= 64)) { + _rEvent_X.Reset(); + _rEvent_X.Name_S = _rName_S; + _rEvent_X.SignaledBitmask_U64 = _InitialState_B ? (1 << (_MaxNumberToNotify_U32 - 1)) - 1 : 0; + _rEvent_X.MaxNumberToNotify_U32 = _MaxNumberToNotify_U32; + _rEvent_X.WaitKeepSignaled_B = _WaitKeepSignaled_B; + _rEvent_X.NotifyAll_B = _NotifyAll_B; + _rEvent_X.Magic_U32 = BOF_EVENT_MAGIC; + Rts_E = BOF_ERR_NO_ERROR; } - // bool k=CreateMyDACL(&SecurityAttribute_X); - pSecurityDescriptor_X = CreateWinSecurityDescriptor(&SecurityAttribute_X); + } - if ((pSecurityDescriptor_X) - // && (Bof_MultiByteToWideChar(_rSharedMemory_X.Name_S.c_str(), sizeof(pName_wc) / sizeof(WCHAR), pName_wc)>=0) - ) - { - Rts_E = BOF_ERR_EINVAL; - // Name must start with Global\\->Responsabilities of the caller ! sinon Rts_h = BOF_INVALID_HANDLE_VALUE; - // _rSharedMemory_X.pHandle = CreateFileMapping(BOF_INVALID_HANDLE_VALUE, &SecurityAttribute_X, PAGE_READWRITE | SEC_COMMIT, 0, _SizeInByte_U32, pName_c); + return Rts_E; +} - Flag_U32 = 0; +bool Bof_IsEventValid(BOF_EVENT &_rEvent_X) +{ + return (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC); +} - if (Bof_IsAllBitFlagSet(_AccessType_E, BOF_ACCESS_TYPE::BOF_ACCESS_READ | BOF_ACCESS_TYPE::BOF_ACCESS_WRITE)) - { - Flag_U32 |= PAGE_READWRITE | SEC_COMMIT; - } - else if (Bof_IsAnyBitFlagSet(_AccessType_E, BOF_ACCESS_TYPE::BOF_ACCESS_READ)) - { - Flag_U32 |= PAGE_READONLY; - } - else if (Bof_IsAnyBitFlagSet(_AccessType_E, BOF::BOF_ACCESS_TYPE::BOF_ACCESS_WRITE)) +BOFERR Bof_SignalEvent(BOF_EVENT &_rEvent_X, uint32_t _Instance_U32) +{ + BOFERR Rts_E = BOF_ERR_INIT; + + if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) + { + Rts_E = BOF_ERR_EINVAL; + if (_Instance_U32 < _rEvent_X.MaxNumberToNotify_U32) + { + std::unique_lock WaitLock_O(_rEvent_X.Mtx); + _rEvent_X.SignaledBitmask_U64 |= (static_cast(1) << _Instance_U32); + if (_rEvent_X.NotifyAll_B) { - Flag_U32 |= PAGE_READWRITE | SEC_COMMIT; + _rEvent_X.Cv.notify_all(); } - _rSharedMemory_X.pHandle = CreateFileMappingA(INVALID_HANDLE_VALUE, &SecurityAttribute_X, Flag_U32, 0, _SizeInByte_U32, _rSharedMemory_X.Name_S.c_str()); - if (_rSharedMemory_X.pHandle) + else { - Rts_E = Bof_GetLastError(false); - if ((Rts_E == BOF_ERR_EEXIST) || (Rts_E == BOF_ERR_NO_ERROR)) - { - _rSharedMemory_X.pBaseAddress = MapViewOfFile(_rSharedMemory_X.pHandle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); - if (_rSharedMemory_X.pBaseAddress == nullptr) - { - Rts_E = BOF_ERR_MAP; - } - else - { - _rSharedMemory_X.DriverHandle = _DriverHandle; - _rSharedMemory_X.Magic_U32 = BOF_FILEMAPPING_MAGIC; - } - } + _rEvent_X.Cv.notify_one(); } + Rts_E = BOF_ERR_NO_ERROR; } + } -#else - // std::string Name_S; - int Handle_i, Access_i; - std::string Name_S; - mode_t Mode; - key_t ShmKey; + return Rts_E; +} +/* +BOFERR Bof_ResetEvent(BOF_EVENT &_rEvent_X, uint32_t _Instance_U32) +{ + BOFERR Rts_E = BOF_ERR_INIT; + if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) + { Rts_E = BOF_ERR_EINVAL; - _rSharedMemory_X.HandleSystemV_i = -1; - if (isalpha(_rSharedMemory_X.Name_S[0])) + if (_Instance_U32 < _rEvent_X.MaxNumberToNotify_U32) { - // Posix shm name must begin with a / - Name_S = "/" + _rSharedMemory_X.Name_S; + std::unique_lock WaitLock_O(_rEvent_X.Mtx); + _rEvent_X.SignaledBitmask_U64 &= ~(1 << _Instance_U32); + Rts_E = BOF_ERR_NO_ERROR; } - else + } + + return Rts_E; +} + +BOFERR Bof_ResetEvent(BOF_EVENT &_rEvent_X) +{ + BOFERR Rts_E = BOF_ERR_INIT; + + if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) + { + std::unique_lock WaitLock_O(_rEvent_X.Mtx); + _rEvent_X.SignaledBitmask_U64 = 0; + Rts_E = BOF_ERR_NO_ERROR; + } + return Rts_E; +} +*/ +bool Bof_IsEventSignaled(BOF_EVENT &_rEvent_X, uint32_t _Instance_U32) +{ + bool Rts_B = false; + + if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) + { + if (_Instance_U32 < _rEvent_X.MaxNumberToNotify_U32) { - Name_S = _rSharedMemory_X.Name_S; + std::unique_lock WaitLock_O(_rEvent_X.Mtx); + Rts_B = (_rEvent_X.SignaledBitmask_U64 & (static_cast(1) << _Instance_U32)) ? true : false; } - if (Name_S[0] == '/') - { - Rts_E = BOF_ERR_FORMAT; - if (strchr(Name_S.c_str() + 1, '/') == nullptr) - { - Rts_E = BOF_ERR_NOT_OPENED; -#if defined(__ANDROID__) - Handle_i = -1; - Rts_E = BOF_ERR_EEXIST; -#else - Access_i = O_CREAT | O_EXCL; - Mode = 0; - if (Bof_IsAllBitFlagSet(_AccessType_E, BOF_ACCESS_TYPE::BOF_ACCESS_READ | BOF_ACCESS_TYPE::BOF_ACCESS_WRITE)) - { - Access_i |= O_RDWR; - Mode |= S_IRUSR | S_IWUSR; - } - else if (Bof_IsAnyBitFlagSet(_AccessType_E, BOF_ACCESS_TYPE::BOF_ACCESS_READ)) - { - Access_i |= O_RDONLY; - Mode |= S_IRUSR; - } - else if (Bof_IsAnyBitFlagSet(_AccessType_E, BOF::BOF_ACCESS_TYPE::BOF_ACCESS_WRITE)) - { - Access_i |= O_RDWR; - Mode |= S_IRUSR | S_IWUSR; - } - if (BOF_IS_HANDLE_VALID(_DriverHandle)) - { - _rSharedMemory_X.pBaseAddress = mmap(nullptr, _SizeInByte_U32, PROT_READ | PROT_WRITE, MAP_SHARED, _DriverHandle, 0); - if (_rSharedMemory_X.pBaseAddress != MAP_FAILED) - { - printf("Bof_OpenSharedMemory '%s' 0: pMap %x:%p\n", Name_S.c_str(), _SizeInByte_U32, _rSharedMemory_X.pBaseAddress); - Rts_E = BOF_ERR_NO_ERROR; - } - } - else - { - Handle_i = shm_open(Name_S.c_str(), Access_i, Mode); - printf("Bof_OpenSharedMemory '%s' 1: Acc %x Mode %d Size %X -> Hndl %d errno %d\n", Name_S.c_str(), Access_i, Mode, _SizeInByte_U32, Handle_i, errno); - if (Handle_i >= 0) - { - Rts_E = (ftruncate(Handle_i, _rSharedMemory_X.SizeInByte_U32) == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_WRONG_SIZE; - } - else - { - // Handle_i = shm_open(Name_S.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - Access_i ^= O_EXCL; - Handle_i = shm_open(Name_S.c_str(), Access_i, Mode); - printf("Bof_OpenSharedMemory '%s' 2: Acc %x Mode %d Size %X -> Hndl %d errno %d\n", Name_S.c_str(), Access_i, Mode, _SizeInByte_U32, Handle_i, errno); - if (Handle_i >= 0) - { - Rts_E = BOF_ERR_EEXIST; - } - } - if (Handle_i >= 0) - { - _rSharedMemory_X.pBaseAddress = mmap(nullptr, _SizeInByte_U32, PROT_READ | PROT_WRITE, MAP_SHARED, Handle_i, 0); - if (_rSharedMemory_X.pBaseAddress != MAP_FAILED) - { - printf("Bof_OpenSharedMemory '%s' 3: pMap %x:%p\n", Name_S.c_str(), _SizeInByte_U32, _rSharedMemory_X.pBaseAddress); - if (Rts_E != BOF_ERR_EEXIST) - { - Rts_E = BOF_ERR_NO_ERROR; - } - } - close(Handle_i); // After a call to mmap(2) the file descriptor may be closed without affecting the memory mapping. - } - else - { - // Posix interface failed (tge2 docket), fallback on System V api - _rSharedMemory_X.PathNameSystemV_S = _rFallbackSystemVKeySubDir_S + Name_S; - ShmKey = Bof_GenerateSystemVKey(true, _rSharedMemory_X.PathNameSystemV_S.c_str(), 1); - // ShmKey = Bof_GenerateSystemVKey(true, nullptr, 1); - printf("Bof_OpenSharedMemory '%s' 4: key %x\n", _rSharedMemory_X.PathNameSystemV_S.c_str(), ShmKey); - if (ShmKey != -1) - { - // Handle_i = shmget(IPC_PRIVATE, _SizeInByte_U32, IPC_EXCL | IPC_CREAT | 0666); - // printf("%x %d\n", 0666, 0666); // 1b6 438 - Handle_i = shmget(ShmKey, _SizeInByte_U32, Mode); // IPC_EXCL | IPC_CREAT | 0666); - printf("Bof_OpenSharedMemory '%s' 5: Mode %d Key %x Size %X -> Hndl %d errno %d\n", _rSharedMemory_X.PathNameSystemV_S.c_str(), Mode, ShmKey, _SizeInByte_U32, Handle_i, errno); - if (Handle_i >= 0) - { - _rSharedMemory_X.pBaseAddress = shmat(Handle_i, 0, 0); - if ((uintptr_t)_rSharedMemory_X.pBaseAddress == -1) - { - Rts_E = BOF_ERR_MAP; - } - else - { - Rts_E = BOF_ERR_EEXIST; - } - } - else - { - Handle_i = shmget(ShmKey, _SizeInByte_U32, IPC_EXCL | IPC_CREAT | Mode); //| 0666); - printf("Bof_OpenSharedMemory '%s' 6: Mode %d Key %x Size %X -> Hndl %d errno %d\n", _rSharedMemory_X.PathNameSystemV_S.c_str(), Mode, ShmKey, _SizeInByte_U32, Handle_i, errno); - if (Handle_i >= 0) - { - _rSharedMemory_X.pBaseAddress = shmat(Handle_i, 0, 0); - if ((uintptr_t)_rSharedMemory_X.pBaseAddress == -1) - { - Rts_E = BOF_ERR_MAP; - } - else - { - printf("Bof_OpenSharedMemory '%s' 7: pMap %x:%p\n", Name_S.c_str(), _SizeInByte_U32, _rSharedMemory_X.pBaseAddress); - Rts_E = BOF_ERR_NO_ERROR; - } - } - } - } - } - } - if ((Rts_E == BOF_ERR_NO_ERROR) || (Rts_E == BOF_ERR_EEXIST)) - { - _rSharedMemory_X.HandleSystemV_i = Handle_i; - _rSharedMemory_X.DriverHandle = _DriverHandle; - _rSharedMemory_X.Magic_U32 = BOF_FILEMAPPING_MAGIC; - } - } - } -#endif - -#endif } - return Rts_E; + return Rts_B; } -bool Bof_IsSharedMemoryValid(BOF_SHARED_MEMORY &_rSharedMemory_X) +BOFERR Bof_SetEventMask(BOF_EVENT &_rEvent_X, uint64_t _EventVal_U64) { - return (_rSharedMemory_X.Magic_U32 == BOF_FILEMAPPING_MAGIC); + BOFERR Rts_E = BOF_ERR_INIT; + + if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) + { + std::unique_lock WaitLock_O(_rEvent_X.Mtx); + _rEvent_X.SignaledBitmask_U64 = _EventVal_U64; + Rts_E = BOF_ERR_NO_ERROR; + } + return Rts_E; } -BOFERR Bof_CloseSharedMemory(BOF_SHARED_MEMORY &_rSharedMemory_X, bool _RemoveIt_B) +BOFERR Bof_GetEventMask(BOF_EVENT &_rEvent_X, uint64_t &_rEventVal_U64) { - BOFERR Rts_E = BOF_ERR_NOT_OPENED; + BOFERR Rts_E = BOF_ERR_INIT; - if (_rSharedMemory_X.Magic_U32 == BOF_FILEMAPPING_MAGIC) + if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) { -#if defined(_WIN32) - if (_rSharedMemory_X.pBaseAddress) + std::unique_lock WaitLock_O(_rEvent_X.Mtx); + _rEventVal_U64 = _rEvent_X.SignaledBitmask_U64; + Rts_E = BOF_ERR_NO_ERROR; + } + else + { + _rEventVal_U64 = 0; + } + return Rts_E; +} + +BOFERR Bof_WaitForEvent(BOF_EVENT &_rEvent_X, uint32_t _TimeoutInMs_U32, uint32_t _Instance_U32) +{ + BOFERR Rts_E = BOF_ERR_INIT; + if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) + { + Rts_E = BOF_ERR_EINVAL; + if (_Instance_U32 < _rEvent_X.MaxNumberToNotify_U32) { - Rts_E = UnmapViewOfFile(_rSharedMemory_X.pBaseAddress) ? BOF_ERR_NO_ERROR : BOF_ERR_UNMAP; + std::unique_lock WaitLock_O(_rEvent_X.Mtx); + if (_rEvent_X.Cv.wait_for(WaitLock_O, std::chrono::milliseconds(_TimeoutInMs_U32), [&]() { bool Rts_B = (_rEvent_X.SignaledBitmask_U64 & (static_cast(1) << _Instance_U32)); if ((Rts_B) && (!_rEvent_X.WaitKeepSignaled_B)) _rEvent_X.SignaledBitmask_U64 &= ~(1 << _Instance_U32); return Rts_B; })) + { + Rts_E = BOF_ERR_NO_ERROR; + } + else + { + Rts_E = BOF_ERR_ETIMEDOUT; + } } - else + } + return Rts_E; +} + +BOFERR Bof_WaitForEventMaskAnd(BOF_EVENT &_rEvent_X, uint32_t _TimeoutInMs_U32, uint64_t _EventMask_U64) +{ + BOFERR Rts_E = BOF_ERR_INIT; + if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) + { + std::unique_lock WaitLock_O(_rEvent_X.Mtx); + if (_rEvent_X.Cv.wait_for(WaitLock_O, std::chrono::milliseconds(_TimeoutInMs_U32), [&]() {bool Rts_B = ((_rEvent_X.SignaledBitmask_U64 & _EventMask_U64) == _EventMask_U64); if ((Rts_B) && (!_rEvent_X.WaitKeepSignaled_B)) _rEvent_X.SignaledBitmask_U64 &= ~_EventMask_U64; return Rts_B; })) { Rts_E = BOF_ERR_NO_ERROR; } - if (Rts_E == BOF_ERR_NO_ERROR) + else { - if (_rSharedMemory_X.pHandle) - { - Rts_E = CloseHandle(_rSharedMemory_X.pHandle) ? BOF_ERR_NO_ERROR : BOF_ERR_CLOSE; - } + Rts_E = BOF_ERR_ETIMEDOUT; } -#else - int Sts_i; - if (_rSharedMemory_X.pBaseAddress) - { - if (_rSharedMemory_X.HandleSystemV_i >= 0) - { - Rts_E = (shmdt(_rSharedMemory_X.pBaseAddress) != -1) ? BOF_ERR_NO_ERROR : BOF_ERR_UNMAP; - printf("shmdt errno %d Rts_E %d\n", errno, Rts_E); - if ((Rts_E == BOF_ERR_NO_ERROR) || (Rts_E == BOF_ERR_ENOTDIR)) - { - // NO !! Sts_i = close(_rSharedMemory_X.HandleSystemV_i); - // Can fail if already _RemoveIt_B by someone else Rts_E = (Sts_i == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_CLOSE; - Rts_E = BOF_ERR_NO_ERROR; - } - } - else - { - Rts_E = (munmap(_rSharedMemory_X.pBaseAddress, _rSharedMemory_X.SizeInByte_U32) == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_UNMAP; - if (Rts_E == BOF_ERR_NO_ERROR) - { - // close handle already made in Bof_OpenSharedMemory: After a call to mmap(2) the file descriptor may be closed without affecting the memory mapping. - } - } - // BOF_ASSERT(Rts_E == BOF_ERR_NO_ERROR); - - if ((Rts_E == BOF_ERR_NO_ERROR) && (_RemoveIt_B)) - { - if (_rSharedMemory_X.HandleSystemV_i >= 0) - { - Rts_E = (shmctl(_rSharedMemory_X.HandleSystemV_i, IPC_RMID, nullptr) != -1) ? BOF_ERR_NO_ERROR : BOF_ERR_EMLINK; - printf("shmctl errno %d Rts_E %d %s\n", errno, Rts_E, _rSharedMemory_X.PathNameSystemV_S.c_str()); - Bof_DeleteFile(_rSharedMemory_X.PathNameSystemV_S); - if (Rts_E == BOF_ERR_EMLINK) - { - // NO !! Sts_i = close(_rSharedMemory_X.HandleSystemV_i); - // Can fail if already _RemoveIt_B by someone else Rts_E = (Sts_i == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_CLOSE; - Rts_E = BOF_ERR_NO_ERROR; - } - } - else - { - Rts_E = (shm_unlink(_rSharedMemory_X.Name_S.c_str()) == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_EMLINK; - printf("Bof_CloseSharedMemory--> '%s' RemoveIt %d Rts %d err %d %x:%p\n", _rSharedMemory_X.Name_S.c_str(), _RemoveIt_B, Rts_E, errno, _rSharedMemory_X.SizeInByte_U32, _rSharedMemory_X.pBaseAddress); - // Can fail if already _RemoveIt_B by someone else - Rts_E = BOF_ERR_NO_ERROR; - // close handle already made in Bof_OpenSharedMemory: After a call to mmap(2) the file descriptor may be closed without affecting the memory mapping. - } - } - } -#endif + } + return Rts_E; +} - if (Rts_E == BOF_ERR_NO_ERROR) +BOFERR Bof_WaitForEventMaskOr(BOF_EVENT &_rEvent_X, uint32_t _TimeoutInMs_U32, uint64_t _EventMask_U64, uint64_t &_rEventGot_U64) +{ + BOFERR Rts_E = BOF_ERR_INIT; + _rEventGot_U64 = 0; + if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) + { + std::unique_lock WaitLock_O(_rEvent_X.Mtx); + if (_rEvent_X.Cv.wait_for(WaitLock_O, std::chrono::milliseconds(_TimeoutInMs_U32), [&]() { _rEventGot_U64 = (_rEvent_X.SignaledBitmask_U64 & _EventMask_U64); + bool Rts_B = (_rEventGot_U64 != 0); if ((Rts_B) && (!_rEvent_X.WaitKeepSignaled_B)) _rEvent_X.SignaledBitmask_U64 &= ~_rEventGot_U64; return Rts_B; })) { - _rSharedMemory_X.Reset(); + Rts_E = BOF_ERR_NO_ERROR; + } + else + { + Rts_E = BOF_ERR_ETIMEDOUT; } - - // Rts_E = BOF_ERR_NO_ERROR; } - printf("Bof_CloseSharedMemory '%s' RemoveIt %d Rts %d\n", _rSharedMemory_X.Name_S.c_str(), _RemoveIt_B, Rts_E); - return Rts_E; } -// TODO: remove this after validation of Bof_OpenSharedMemory -#if 0 - -/*! - * Description - * This function creates a file mapping - * - * Parameters - * _AccessType_U32 - The requested access type - * _pName_c - The name of the shared memory - * _Size_U32 - The size in bytes of the shared memory - * _pAlreadyExist_B - The optional pointer to where to store the flag indicating if the shared memory already exists - * - * Returns - * The handle to the shared memory - * - * Remarks - * None - */ -HANDLE Bof_CreateFileMapping(U32 _AccessType_U32, const char *_pName_c, U32 _Size_U32, bool *_pAlreadyExist_B) +BOFERR Bof_DestroyEvent(BOF_EVENT &_rEvent_X) { - HANDLE Ret_h = nullptr; - BOF_SHARED_MEM_HANDLE *pHandle_X = new BOF_SHARED_MEM_HANDLE(); - bool Ok_B = false; - U32 Protect_U32 = 0; - - if (pHandle_X != nullptr) + BOFERR Rts_E = BOF_ERR_INIT; + if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) { -#if defined(__linux__) || defined(__APPLE__) - - key_t SemKey; - // int Flag_i; - //char pFile_c[512]; - //char *pId_c; - int Id_i, Flag_i; - - + _rEvent_X.Reset(); + Rts_E = BOF_ERR_NO_ERROR; + } + return Rts_E; +} - - if (_pName_c != nullptr) - { -#if defined(__ANDROID__) -#else -#if 0 - // Convert name to key - strncpy(pFile_c, _pName_c, sizeof(pFile_c)); - - // Convert the name to "File path" - "Projet Id" couple - pId_c = strrchr(pFile_c, '/'); - - if (pId_c != nullptr) - { - *pId_c = '\0'; - pId_c += 1; - - Id_i = atoi(pId_c); - - // Build the unique key - SemKey = ftok(pFile_c, (char)Id_i); - } -#endif - // IdKey = ftok("/dev/null", _pName_c[0]); //ftok need an exiting filename /dev/null is supposed to be present on alll unix station... - SemKey = Bof_GenerateSystemVKey(true, _pName_c, 0); - if (SemKey != -1) - { - // Get the semaphore if it already exists - pHandle_X->SharedMemId_i = shmget(SemKey, (size_t)_Size_U32, 0); - - // The semaphore does not exist : create it - if (pHandle_X->SharedMemId_i == -1) - { - if (_pAlreadyExist_B != nullptr) - { - *_pAlreadyExist_B = false; - } - - // Creation flag - Flag_i = IPC_CREAT; - - // Set the permissions flags - if ((_AccessType_U32 & BOF_THREAD_ACCESS_READ) == BOF_THREAD_ACCESS_READ) - { - Flag_i |= (S_IRUSR | S_IRGRP); - } - - if ((_AccessType_U32 & BOF_THREAD_ACCESS_WRITE) == BOF_THREAD_ACCESS_WRITE) - { - Flag_i |= (S_IWUSR | S_IWGRP); - } - - if ((_AccessType_U32 & BOF_THREAD_ACCESS_EXECUTE) == BOF_THREAD_ACCESS_EXECUTE) - { - Flag_i |= (S_IXUSR | S_IXGRP); - } - - // Create the shared memory - pHandle_X->SharedMemId_i = (int)shmget(SemKey, (size_t)_Size_U32, Flag_i); - - if (pHandle_X->SharedMemId_i >= 0) - { - Ok_B = true; - } - } - else - { - if (_pAlreadyExist_B != nullptr) - { - *_pAlreadyExist_B = true; - } - - Ok_B = true; - } - } -#endif - } -#else - TCHAR pName_W[256] = {0}; - TCHAR *pName_c = pName_W; - -#if UNICODE - if (_pName_c != nullptr) - { - // On convertit le nom du programme et les arguments en Unicode - MultiByteToWideChar(CP_ACP, 0, _pName_c, (int)strlen(_pName_c) + 1, pName_W, sizeof(pName_W) / sizeof(pName_W[0])); - } - else - { - pName_c = nullptr; - } - -#else - pName_c = (TCHAR *)_pName_c; -#endif - - // Set the protection bits - if ((_AccessType_U32 & BOF_THREAD_ACCESS_NONE) == BOF_THREAD_ACCESS_NONE) - { - Protect_U32 = PAGE_NOACCESS; - } - else - { - if ((_AccessType_U32 & BOF_THREAD_ACCESS_EXECUTE_READWRITE) == BOF_THREAD_ACCESS_EXECUTE_READWRITE) - { - Protect_U32 |= PAGE_EXECUTE_READWRITE; - } - else if ((_AccessType_U32 & BOF_THREAD_ACCESS_EXECUTE_READ) == BOF_THREAD_ACCESS_EXECUTE_READ) - { - Protect_U32 |= PAGE_EXECUTE_READ; - } - else if ((_AccessType_U32 & BOF_THREAD_ACCESS_EXECUTE_WRITE) == BOF_THREAD_ACCESS_EXECUTE_WRITE) - { - Protect_U32 |= PAGE_EXECUTE_WRITECOPY; - } - else if ((_AccessType_U32 & BOF_THREAD_ACCESS_READWRITE) == BOF_THREAD_ACCESS_READWRITE) - { - Protect_U32 |= PAGE_READWRITE; - } - else if ((_AccessType_U32 & BOF_THREAD_ACCESS_READ) == BOF_THREAD_ACCESS_READ) - { - Protect_U32 |= PAGE_READONLY; - } - else if ((_AccessType_U32 & BOF_THREAD_ACCESS_WRITE) == BOF_THREAD_ACCESS_WRITE) - { - Protect_U32 |= PAGE_WRITECOPY; - } - } - - // Create the file mapping - pHandle_X->SharedMem_h = CreateFileMapping(nullptr, nullptr, Protect_U32, 0, _Size_U32, pName_c); - - if (pHandle_X->SharedMem_h != nullptr) - { - Ok_B = true; - - if (_pAlreadyExist_B != nullptr) - { - *_pAlreadyExist_B = (GetLastError() == ERROR_ALREADY_EXISTS); - } - } -#endif - - if (Ok_B) - { - pHandle_X->Magic_U32 = BOFSHAREDMEM_MAGIC; - - Ret_h = (HANDLE)pHandle_X; - } - else - { - SAFE_DELETE(pHandle_X); - } - } - - return Ret_h; -} - - - - - -/*! - * Description - * This function unmaps an opened file mapping - * from the current process space - * - * Parameters - * _pMap - The pointer to the mapped zone - * - * Returns - * BOF_THREAD_ERR_OK - The operation was successful - * BOF_THREAD_ERR_INVALID_PARAM - At least one parameter is not valid - * BOF_THREAD_ERR_INTERNAL_ERROR - An internal error occurred - * BOF_THREAD_ERR_WAIT_TIMEOUT - A timeout occurred - * BOF_THREAD_ERR_ALREADY_EXIST - The object already exist - * - * Remarks - * None - */ -uint32_t Bof_UnmapViewOfFile(void *_pMap) -{ - uint32_t Ret_U32 = (uint32_t)BOF_THREAD_ERR_OK; - - if (_pMap != nullptr) - { -#if defined(__linux__) || defined(__APPLE__) -#if defined(__ANDROID__) -#else - if (shmdt(_pMap) == -1) - { - Ret_U32 = (uint32_t)BOF_THREAD_ERR_INTERNAL_ERROR; - } -#endif -#else - if (!UnmapViewOfFile(_pMap)) - { - Ret_U32 = (uint32_t)BOF_THREAD_ERR_INTERNAL_ERROR; - } -#endif - } - else - { - Ret_U32 = (uint32_t)BOF_THREAD_ERR_INVALID_PARAM; - } - - return Ret_U32; -} - -/*! - * Description - * This function closes an opened file mapping - * - * Parameters - * _FileMap_h - The handle to the file mapping - * - * Returns - * BOF_THREAD_ERR_OK - The operation was successful - * BOF_THREAD_ERR_INVALID_PARAM - At least one parameter is not valid - * BOF_THREAD_ERR_INTERNAL_ERROR - An internal error occurred - * BOF_THREAD_ERR_WAIT_TIMEOUT - A timeout occurred - * BOF_THREAD_ERR_ALREADY_EXIST - The object already exist - * - * Remarks - * None - */ -uint32_t Bof_RemoveFileMapping(HANDLE _FileMap_h) -{ - uint32_t Ret_U32 = (uint32_t)BOF_THREAD_ERR_OK; - BOF_SHARED_MEM_HANDLE *pHandle_X = (BOF_SHARED_MEM_HANDLE *)_FileMap_h; - - if ((pHandle_X != nullptr) && (pHandle_X->Magic_U32 == BOFSHAREDMEM_MAGIC)) - { -#if defined(__linux__) || defined(__APPLE__) -#if defined(__ANDROID__) -#else - if (shmctl(pHandle_X->SharedMemId_i, IPC_RMID, nullptr) != 0) - { - Ret_U32 = (uint32_t)BOF_THREAD_ERR_INTERNAL_ERROR; - } -#endif -#else - if (!CloseHandle(pHandle_X->SharedMem_h)) - { - Ret_U32 = (uint32_t)BOF_THREAD_ERR_INTERNAL_ERROR; - } -#endif - - pHandle_X->Magic_U32 = 0; - - SAFE_DELETE(pHandle_X); - } - else - { - Ret_U32 = (uint32_t)BOF_THREAD_ERR_INVALID_PARAM; - } - - return Ret_U32; -} -#endif - -BOFERR Bof_CreateMutex(const std::string &_rName_S, bool _Recursive_B, bool _PriorityInversionAware_B, BOF_MUTEX &_rMtx_X) -{ - BOFERR Rts_E = BOF_ERR_EEXIST; - - if (_rMtx_X.Magic_U32 != BOF_MUTEX_MAGIC) - { - _rMtx_X.Reset(); - _rMtx_X.Magic_U32 = BOF_MUTEX_MAGIC; - _rMtx_X.Name_S = _rName_S; - _rMtx_X.Recursive_B = _Recursive_B; -#if defined(_WIN32) -#else - if (_PriorityInversionAware_B) - { - // https://sakhnik.com/2017/07/16/custom-mutex.html - - pthread_mutexattr_t Attributes_X; - // Destroy the underlying mutex - ::pthread_mutex_destroy(_rMtx_X.Mtx.native_handle()); - ::pthread_mutex_destroy(_rMtx_X.RecursiveMtx.native_handle()); - - // Create mutex attribute with desired protocol - pthread_mutexattr_init(&Attributes_X); - pthread_mutexattr_setprotocol(&Attributes_X, PTHREAD_PRIO_INHERIT); - ::pthread_mutex_init(_rMtx_X.Mtx.native_handle(), &Attributes_X); - ::pthread_mutexattr_destroy(&Attributes_X); - - pthread_mutexattr_init(&Attributes_X); - pthread_mutexattr_settype(&Attributes_X, PTHREAD_MUTEX_RECURSIVE); - pthread_mutexattr_setprotocol(&Attributes_X, PTHREAD_PRIO_INHERIT); - ::pthread_mutex_init(_rMtx_X.RecursiveMtx.native_handle(), &Attributes_X); - ::pthread_mutexattr_destroy(&Attributes_X); - } - // BOFERR e=Bof_LockMutex(_rMtx_X); - // e=Bof_LockMutex(_rMtx_X); -#endif - Rts_E = BOF_ERR_NO_ERROR; - } - return Rts_E; -} - -bool Bof_IsMutexValid(BOF_MUTEX &_rMtx_X) -{ - return (_rMtx_X.Magic_U32 == BOF_MUTEX_MAGIC); -} - -BOFERR Bof_LockMutex(BOF_MUTEX &_rMtx_X) -{ - BOFERR Rts_E = BOF_ERR_INIT; - - if (_rMtx_X.Magic_U32 == BOF_MUTEX_MAGIC) - { - Rts_E = BOF_ERR_NO_ERROR; - try - { - _rMtx_X.Recursive_B ? _rMtx_X.RecursiveMtx.lock() : _rMtx_X.Mtx.lock(); - } - catch (const std::exception &e) - { - // printf("mutex exception %s\n", e.what()); - Rts_E = BOF_ERR_OPERATION_FAILED; - } - } - return Rts_E; -} - -BOFERR Bof_UnlockMutex(BOF_MUTEX &_rMtx_X) -{ - BOFERR Rts_E = BOF_ERR_INIT; - - if (_rMtx_X.Magic_U32 == BOF_MUTEX_MAGIC) - { - Rts_E = BOF_ERR_NO_ERROR; - try - { - _rMtx_X.Recursive_B ? _rMtx_X.RecursiveMtx.unlock() : _rMtx_X.Mtx.unlock(); - } - catch (const std::exception &e) - { - // printf("mutex exception %s\n", e.what()); - Rts_E = BOF_ERR_OPERATION_FAILED; - } - } - return Rts_E; -} - -BOFERR Bof_DestroyMutex(BOF_MUTEX &_rMtx_X) -{ - BOFERR Rts_E = BOF_ERR_INIT; - - if (_rMtx_X.Magic_U32 == BOF_MUTEX_MAGIC) - { - _rMtx_X.Reset(); - Rts_E = BOF_ERR_NO_ERROR; - } - return Rts_E; -} - -BOFERR Bof_CreateSemaphore(const std::string &_rName_S, int32_t _InitialCount_S32, BOF_SEMAPHORE &_rSem_X) -{ - BOFERR Rts_E = BOF_ERR_EEXIST; +BOFERR Bof_CreateSemaphore(const std::string &_rName_S, int32_t _InitialCount_S32, BOF_SEMAPHORE &_rSem_X) +{ + BOFERR Rts_E = BOF_ERR_EEXIST; if (_rSem_X.Magic_U32 != BOF_SEMAPHORE_MAGIC) { @@ -955,6 +493,7 @@ bool Bof_IsSemaphoreValid(BOF_SEMAPHORE &_rSem_X) { return (_rSem_X.Magic_U32 == BOF_SEMAPHORE_MAGIC); } + BOFERR Bof_SignalSemaphore(BOF_SEMAPHORE &_rSem_X) { BOFERR Rts_E = BOF_ERR_INIT; @@ -1004,327 +543,926 @@ BOFERR Bof_DestroySemaphore(BOF_SEMAPHORE &_rSem_X) return Rts_E; } -BOFERR Bof_CreateConditionalVariable(const std::string &_rName_S, bool _NotifyAll_B, BOF_CONDITIONAL_VARIABLE &_rCv_X) +// man ftok: _Id_U8 the least significant 8 bits of proj_id (which must be nonzero) +uint64_t Bof_GenerateSystemVKey(bool _CreateFn_B, const char *_pFn_c, uint8_t _Id_U8) { - BOFERR Rts_E = BOF_ERR_EEXIST; + uint64_t Rts_U64 = -1; // IPC_PRIVATE is 0 + char pFn_c[512]; //, *pId_c; + uintptr_t Io; + bool ItIsADirectory_B; - if (_rCv_X.Magic_U32 != BOF_CONDITIONAL_VARIABLE_MAGIC) + if (_Id_U8) { - _rCv_X.Reset(); - _rCv_X.Name_S = _rName_S; - _rCv_X.Magic_U32 = BOF_CONDITIONAL_VARIABLE_MAGIC; - _rCv_X.NotifyAll_B = _NotifyAll_B; - Rts_E = BOF_ERR_NO_ERROR; - } - return Rts_E; -} - -BOFERR Bof_DestroyConditionalVariable(BOF_CONDITIONAL_VARIABLE &_rCv_X) -{ - BOFERR Rts_E = BOF_ERR_INIT; - if (_rCv_X.Magic_U32 == BOF_CONDITIONAL_VARIABLE_MAGIC) - { - _rCv_X.Reset(); - Rts_E = BOF_ERR_NO_ERROR; - } - return Rts_E; -} - -BOFERR Bof_CreateEvent(const std::string &_rName_S, bool _InitialState_B, uint32_t _MaxNumberToNotify_U32, bool _WaitKeepSignaled_B, bool _NotifyAll_B, BOF_EVENT &_rEvent_X) -{ - BOFERR Rts_E = BOF_ERR_EEXIST; - - if (_rEvent_X.Magic_U32 != BOF_EVENT_MAGIC) - { - Rts_E = BOF_ERR_EINVAL; - if ((_MaxNumberToNotify_U32) && (_MaxNumberToNotify_U32 <= 64)) + if ((_pFn_c == nullptr) || (_pFn_c[0] == 0)) { - _rEvent_X.Reset(); - _rEvent_X.Name_S = _rName_S; - _rEvent_X.SignaledBitmask_U64 = _InitialState_B ? (1 << (_MaxNumberToNotify_U32 - 1)) - 1 : 0; - _rEvent_X.MaxNumberToNotify_U32 = _MaxNumberToNotify_U32; - _rEvent_X.WaitKeepSignaled_B = _WaitKeepSignaled_B; - _rEvent_X.NotifyAll_B = _NotifyAll_B; - _rEvent_X.Magic_U32 = BOF_EVENT_MAGIC; - Rts_E = BOF_ERR_NO_ERROR; + strcpy(pFn_c, "/dev/null"); // /dev/null is supposed to be present on alll unix station.. + _CreateFn_B = false; + } + else + { + strcpy(pFn_c, _pFn_c); } - } - - return Rts_E; -} - -bool Bof_IsEventValid(BOF_EVENT &_rEvent_X) -{ - return (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC); -} - -BOFERR Bof_SignalEvent(BOF_EVENT &_rEvent_X, uint32_t _Instance_U32) -{ - BOFERR Rts_E = BOF_ERR_INIT; - if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) - { - Rts_E = BOF_ERR_EINVAL; - if (_Instance_U32 < _rEvent_X.MaxNumberToNotify_U32) +#if 0 + if (_Id_U8 == 0) { - std::unique_lock WaitLock_O(_rEvent_X.Mtx); - _rEvent_X.SignaledBitmask_U64 |= (static_cast(1) << _Instance_U32); - if (_rEvent_X.NotifyAll_B) - { - _rEvent_X.Cv.notify_all(); - } - else + // Check if id is set in filename. for example you can specify a path to your app exe such as /usr/mc/ucode followed by a numeric id->/usr/mc/ucode/23 + pId_c = strrchr(pFn_c, '/'); + if (pId_c != nullptr) { - _rEvent_X.Cv.notify_one(); + _Id_U8 = atoi(pId_c + 1); + if (_Id_U8 == 0) + { + _Id_U8 = *(pId_c + 1); // pFn_c[0]; + } + else + { + *pId_c = (char)0; // keep path to existing file and remove id component + // _CreateFn_B = false; //In that case the file must exist and could be on a read only disk + } } - Rts_E = BOF_ERR_NO_ERROR; } - } - - return Rts_E; -} -/* -BOFERR Bof_ResetEvent(BOF_EVENT &_rEvent_X, uint32_t _Instance_U32) -{ - BOFERR Rts_E = BOF_ERR_INIT; - - if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) - { - Rts_E = BOF_ERR_EINVAL; - if (_Instance_U32 < _rEvent_X.MaxNumberToNotify_U32) +#endif + if (_CreateFn_B) { - std::unique_lock WaitLock_O(_rEvent_X.Mtx); - _rEvent_X.SignaledBitmask_U64 &= ~(1 << _Instance_U32); - Rts_E = BOF_ERR_NO_ERROR; + // Bof_CreateFile(BOF::BOF_FILE_PERMISSION_READ_FOR_ALL | BOF::BOF_FILE_PERMISSION_WRITE_FOR_ALL, pFn_c, false, Io); // If it fails, it will also fails on the following line + Bof_CreateFile(BOF_FILE_PERMISSION_DEFAULT_R, pFn_c, false, Io); // If it fails, it will also fails on the following line + } + if (Bof_IsPathExist(pFn_c, ItIsADirectory_B)) + { +#if defined(_WIN32) + Rts_U64 = 0; +#else + Rts_U64 = (uint64_t)ftok(pFn_c, _Id_U8); // ftok need an exiting filename . +#endif } } - - return Rts_E; + return Rts_U64; } -BOFERR Bof_ResetEvent(BOF_EVENT &_rEvent_X) -{ - BOFERR Rts_E = BOF_ERR_INIT; - - if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) - { - std::unique_lock WaitLock_O(_rEvent_X.Mtx); - _rEvent_X.SignaledBitmask_U64 = 0; - Rts_E = BOF_ERR_NO_ERROR; - } - return Rts_E; -} -*/ -bool Bof_IsEventSignaled(BOF_EVENT &_rEvent_X, uint32_t _Instance_U32) +BOFERR Bof_OpenSharedMemory(const std::string &_rName_S, uint32_t _SizeInByte_U32, BOF_ACCESS_TYPE _AccessType_E, const std::string &_rFallbackSystemVKeySubDir_S, BOF_HANDLE _DriverHandle, BOF_SHARED_MEMORY &_rSharedMemory_X) { - bool Rts_B = false; + BOFERR Rts_E = BOF_ERR_ALREADY_OPENED; - if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) + if (_rSharedMemory_X.Magic_U32 != BOF_FILEMAPPING_MAGIC) { - if (_Instance_U32 < _rEvent_X.MaxNumberToNotify_U32) + _rSharedMemory_X.Reset(); + _rSharedMemory_X.Name_S = _rName_S; + _rSharedMemory_X.SizeInByte_U32 = _SizeInByte_U32; +#if defined(_WIN32) + // char pName_c[512]; + PSECURITY_DESCRIPTOR pSecurityDescriptor_X; + SECURITY_ATTRIBUTES SecurityAttribute_X; + uint32_t Flag_U32; + Rts_E = BOF_ERR_EACCES; + // Name must start with Global\\->Responsabilities of the caller ! + if ((strncmp(_rSharedMemory_X.Name_S.c_str(), "Global\\", 7)) && (strncmp(_rSharedMemory_X.Name_S.c_str(), "Local\\", 6))) { - std::unique_lock WaitLock_O(_rEvent_X.Mtx); - Rts_B = (_rEvent_X.SignaledBitmask_U64 & (static_cast(1) << _Instance_U32)) ? true : false; } - } - - return Rts_B; -} + // bool k=CreateMyDACL(&SecurityAttribute_X); + pSecurityDescriptor_X = CreateWinSecurityDescriptor(&SecurityAttribute_X); -BOFERR Bof_SetEventMask(BOF_EVENT &_rEvent_X, uint64_t _EventVal_U64) -{ - BOFERR Rts_E = BOF_ERR_INIT; + if ((pSecurityDescriptor_X) + // && (Bof_MultiByteToWideChar(_rSharedMemory_X.Name_S.c_str(), sizeof(pName_wc) / sizeof(WCHAR), pName_wc)>=0) + ) + { + Rts_E = BOF_ERR_EINVAL; + // Name must start with Global\\->Responsabilities of the caller ! sinon Rts_h = BOF_INVALID_HANDLE_VALUE; + // _rSharedMemory_X.pHandle = CreateFileMapping(BOF_INVALID_HANDLE_VALUE, &SecurityAttribute_X, PAGE_READWRITE | SEC_COMMIT, 0, _SizeInByte_U32, pName_c); - if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) - { - std::unique_lock WaitLock_O(_rEvent_X.Mtx); - _rEvent_X.SignaledBitmask_U64 = _EventVal_U64; - Rts_E = BOF_ERR_NO_ERROR; - } - return Rts_E; -} -BOFERR Bof_GetEventMask(BOF_EVENT &_rEvent_X, uint64_t &_rEventVal_U64) -{ - BOFERR Rts_E = BOF_ERR_INIT; + Flag_U32 = 0; - if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) - { - std::unique_lock WaitLock_O(_rEvent_X.Mtx); - _rEventVal_U64 = _rEvent_X.SignaledBitmask_U64; - Rts_E = BOF_ERR_NO_ERROR; - } - else - { - _rEventVal_U64 = 0; - } - return Rts_E; -} -BOFERR Bof_WaitForEvent(BOF_EVENT &_rEvent_X, uint32_t _TimeoutInMs_U32, uint32_t _Instance_U32) -{ - BOFERR Rts_E = BOF_ERR_INIT; - if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) - { - Rts_E = BOF_ERR_EINVAL; - if (_Instance_U32 < _rEvent_X.MaxNumberToNotify_U32) - { - std::unique_lock WaitLock_O(_rEvent_X.Mtx); - if (_rEvent_X.Cv.wait_for(WaitLock_O, std::chrono::milliseconds(_TimeoutInMs_U32), [&]() { bool Rts_B = (_rEvent_X.SignaledBitmask_U64 & (static_cast(1) << _Instance_U32)); if ((Rts_B) && (!_rEvent_X.WaitKeepSignaled_B)) _rEvent_X.SignaledBitmask_U64 &= ~(1 << _Instance_U32); return Rts_B; })) + if (Bof_IsAllBitFlagSet(_AccessType_E, BOF_ACCESS_TYPE::BOF_ACCESS_READ | BOF_ACCESS_TYPE::BOF_ACCESS_WRITE)) { - Rts_E = BOF_ERR_NO_ERROR; + Flag_U32 |= PAGE_READWRITE | SEC_COMMIT; } - else + else if (Bof_IsAnyBitFlagSet(_AccessType_E, BOF_ACCESS_TYPE::BOF_ACCESS_READ)) { - Rts_E = BOF_ERR_ETIMEDOUT; + Flag_U32 |= PAGE_READONLY; + } + else if (Bof_IsAnyBitFlagSet(_AccessType_E, BOF::BOF_ACCESS_TYPE::BOF_ACCESS_WRITE)) + { + Flag_U32 |= PAGE_READWRITE | SEC_COMMIT; + } + _rSharedMemory_X.pHandle = CreateFileMappingA(INVALID_HANDLE_VALUE, &SecurityAttribute_X, Flag_U32, 0, _SizeInByte_U32, _rSharedMemory_X.Name_S.c_str()); + if (_rSharedMemory_X.pHandle) + { + Rts_E = Bof_GetLastError(false); + if ((Rts_E == BOF_ERR_EEXIST) || (Rts_E == BOF_ERR_NO_ERROR)) + { + _rSharedMemory_X.pBaseAddress = MapViewOfFile(_rSharedMemory_X.pHandle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + if (_rSharedMemory_X.pBaseAddress == nullptr) + { + Rts_E = BOF_ERR_MAP; + } + else + { + _rSharedMemory_X.DriverHandle = _DriverHandle; + _rSharedMemory_X.Magic_U32 = BOF_FILEMAPPING_MAGIC; + } + } } } - } - return Rts_E; -} -BOFERR Bof_WaitForEventMaskAnd(BOF_EVENT &_rEvent_X, uint32_t _TimeoutInMs_U32, uint64_t _EventMask_U64) -{ - BOFERR Rts_E = BOF_ERR_INIT; - if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) - { - std::unique_lock WaitLock_O(_rEvent_X.Mtx); - if (_rEvent_X.Cv.wait_for(WaitLock_O, std::chrono::milliseconds(_TimeoutInMs_U32), [&]() {bool Rts_B=((_rEvent_X.SignaledBitmask_U64 & _EventMask_U64) == _EventMask_U64); if ((Rts_B) && (!_rEvent_X.WaitKeepSignaled_B)) _rEvent_X.SignaledBitmask_U64 &= ~_EventMask_U64; return Rts_B; })) +#else + // std::string Name_S; + int Handle_i, Access_i; + std::string Name_S; + mode_t Mode; + key_t ShmKey; + + Rts_E = BOF_ERR_EINVAL; + _rSharedMemory_X.HandleSystemV_i = -1; + if (isalpha(_rSharedMemory_X.Name_S[0])) { - Rts_E = BOF_ERR_NO_ERROR; + // Posix shm name must begin with a / + Name_S = "/" + _rSharedMemory_X.Name_S; } else { - Rts_E = BOF_ERR_ETIMEDOUT; - } - } - return Rts_E; -} -BOFERR Bof_WaitForEventMaskOr(BOF_EVENT &_rEvent_X, uint32_t _TimeoutInMs_U32, uint64_t _EventMask_U64, uint64_t &_rEventGot_U64) -{ - BOFERR Rts_E = BOF_ERR_INIT; - _rEventGot_U64 = 0; - if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) - { - std::unique_lock WaitLock_O(_rEvent_X.Mtx); - if (_rEvent_X.Cv.wait_for(WaitLock_O, std::chrono::milliseconds(_TimeoutInMs_U32), [&]() { _rEventGot_U64 = (_rEvent_X.SignaledBitmask_U64 & _EventMask_U64); - bool Rts_B = (_rEventGot_U64 != 0); if ((Rts_B) && (!_rEvent_X.WaitKeepSignaled_B)) _rEvent_X.SignaledBitmask_U64 &= ~_rEventGot_U64; return Rts_B; })) - { - Rts_E = BOF_ERR_NO_ERROR; + Name_S = _rSharedMemory_X.Name_S; } - else + if (Name_S[0] == '/') { - Rts_E = BOF_ERR_ETIMEDOUT; - } - } - return Rts_E; + Rts_E = BOF_ERR_FORMAT; + if (strchr(Name_S.c_str() + 1, '/') == nullptr) + { + Rts_E = BOF_ERR_NOT_OPENED; +#if defined(__ANDROID__) + Handle_i = -1; + Rts_E = BOF_ERR_EEXIST; +#else + Access_i = O_CREAT | O_EXCL; + Mode = 0; + if (Bof_IsAllBitFlagSet(_AccessType_E, BOF_ACCESS_TYPE::BOF_ACCESS_READ | BOF_ACCESS_TYPE::BOF_ACCESS_WRITE)) + { + Access_i |= O_RDWR; + Mode |= S_IRUSR | S_IWUSR; + } + else if (Bof_IsAnyBitFlagSet(_AccessType_E, BOF_ACCESS_TYPE::BOF_ACCESS_READ)) + { + Access_i |= O_RDONLY; + Mode |= S_IRUSR; + } + else if (Bof_IsAnyBitFlagSet(_AccessType_E, BOF::BOF_ACCESS_TYPE::BOF_ACCESS_WRITE)) + { + Access_i |= O_RDWR; + Mode |= S_IRUSR | S_IWUSR; + } + if (BOF_IS_HANDLE_VALID(_DriverHandle)) + { + _rSharedMemory_X.pBaseAddress = mmap(nullptr, _SizeInByte_U32, PROT_READ | PROT_WRITE, MAP_SHARED, _DriverHandle, 0); + if (_rSharedMemory_X.pBaseAddress != MAP_FAILED) + { + printf("Bof_OpenSharedMemory '%s' 0: pMap %x:%p\n", Name_S.c_str(), _SizeInByte_U32, _rSharedMemory_X.pBaseAddress); + Rts_E = BOF_ERR_NO_ERROR; + } + } + else + { + Handle_i = shm_open(Name_S.c_str(), Access_i, Mode); + printf("Bof_OpenSharedMemory '%s' 1: Acc %x Mode %d Size %X -> Hndl %d errno %d\n", Name_S.c_str(), Access_i, Mode, _SizeInByte_U32, Handle_i, errno); + if (Handle_i >= 0) + { + Rts_E = (ftruncate(Handle_i, _rSharedMemory_X.SizeInByte_U32) == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_WRONG_SIZE; + } + else + { + // Handle_i = shm_open(Name_S.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + Access_i ^= O_EXCL; + Handle_i = shm_open(Name_S.c_str(), Access_i, Mode); + printf("Bof_OpenSharedMemory '%s' 2: Acc %x Mode %d Size %X -> Hndl %d errno %d\n", Name_S.c_str(), Access_i, Mode, _SizeInByte_U32, Handle_i, errno); + if (Handle_i >= 0) + { + Rts_E = BOF_ERR_EEXIST; + } + } + if (Handle_i >= 0) + { + _rSharedMemory_X.pBaseAddress = mmap(nullptr, _SizeInByte_U32, PROT_READ | PROT_WRITE, MAP_SHARED, Handle_i, 0); + if (_rSharedMemory_X.pBaseAddress != MAP_FAILED) + { + printf("Bof_OpenSharedMemory '%s' 3: pMap %x:%p\n", Name_S.c_str(), _SizeInByte_U32, _rSharedMemory_X.pBaseAddress); + if (Rts_E != BOF_ERR_EEXIST) + { + Rts_E = BOF_ERR_NO_ERROR; + } + } + close(Handle_i); // After a call to mmap(2) the file descriptor may be closed without affecting the memory mapping. + } + else + { + // Posix interface failed (tge2 docket), fallback on System V api + _rSharedMemory_X.PathNameSystemV_S = _rFallbackSystemVKeySubDir_S + Name_S; + ShmKey = Bof_GenerateSystemVKey(true, _rSharedMemory_X.PathNameSystemV_S.c_str(), 1); + // ShmKey = Bof_GenerateSystemVKey(true, nullptr, 1); + printf("Bof_OpenSharedMemory '%s' 4: key %x\n", _rSharedMemory_X.PathNameSystemV_S.c_str(), ShmKey); + if (ShmKey != -1) + { + // Handle_i = shmget(IPC_PRIVATE, _SizeInByte_U32, IPC_EXCL | IPC_CREAT | 0666); + // printf("%x %d\n", 0666, 0666); // 1b6 438 + Handle_i = shmget(ShmKey, _SizeInByte_U32, Mode); // IPC_EXCL | IPC_CREAT | 0666); + printf("Bof_OpenSharedMemory '%s' 5: Mode %d Key %x Size %X -> Hndl %d errno %d\n", _rSharedMemory_X.PathNameSystemV_S.c_str(), Mode, ShmKey, _SizeInByte_U32, Handle_i, errno); + if (Handle_i >= 0) + { + _rSharedMemory_X.pBaseAddress = shmat(Handle_i, 0, 0); + if ((uintptr_t)_rSharedMemory_X.pBaseAddress == -1) + { + Rts_E = BOF_ERR_MAP; + } + else + { + Rts_E = BOF_ERR_EEXIST; + } + } + else + { + Handle_i = shmget(ShmKey, _SizeInByte_U32, IPC_EXCL | IPC_CREAT | Mode); //| 0666); + printf("Bof_OpenSharedMemory '%s' 6: Mode %d Key %x Size %X -> Hndl %d errno %d\n", _rSharedMemory_X.PathNameSystemV_S.c_str(), Mode, ShmKey, _SizeInByte_U32, Handle_i, errno); + if (Handle_i >= 0) + { + _rSharedMemory_X.pBaseAddress = shmat(Handle_i, 0, 0); + if ((uintptr_t)_rSharedMemory_X.pBaseAddress == -1) + { + Rts_E = BOF_ERR_MAP; + } + else + { + printf("Bof_OpenSharedMemory '%s' 7: pMap %x:%p\n", Name_S.c_str(), _SizeInByte_U32, _rSharedMemory_X.pBaseAddress); + Rts_E = BOF_ERR_NO_ERROR; + } + } + } + } + } + } + if ((Rts_E == BOF_ERR_NO_ERROR) || (Rts_E == BOF_ERR_EEXIST)) + { + _rSharedMemory_X.HandleSystemV_i = Handle_i; + _rSharedMemory_X.DriverHandle = _DriverHandle; + _rSharedMemory_X.Magic_U32 = BOF_FILEMAPPING_MAGIC; + } + } + } +#endif + +#endif + } + + return Rts_E; +} + +bool Bof_IsSharedMemoryValid(BOF_SHARED_MEMORY &_rSharedMemory_X) +{ + return (_rSharedMemory_X.Magic_U32 == BOF_FILEMAPPING_MAGIC); +} + +BOFERR Bof_CloseSharedMemory(BOF_SHARED_MEMORY &_rSharedMemory_X, bool _RemoveIt_B) +{ + BOFERR Rts_E = BOF_ERR_NOT_OPENED; + + if (_rSharedMemory_X.Magic_U32 == BOF_FILEMAPPING_MAGIC) + { +#if defined(_WIN32) + if (_rSharedMemory_X.pBaseAddress) + { + Rts_E = UnmapViewOfFile(_rSharedMemory_X.pBaseAddress) ? BOF_ERR_NO_ERROR : BOF_ERR_UNMAP; + } + else + { + Rts_E = BOF_ERR_NO_ERROR; + } + if (Rts_E == BOF_ERR_NO_ERROR) + { + if (_rSharedMemory_X.pHandle) + { + Rts_E = CloseHandle(_rSharedMemory_X.pHandle) ? BOF_ERR_NO_ERROR : BOF_ERR_CLOSE; + } + } +#else + int Sts_i; + if (_rSharedMemory_X.pBaseAddress) + { + if (_rSharedMemory_X.HandleSystemV_i >= 0) + { + Rts_E = (shmdt(_rSharedMemory_X.pBaseAddress) != -1) ? BOF_ERR_NO_ERROR : BOF_ERR_UNMAP; + printf("shmdt errno %d Rts_E %d\n", errno, Rts_E); + if ((Rts_E == BOF_ERR_NO_ERROR) || (Rts_E == BOF_ERR_ENOTDIR)) + { + // NO !! Sts_i = close(_rSharedMemory_X.HandleSystemV_i); + // Can fail if already _RemoveIt_B by someone else Rts_E = (Sts_i == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_CLOSE; + Rts_E = BOF_ERR_NO_ERROR; + } + } + else + { + Rts_E = (munmap(_rSharedMemory_X.pBaseAddress, _rSharedMemory_X.SizeInByte_U32) == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_UNMAP; + if (Rts_E == BOF_ERR_NO_ERROR) + { + // close handle already made in Bof_OpenSharedMemory: After a call to mmap(2) the file descriptor may be closed without affecting the memory mapping. + } + } + // BOF_ASSERT(Rts_E == BOF_ERR_NO_ERROR); + + if ((Rts_E == BOF_ERR_NO_ERROR) && (_RemoveIt_B)) + { + if (_rSharedMemory_X.HandleSystemV_i >= 0) + { + Rts_E = (shmctl(_rSharedMemory_X.HandleSystemV_i, IPC_RMID, nullptr) != -1) ? BOF_ERR_NO_ERROR : BOF_ERR_EMLINK; + printf("shmctl errno %d Rts_E %d %s\n", errno, Rts_E, _rSharedMemory_X.PathNameSystemV_S.c_str()); + Bof_DeleteFile(_rSharedMemory_X.PathNameSystemV_S); + if (Rts_E == BOF_ERR_EMLINK) + { + // NO !! Sts_i = close(_rSharedMemory_X.HandleSystemV_i); + // Can fail if already _RemoveIt_B by someone else Rts_E = (Sts_i == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_CLOSE; + Rts_E = BOF_ERR_NO_ERROR; + } + } + else + { + Rts_E = (shm_unlink(_rSharedMemory_X.Name_S.c_str()) == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_EMLINK; + printf("Bof_CloseSharedMemory--> '%s' RemoveIt %d Rts %d err %d %x:%p\n", _rSharedMemory_X.Name_S.c_str(), _RemoveIt_B, Rts_E, errno, _rSharedMemory_X.SizeInByte_U32, _rSharedMemory_X.pBaseAddress); + // Can fail if already _RemoveIt_B by someone else + Rts_E = BOF_ERR_NO_ERROR; + // close handle already made in Bof_OpenSharedMemory: After a call to mmap(2) the file descriptor may be closed without affecting the memory mapping. + } + } + } +#endif + + if (Rts_E == BOF_ERR_NO_ERROR) + { + _rSharedMemory_X.Reset(); + } + + // Rts_E = BOF_ERR_NO_ERROR; + } + printf("Bof_CloseSharedMemory '%s' RemoveIt %d Rts %d\n", _rSharedMemory_X.Name_S.c_str(), _RemoveIt_B, Rts_E); + + return Rts_E; +} + +BOFERR Bof_CreateConditionalVariable(const std::string &_rName_S, bool _NotifyAll_B, BOF_CONDITIONAL_VARIABLE &_rCv_X) +{ + BOFERR Rts_E = BOF_ERR_EEXIST; + + if (_rCv_X.Magic_U32 != BOF_CONDITIONAL_VARIABLE_MAGIC) + { + _rCv_X.Reset(); + _rCv_X.Name_S = _rName_S; + _rCv_X.Magic_U32 = BOF_CONDITIONAL_VARIABLE_MAGIC; + _rCv_X.NotifyAll_B = _NotifyAll_B; + Rts_E = BOF_ERR_NO_ERROR; + } + return Rts_E; +} + +BOFERR Bof_DestroyConditionalVariable(BOF_CONDITIONAL_VARIABLE &_rCv_X) +{ + BOFERR Rts_E = BOF_ERR_INIT; + if (_rCv_X.Magic_U32 == BOF_CONDITIONAL_VARIABLE_MAGIC) + { + _rCv_X.Reset(); + Rts_E = BOF_ERR_NO_ERROR; + } + return Rts_E; +} + +BOFERR Bof_GetMemoryState(uint64_t &_rAvailableFreeMemory_U64, uint64_t &_rTotalMemorySize_U64) +{ + BOFERR Rts_E = BOF_ERR_INTERNAL; + +#if defined(_WIN32) + MEMORYSTATUSEX Ms_X; + Ms_X.dwLength = sizeof(Ms_X); + if (GlobalMemoryStatusEx(&Ms_X)) + { + _rAvailableFreeMemory_U64 = Ms_X.ullAvailPhys; + _rTotalMemorySize_U64 = Ms_X.ullTotalPhys; + + Rts_E = BOF_ERR_NO_ERROR; + } + else + { + _rAvailableFreeMemory_U64 = 0; + _rTotalMemorySize_U64 = 0; + } +#else + int PageSize_i = static_cast(sysconf(_SC_PAGE_SIZE)); + + _rAvailableFreeMemory_U64 = (get_avphys_pages() * PageSize_i); + _rTotalMemorySize_U64 = (get_phys_pages() * PageSize_i); + Rts_E = BOF_ERR_NO_ERROR; +#endif + return Rts_E; +} + +//_OsAdvice_i mainly for MADV_DONTFORK option in madvise +BOFERR Bof_LockMem(int _OsAdvice_i, uint64_t _SizeInByte_U64, void *_pData) +{ + BOFERR Rts_E; + +#if defined(_WIN32) + // Rts_E = VirtualLock(_pData, _SizeInByte_U64) ? BOF_ERR_NO_ERROR : BOF_ERR_LOCK; + Rts_E = BOF_ERR_LOCK; +#else + int Sts_i; + if (_OsAdvice_i) + { + Sts_i = madvise(_pData, _SizeInByte_U64, _OsAdvice_i); + Rts_E = (Sts_i == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_SET; + if (Rts_E == BOF_ERR_NO_ERROR) + { + Sts_i = mlock(_pData, _SizeInByte_U64); + Rts_E = (Sts_i == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_LOCK; + } + } + else + { + Rts_E = BOF_ERR_NO_ERROR; + } + if (Rts_E == BOF_ERR_NO_ERROR) + { + Sts_i = mlock(_pData, _SizeInByte_U64); + Rts_E = (Sts_i == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_LOCK; + } +#endif + return Rts_E; +} + +BOFERR Bof_UnlockMem(uint64_t _SizeInByte_U64, void *_pData) +{ + BOFERR Rts_E; + +#if defined(_WIN32) + // Rts_E = VirtualUnlock(_pData, _SizeInByte_U64) ? BOF_ERR_NO_ERROR : BOF_ERR_LOCK; + Rts_E = BOF_ERR_LOCK; +#else + Rts_E = (munlock(_pData, _SizeInByte_U64) == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_LOCK; +#endif + return Rts_E; +} + +bool Bof_AlignedMemCpy8(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32) +{ + bool Rts_B = true; + uint32_t i_U32; + volatile uint8_t *pDst_U8 = reinterpret_cast(_pDst); + const volatile uint8_t *pSrc_U8 = reinterpret_cast(_pSrc); + + for (i_U32 = 0; i_U32 < _SizeInByte_U32; i_U32++) + { + pDst_U8[i_U32] = pSrc_U8[i_U32]; + } + return Rts_B; +} + +bool Bof_AlignedMemCpy16(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32) +{ + bool Rts_B = false; + uint32_t i_U32, SizeInWord_U32; + volatile uint16_t *pDst_U16 = reinterpret_cast(_pDst); + const volatile uint16_t *pSrc_U16 = reinterpret_cast(_pSrc); + + if (((reinterpret_cast(_pDst) & 0x01) == 0) && ((reinterpret_cast(_pSrc) & 0x01) == 0)) + { + SizeInWord_U32 = _SizeInByte_U32 >> 1; + for (i_U32 = 0; i_U32 < SizeInWord_U32; i_U32++) + { + pDst_U16[i_U32] = pSrc_U16[i_U32]; + } + Rts_B = true; + } + return Rts_B; +} + +bool Bof_AlignedMemCpy32(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32) +{ + bool Rts_B = false; + uint32_t i_U32, SizeInDword_U32; + volatile uint32_t *pDst_U32 = reinterpret_cast(_pDst); + const volatile uint32_t *pSrc_U32 = reinterpret_cast(_pSrc); + + if (((reinterpret_cast(_pDst) & 0x03) == 0) && ((reinterpret_cast(_pSrc) & 0x03) == 0)) + { + // SizeInDword_U32 = (_SizeInByte_U32 & 0x00000003) ? ((_SizeInByte_U32 | 0x00000003) + 1) >> 2 : _SizeInByte_U32 >> 2; + SizeInDword_U32 = _SizeInByte_U32 >> 2; + for (i_U32 = 0; i_U32 < SizeInDword_U32; i_U32++) + { + pDst_U32[i_U32] = pSrc_U32[i_U32]; + } + Rts_B = true; + } + return Rts_B; +} + +// https://stackoverflow.com/questions/32652833/how-to-allocate-huge-pages-for-c-application-on-linux +// constexpr char MMGW_HUGE_PAGE_PATH[]="/sys/kernel/mm/hugepages/hugepages-2048kB/page_%08X"; //"/var/lib/hugetlbfs/global/pagesize-2MB/page_%08X"; +constexpr char BOF_HUGE_PAGE_PATH[] = "/tmp/hugepages/page_%08X"; +constexpr uint32_t BOF_HUGE_PAGE_SIZE = 2 * 1024 * 1024; +//_OsAdvice_i mainly for MADV_DONTFORK option in madvise +BOFERR Bof_AlignedMemAlloc(BOF_BUFFER_ALLOCATE_ZONE _AllocateZone_E, uint32_t _AligmentInByte_U32, uint32_t _SizeInByte_U32, bool _LockIt_B, int _OsAdvice_i, bool _ClearIt_B, BOF_BUFFER &_rAllocatedBuffer_X) //, uint32_t _Offset_U32) +{ + BOFERR Rts_E = BOF_ERR_EINVAL; + BOF_BUFFER_ALLOCATE_HEADER AllocateBuffer_X; + static std::atomic S_HugePageId(0); + + _rAllocatedBuffer_X.Reset(); + if (Bof_IsAPowerOf2(_AligmentInByte_U32)) + { + Rts_E = BOF_ERR_ENOMEM; + + _rAllocatedBuffer_X.Deleter_E = BOF_BUFFER_DELETER_ALIGNED_FREE; + _rAllocatedBuffer_X.Capacity_U64 = _SizeInByte_U32; + _rAllocatedBuffer_X.Size_U64 = 0; + _rAllocatedBuffer_X.pData_U8 = nullptr; + AllocateBuffer_X.AllocateZone_E = _AllocateZone_E; + switch (_AllocateZone_E) + { + default: + case BOF_BUFFER_ALLOCATE_ZONE::BOF_BUFFER_ALLOCATE_ZONE_RAM: +#if defined(_WIN32) + _rAllocatedBuffer_X.pData_U8 = reinterpret_cast(_aligned_malloc(_SizeInByte_U32, _AligmentInByte_U32)); // malloc(size); // TODO pChannel->getBoard()->getNUMANode() !!! +#else + _rAllocatedBuffer_X.pData_U8 = reinterpret_cast(aligned_alloc(_AligmentInByte_U32, _SizeInByte_U32)); // malloc(size); // TODO pChannel->getBoard()->getNUMANode() !!! +#endif + break; + + /* + * On a NUMA platform, the kernel will attempt to distribute the huge page pool + over all the set of allowed nodes specified by the NUMA memory policy of the + task that modifies nr_hugepages. https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt + */ + case BOF_BUFFER_ALLOCATE_ZONE::BOF_BUFFER_ALLOCATE_ZONE_HUGE_PAGE: +#if defined(_WIN32) +#else + void *pBuffer; + + S_HugePageId++; + snprintf(AllocateBuffer_X.pHugePath_c, sizeof(AllocateBuffer_X.pHugePath_c), BOF_HUGE_PAGE_PATH, S_HugePageId.load()); + AllocateBuffer_X.Io_i = open(AllocateBuffer_X.pHugePath_c, O_CREAT | O_RDWR, 0755); + if (AllocateBuffer_X.Io_i >= 0) + { + // BOFERR Bof_OpenSharedMemory(const std::string &_rName_S, uint32_t _SizeInByte_U32, BOF_SHARED_MEMORY &_rSharedMemory_X) + pBuffer = ::mmap(0, _SizeInByte_U32 < BOF_HUGE_PAGE_SIZE ? BOF_HUGE_PAGE_SIZE : _SizeInByte_U32, PROT_READ | PROT_WRITE, MAP_SHARED, AllocateBuffer_X.Io_i, 0); + if (pBuffer == MAP_FAILED) + { + ::close(AllocateBuffer_X.Io_i); + unlink(AllocateBuffer_X.pHugePath_c); + } + else + { + _rAllocatedBuffer_X.pData_U8 = reinterpret_cast(pBuffer); + } + } +#endif + break; + } + if (_rAllocatedBuffer_X.pData_U8) + { + _rAllocatedBuffer_X.pUser = new BOF_BUFFER_ALLOCATE_HEADER; + if (_rAllocatedBuffer_X.pUser) + { + Rts_E = BOF_ERR_NO_ERROR; + *reinterpret_cast(_rAllocatedBuffer_X.pUser) = AllocateBuffer_X; + if (_LockIt_B) + { + Rts_E = Bof_LockMem(_OsAdvice_i, _SizeInByte_U32, _rAllocatedBuffer_X.pData_U8); + if (Rts_E != BOF_ERR_NO_ERROR) + { + Bof_AlignedMemFree(_rAllocatedBuffer_X); + } + } + else + { +#if defined(_WIN32) +#else + if (_OsAdvice_i) + { + Rts_E = (madvise(_rAllocatedBuffer_X.pData_U8, _SizeInByte_U32, _OsAdvice_i) == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_SET; + } +#endif + } + if (Rts_E == BOF_ERR_NO_ERROR) + { + if (_ClearIt_B) + { + memset(_rAllocatedBuffer_X.pData_U8, 0, _SizeInByte_U32); + } + } + } + else + { + _rAllocatedBuffer_X.Deleter_E = BOF_BUFFER_DELETER_NONE; + _rAllocatedBuffer_X.pUser = &AllocateBuffer_X; + Bof_AlignedMemFree(_rAllocatedBuffer_X); + } + } + } + // printf("=======> alloc Zone %d Must %d handle %x:%p data %x:%p\n",AllocateBuffer_X.AllocateZone_E, _rAllocatedBuffer_X.MustBeDeleted_B, sizeof(BOF_BUFFER_ALLOCATE_HEADER), _rAllocatedBuffer_X.pUser, _SizeInByte_U32, _rAllocatedBuffer_X.pData_U8); + return Rts_E; } -BOFERR Bof_DestroyEvent(BOF_EVENT &_rEvent_X) -{ - BOFERR Rts_E = BOF_ERR_INIT; - if (_rEvent_X.Magic_U32 == BOF_EVENT_MAGIC) - { - _rEvent_X.Reset(); - Rts_E = BOF_ERR_NO_ERROR; - } +BOFERR Bof_AlignedMemFree(BOF_BUFFER &_rBuffer_X) +{ + BOF_BUFFER_ALLOCATE_HEADER *pAllocateBuffer_X; + BOFERR Rts_E = BOF_ERR_EINVAL; + + pAllocateBuffer_X = reinterpret_cast(_rBuffer_X.pUser); + if (pAllocateBuffer_X) + { + Rts_E = BOF_ERR_NO_ERROR; + if (pAllocateBuffer_X->Locked_B) + { + Rts_E = Bof_UnlockMem(_rBuffer_X.Capacity_U64, _rBuffer_X.pData_U8); + } + switch (pAllocateBuffer_X->AllocateZone_E) + { + default: + case BOF_BUFFER_ALLOCATE_ZONE::BOF_BUFFER_ALLOCATE_ZONE_RAM: +#if defined(_WIN32) + _aligned_free(_rBuffer_X.pData_U8); + // VirtualFree(_rBuffer_X.pData_U8, _rBuffer_X.Capacity_U64, MEM_RELEASE); +#else + free(_rBuffer_X.pData_U8); +#endif + break; + + case BOF_BUFFER_ALLOCATE_ZONE::BOF_BUFFER_ALLOCATE_ZONE_HUGE_PAGE: +#if defined(_WIN32) +#else + ::munmap(_rBuffer_X.pData_U8, _rBuffer_X.Size_U64); + ::close(pAllocateBuffer_X->Io_i); + unlink(pAllocateBuffer_X->pHugePath_c); +#endif + break; + } + // printf("=======> DELETE Zone %d Must %d handle %x:%p data %lx:%p\n",pAllocateBuffer_X->AllocateZone_E, _rBuffer_X.MustBeDeleted_B, sizeof(BOF_BUFFER_ALLOCATE_HEADER), _rBuffer_X.pUser, _rBuffer_X.SizeInByte_U64, _rBuffer_X.pData_U8); + + _rBuffer_X.Deleter_E = BOF_BUFFER_DELETER_NONE; // Done by free or _aligned_free + BOF_SAFE_DELETE(pAllocateBuffer_X); + _rBuffer_X.Reset(); + } + return Rts_E; +} + +std::string Bof_DumpMemoryZone(const BOF_DUMP_MEMORY_ZONE_PARAM &_rDumpMemoryZoneParam_X) +{ + const uint32_t MAX_NBBYTEPERLINE = 1024; + uint32_t i_U32, j_U32, IndexInMemoryZone_U32, NbBytePerRead_U32, MemoryZoneSizeInByte_U32, NbItemBytePerLine_U32; + int32_t Remain_S32; + uint8_t Data_U8, pData_U8[8]; + const volatile uint8_t *pMemoryZone_U8; + char *pBinaryData_c, pBinary_c[2 + 8 + 1 + (MAX_NBBYTEPERLINE * 5) + MAX_NBBYTEPERLINE + 2 + 1], pAscii_c[MAX_NBBYTEPERLINE + 1]; // 2: 0x 1: Separator 5: 0x%2Separator + std::string Rts_S = ""; + uint64_t VirtualOffset_S64; + volatile const uint64_t *pDataVal_U64; + volatile uint64_t *pDataPtr_U64; + volatile const uint32_t *pDataVal_U32; + volatile uint32_t *pDataPtr_U32; + volatile const uint16_t *pDataVal_U16; + volatile uint16_t *pDataPtr_U16; + + if ((_rDumpMemoryZoneParam_X.pMemoryZone) && (_rDumpMemoryZoneParam_X.Separator_c != 0)) + { + pMemoryZone_U8 = reinterpret_cast(_rDumpMemoryZoneParam_X.pMemoryZone); + if ((_rDumpMemoryZoneParam_X.GenerateVirtualOffset) || (_rDumpMemoryZoneParam_X.GenerateBinaryData_B) || (_rDumpMemoryZoneParam_X.GenerateAsciiData_B)) + { + IndexInMemoryZone_U32 = 0; + VirtualOffset_S64 = (_rDumpMemoryZoneParam_X.VirtualOffset_S64 == -1) ? reinterpret_cast(_rDumpMemoryZoneParam_X.pMemoryZone) : _rDumpMemoryZoneParam_X.VirtualOffset_S64; + switch (_rDumpMemoryZoneParam_X.AccessSize_E) + { + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_64: + NbBytePerRead_U32 = 8; + MemoryZoneSizeInByte_U32 = (_rDumpMemoryZoneParam_X.NbItemToDump_U32 * NbBytePerRead_U32); + Remain_S32 = static_cast(MemoryZoneSizeInByte_U32) & 0xFFFFFFF8; + break; + + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_32: + NbBytePerRead_U32 = 4; + MemoryZoneSizeInByte_U32 = (_rDumpMemoryZoneParam_X.NbItemToDump_U32 * NbBytePerRead_U32); + Remain_S32 = static_cast(MemoryZoneSizeInByte_U32) & 0xFFFFFFFC; + break; + + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_16: + NbBytePerRead_U32 = 2; + MemoryZoneSizeInByte_U32 = (_rDumpMemoryZoneParam_X.NbItemToDump_U32 * NbBytePerRead_U32); + Remain_S32 = static_cast(MemoryZoneSizeInByte_U32) & 0xFFFFFFFE; + break; + + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_8: + default: + NbBytePerRead_U32 = 1; + MemoryZoneSizeInByte_U32 = (_rDumpMemoryZoneParam_X.NbItemToDump_U32 * NbBytePerRead_U32); + Remain_S32 = static_cast(MemoryZoneSizeInByte_U32) & 0xFFFFFFFF; + break; + } + if (_rDumpMemoryZoneParam_X.NbItemPerLine_U32 <= (MAX_NBBYTEPERLINE / NbBytePerRead_U32)) + { + while (Remain_S32 > 0) + { + pBinaryData_c = pBinary_c; + if (_rDumpMemoryZoneParam_X.GenerateVirtualOffset) + { + if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) + { + if (VirtualOffset_S64 > 0xFFFFFFFF) + { + pBinaryData_c += sprintf(pBinaryData_c, "0x%016" PRIX64 "%c%c%c", VirtualOffset_S64, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c); + } + else + { + pBinaryData_c += sprintf(pBinaryData_c, "0x%08X%c%c%c", static_cast(VirtualOffset_S64), _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c); + } + } + else + { + if (VirtualOffset_S64 > 0xFFFFFFFF) + { + pBinaryData_c += sprintf(pBinaryData_c, "%016" PRIX64 "%c%c%c", VirtualOffset_S64, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c); + } + else + { + pBinaryData_c += sprintf(pBinaryData_c, "%08X%c%c%c", static_cast(VirtualOffset_S64), _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c); + } + } + } + + NbItemBytePerLine_U32 = _rDumpMemoryZoneParam_X.NbItemPerLine_U32 * NbBytePerRead_U32; + for (i_U32 = 0; i_U32 < NbItemBytePerLine_U32; i_U32 += NbBytePerRead_U32) + { + if (IndexInMemoryZone_U32 >= MemoryZoneSizeInByte_U32) + { + if (_rDumpMemoryZoneParam_X.GenerateBinaryData_B) + { + switch (_rDumpMemoryZoneParam_X.AccessSize_E) + { + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_64: + if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) + { + pBinaryData_c += sprintf(pBinaryData_c, " "); + } + else + { + pBinaryData_c += sprintf(pBinaryData_c, " "); + } + break; + + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_32: + if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) + { + pBinaryData_c += sprintf(pBinaryData_c, " "); + } + else + { + pBinaryData_c += sprintf(pBinaryData_c, " "); + } + break; + + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_16: + if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) + { + pBinaryData_c += sprintf(pBinaryData_c, " "); + } + else + { + pBinaryData_c += sprintf(pBinaryData_c, " "); + } + break; + + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_8: + default: + if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) + { + pBinaryData_c += sprintf(pBinaryData_c, " "); + } + else + { + pBinaryData_c += sprintf(pBinaryData_c, " "); + } + break; + } + } + if (_rDumpMemoryZoneParam_X.GenerateAsciiData_B) + { + for (j_U32 = 0; j_U32 < NbBytePerRead_U32; j_U32++) + { + pAscii_c[i_U32 + j_U32] = ' '; + } + } + } + else + { + if (_rDumpMemoryZoneParam_X.GenerateBinaryData_B) + { + switch (_rDumpMemoryZoneParam_X.AccessSize_E) + { + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_64: + // *(uint64_t *)pData_U8 = *(uint64_t *)(&pMemoryZone_U8[IndexInMemoryZone_U32]); + pDataPtr_U64 = reinterpret_cast(pData_U8); + pDataVal_U64 = reinterpret_cast(&pMemoryZone_U8[IndexInMemoryZone_U32]); + *pDataPtr_U64 = *pDataVal_U64; + if (_rDumpMemoryZoneParam_X.ReverseEndianness_B) + { + BOF_SWAP64PTR(pData_U8); + } + + if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) + { + pBinaryData_c += sprintf(pBinaryData_c, "0x%016" PRIX64 "%c", *pDataPtr_U64, _rDumpMemoryZoneParam_X.Separator_c); + } + else + { + pBinaryData_c += sprintf(pBinaryData_c, "%016" PRIX64 "%c", *pDataPtr_U64, _rDumpMemoryZoneParam_X.Separator_c); + } - return Rts_E; -} + break; -BOFERR Bof_GetThreadPriorityRange(BOF_THREAD_SCHEDULER_POLICY _ThreadSchedulerPolicy_E, BOF_THREAD_PRIORITY &_rMin_E, BOF_THREAD_PRIORITY &_rMax_E) -{ - BOFERR Rts_E; + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_32: + // *(uint32_t *)pData_U8 = *(uint32_t *)(&pMemoryZone_U8[IndexInMemoryZone_U32]); + pDataPtr_U32 = reinterpret_cast(pData_U8); + pDataVal_U32 = reinterpret_cast(&pMemoryZone_U8[IndexInMemoryZone_U32]); + *pDataPtr_U32 = *pDataVal_U32; -#if defined(_WIN32) - switch (_ThreadSchedulerPolicy_E) - { - case BOF_THREAD_SCHEDULER_POLICY_OTHER: - _rMin_E = BOF_THREAD_PRIORITY_000; - _rMax_E = BOF_THREAD_PRIORITY_000; - Rts_E = BOF_ERR_NO_ERROR; - break; + if (_rDumpMemoryZoneParam_X.ReverseEndianness_B) + { + BOF_SWAP32PTR(pData_U8); + } + if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) + { + pBinaryData_c += sprintf(pBinaryData_c, "0x%08X%c", *pDataPtr_U32, _rDumpMemoryZoneParam_X.Separator_c); + } + else + { + pBinaryData_c += sprintf(pBinaryData_c, "%08X%c", *pDataPtr_U32, _rDumpMemoryZoneParam_X.Separator_c); + } + break; - case BOF_THREAD_SCHEDULER_POLICY_ROUND_ROBIN: - case BOF_THREAD_SCHEDULER_POLICY_FIFO: - _rMin_E = BOF_THREAD_PRIORITY_001; - _rMax_E = BOF_THREAD_PRIORITY_099; - Rts_E = BOF_ERR_NO_ERROR; - break; + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_16: + // *(uint16_t *)pData_U8 = *(uint16_t *)(&pMemoryZone_U8[IndexInMemoryZone_U32]); + pDataPtr_U16 = reinterpret_cast(pData_U8); + pDataVal_U16 = reinterpret_cast(&pMemoryZone_U8[IndexInMemoryZone_U32]); + *pDataPtr_U16 = *pDataVal_U16; - default: - _rMin_E = BOF_THREAD_PRIORITY_000; - _rMax_E = BOF_THREAD_PRIORITY_000; - Rts_E = BOF_ERR_EINVAL; - break; - } -#else - int Min_i = sched_get_priority_min(_ThreadSchedulerPolicy_E); - int Max_i = sched_get_priority_max(_ThreadSchedulerPolicy_E); + if (_rDumpMemoryZoneParam_X.ReverseEndianness_B) + { + BOF_SWAP16PTR(pData_U8); + } + if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) + { + pBinaryData_c += sprintf(pBinaryData_c, "0x%04X%c", *pDataPtr_U16, _rDumpMemoryZoneParam_X.Separator_c); + } + else + { + pBinaryData_c += sprintf(pBinaryData_c, "%04X%c", *pDataPtr_U16, _rDumpMemoryZoneParam_X.Separator_c); + } + break; - if ((Min_i != EINVAL) && (Max_i != EINVAL)) - { - _rMin_E = (BOF_THREAD_PRIORITY)Min_i; - _rMax_E = (BOF_THREAD_PRIORITY)Max_i; - Rts_E = BOF_ERR_NO_ERROR; + case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_8: + default: + pData_U8[0] = pMemoryZone_U8[IndexInMemoryZone_U32 + 0]; + if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) + { + pBinaryData_c += sprintf(pBinaryData_c, "0x%02X%c", *pData_U8, _rDumpMemoryZoneParam_X.Separator_c); + } + else + { + pBinaryData_c += sprintf(pBinaryData_c, "%02X%c", *pData_U8, _rDumpMemoryZoneParam_X.Separator_c); + } + break; + } + } + if (_rDumpMemoryZoneParam_X.GenerateAsciiData_B) + { + for (j_U32 = 0; j_U32 < NbBytePerRead_U32; j_U32++) + { + Data_U8 = pMemoryZone_U8[IndexInMemoryZone_U32 + j_U32]; + pAscii_c[i_U32 + j_U32] = ((Data_U8 < 32) || (Data_U8 > 127)) ? '?' : Data_U8; + } + } + IndexInMemoryZone_U32 += NbBytePerRead_U32; + Remain_S32 -= NbBytePerRead_U32; + } // else if (IndexInMemoryZone_U32 >= _MemoryZoneSizeInByte_U32) + } // for (i_U32 = 0; i_U32 < _NbDataPerLine_U32; i_U32++) + if (_rDumpMemoryZoneParam_X.GenerateBinaryData_B) + { + Rts_S += pBinary_c; + } + if (_rDumpMemoryZoneParam_X.GenerateAsciiData_B) + { + pAscii_c[NbItemBytePerLine_U32] = 0; + Rts_S += pAscii_c; + } + Rts_S += '\n'; // same for linux and windows Bof_Eol(); + VirtualOffset_S64 += NbItemBytePerLine_U32; + } // while (Remain_S32 > 0) } -#endif - return Rts_E; + } // if ((_GenerateVirtualOffset) || (_GenerateBinaryData_B) || (_GenerateAsciiData_B)) + } // if ((_pMemoryZone_U8) && (_NbDataPerLine_U32 <= MAX_NBBYTEPERLINE) && (_Separator_c != 0)) + // printf("%s", Rts_S.c_str()); + return Rts_S; } -/*! - * Description - * This function retrieve current scheduling - * policy and priority of the current thread - * - * Parameters - * _rPolicy_E - The policy of the thread - * _rPriority_E - The priority of the thread - * - * Returns - * true - The operation was successful - * false - The operation failed - * - * Remarks - * None - */ -BOFERR Bof_GetThreadPriorityLevel(BOF_THREAD &_rThread_X, BOF_THREAD_SCHEDULER_POLICY &_rPolicy_E, BOF_THREAD_PRIORITY &_rPriority_E) -{ - BOFERR Rts_E = BOF_ERR_INIT; - if (_rThread_X.Magic_U32 == BOF_THREAD_MAGIC) - { -#if defined(_WIN32) - void *Process_h = GetCurrentProcess(); - - switch (GetPriorityClass(Process_h)) - { - default: - case NORMAL_PRIORITY_CLASS: - _rPolicy_E = BOF_THREAD_SCHEDULER_POLICY::BOF_THREAD_SCHEDULER_POLICY_OTHER; - break; - - case REALTIME_PRIORITY_CLASS: - _rPolicy_E = BOF_THREAD_SCHEDULER_POLICY::BOF_THREAD_SCHEDULER_POLICY_FIFO; - break; - } - _rPriority_E = Bof_ThreadPriorityFromPriorityValue(GetThreadPriority(_rThread_X.pThread)); - Rts_E = BOF_ERR_NO_ERROR; -#else - int Status_i = 0; - int Policy_i = 0; - struct sched_param Params_X; - - Rts_E = BOF_ERR_EINVAL; - Status_i = pthread_getschedparam(_rThread_X.ThreadId, &Policy_i, &Params_X); - - if (Status_i == 0) - { - _rPolicy_E = (BOF_THREAD_SCHEDULER_POLICY)Policy_i; - _rPriority_E = Bof_ThreadPriorityFromPriorityValue(Params_X.sched_priority); - Rts_E = BOF_ERR_NO_ERROR; - } -#endif - } - return Rts_E; -} // Internal // THREAD_PRIORITY_TIME_CRITICAL 15 Base priority of 15 for IDLE_PRIORITY_CLASS, // THREAD_PRIORITY_HIGHEST 2 Priority 2 points above the priority class. @@ -1493,7 +1631,7 @@ int32_t Bof_PriorityValueFromThreadPriority(BOF_THREAD_PRIORITY _Priority_E) break; } #else - Rts_S32 = static_cast(_Priority_E); + Rts_S32 = static_cast(_Priority_E); #endif } @@ -1527,36 +1665,100 @@ BOF_THREAD_PRIORITY Bof_ThreadPriorityFromPriorityValue(int32_t _Priority_S32) Rts_E = BOF_THREAD_PRIORITY_052; break; - case 2: - Rts_E = BOF_THREAD_PRIORITY_068; - break; + case 2: + Rts_E = BOF_THREAD_PRIORITY_068; + break; + + case 15: + Rts_E = BOF_THREAD_PRIORITY_085; + break; + } +#else + Rts_E = static_cast(_Priority_S32); +#endif + + return Rts_E; +} + +BOFERR Bof_GetThreadPriorityRange(BOF_THREAD_SCHEDULER_POLICY _ThreadSchedulerPolicy_E, BOF_THREAD_PRIORITY &_rMin_E, BOF_THREAD_PRIORITY &_rMax_E) +{ + BOFERR Rts_E; + +#if defined(_WIN32) + switch (_ThreadSchedulerPolicy_E) + { + case BOF_THREAD_SCHEDULER_POLICY_OTHER: + _rMin_E = BOF_THREAD_PRIORITY_000; + _rMax_E = BOF_THREAD_PRIORITY_000; + Rts_E = BOF_ERR_NO_ERROR; + break; + + case BOF_THREAD_SCHEDULER_POLICY_ROUND_ROBIN: + case BOF_THREAD_SCHEDULER_POLICY_FIFO: + _rMin_E = BOF_THREAD_PRIORITY_001; + _rMax_E = BOF_THREAD_PRIORITY_099; + Rts_E = BOF_ERR_NO_ERROR; + break; + + default: + _rMin_E = BOF_THREAD_PRIORITY_000; + _rMax_E = BOF_THREAD_PRIORITY_000; + Rts_E = BOF_ERR_EINVAL; + break; + } +#else + int Min_i = sched_get_priority_min(_ThreadSchedulerPolicy_E); + int Max_i = sched_get_priority_max(_ThreadSchedulerPolicy_E); + + if ((Min_i != EINVAL) && (Max_i != EINVAL)) + { + _rMin_E = (BOF_THREAD_PRIORITY)Min_i; + _rMax_E = (BOF_THREAD_PRIORITY)Max_i; + Rts_E = BOF_ERR_NO_ERROR; + } +#endif + return Rts_E; +} + +BOFERR Bof_GetThreadPriorityLevel(BOF_THREAD &_rThread_X, BOF_THREAD_SCHEDULER_POLICY &_rPolicy_E, BOF_THREAD_PRIORITY &_rPriority_E) +{ + BOFERR Rts_E = BOF_ERR_INIT; + if (_rThread_X.Magic_U32 == BOF_THREAD_MAGIC) + { +#if defined(_WIN32) + void *Process_h = GetCurrentProcess(); + + switch (GetPriorityClass(Process_h)) + { + default: + case NORMAL_PRIORITY_CLASS: + _rPolicy_E = BOF_THREAD_SCHEDULER_POLICY::BOF_THREAD_SCHEDULER_POLICY_OTHER; + break; + + case REALTIME_PRIORITY_CLASS: + _rPolicy_E = BOF_THREAD_SCHEDULER_POLICY::BOF_THREAD_SCHEDULER_POLICY_FIFO; + break; + } + _rPriority_E = Bof_ThreadPriorityFromPriorityValue(GetThreadPriority(_rThread_X.pThread)); + Rts_E = BOF_ERR_NO_ERROR; +#else + int Status_i = 0; + int Policy_i = 0; + struct sched_param Params_X; + + Rts_E = BOF_ERR_EINVAL; + Status_i = pthread_getschedparam(_rThread_X.ThreadId, &Policy_i, &Params_X); - case 15: - Rts_E = BOF_THREAD_PRIORITY_085; - break; - } -#else - Rts_E = static_cast(_Priority_S32); + if (Status_i == 0) + { + _rPolicy_E = (BOF_THREAD_SCHEDULER_POLICY)Policy_i; + _rPriority_E = Bof_ThreadPriorityFromPriorityValue(Params_X.sched_priority); + Rts_E = BOF_ERR_NO_ERROR; + } #endif - + } return Rts_E; } -/*! - * Description - * This function sets the policy and priority - * of the thread - * - * Parameters - * _ThreadSchedulerPolicy_E - The policy of the thread - * _ThreadPriority_E - The priority of the thread - * - * Returns - * true - The operation was successful - * false - The operation failed - * - * Remarks - * None - */ BOFERR Bof_SetThreadPriorityLevel(BOF_THREAD &_rThread_X, BOF_THREAD_SCHEDULER_POLICY _ThreadSchedulerPolicy_E, BOF_THREAD_PRIORITY _ThreadPriority_E) { @@ -1606,6 +1808,77 @@ BOFERR Bof_SetThreadPriorityLevel(BOF_THREAD &_rThread_X, BOF_THREAD_SCHEDULER_P return Rts_E; } +BOFERR Bof_GetThreadExitCode(BOF_THREAD &_rThread_X, BOFERR *_pRtsCode_E) +{ + BOFERR Rts_E = BOF_ERR_EINVAL; + + if (_rThread_X.Magic_U32 == BOF_THREAD_MAGIC) + { + if (_rThread_X.ThreadRunning_B) + { + Rts_E = BOF_ERR_RUNNING; + } + else + { + Rts_E = BOF_ERR_NO_ERROR; + if (_pRtsCode_E != nullptr) + { + *_pRtsCode_E = _rThread_X.ThreadExitCode_E; + } + } + } + return Rts_E; +} + +int Bof_BofThreadBalance() +{ + return S_BofThreadBalance.load(); +} + +uint32_t Bof_CurrentThreadId() +{ +#if defined(_WIN32) + uint32_t Rts_U32 = static_cast(GetCurrentThreadId()); +#else + uint32_t Rts_U32 = static_cast(pthread_self()); +#endif + return Rts_U32; +} + +BOFERR Bof_SetCurrentThreadPriorityLevel(BOF_THREAD_SCHEDULER_POLICY _Policy_E, BOF_THREAD_PRIORITY _Priority_E) +{ + BOFERR Rts_E = BOF_ERR_PRIORITY; + int32_t Priority_i = Bof_PriorityValueFromThreadPriority(_Priority_E); +#if defined(__EMSCRIPTEN__) || defined(__linux__) + int Status_i = 0; + int Policy_i = 0; + pthread_t Thread_h = pthread_self(); + struct sched_param Params_X; + + Params_X.sched_priority = Priority_i; + Status_i = pthread_setschedparam(Thread_h, _Policy_E, &Params_X); + if (Status_i == 0) + { + Status_i = pthread_getschedparam(Thread_h, &Policy_i, &Params_X); + if ((Policy_i == _Policy_E) && (Params_X.sched_priority == Priority_i)) + { + Rts_E = BOF_ERR_NO_ERROR; + } + } +#else + // if (SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)); // Get the current process and set it to "Realtime" priority class. + HANDLE Thread_h = GetCurrentThread(); + if (BOF_IS_HANDLE_VALID(Thread_h)) + { + if (SetThreadPriority(Thread_h, Priority_i)) // THREAD_PRIORITY_LOWEST))// Priority_i)) + { + Rts_E = BOF_ERR_NO_ERROR; + } + } +#endif + return Rts_E; +} + BOFERR Bof_CreateThread(const std::string &_rName_S, BofThreadFunction _ThreadFunction, void *_pUserContext, BOF_THREAD &_rThread_X) { BOFERR Rts_E = BOF_ERR_EEXIST; @@ -1634,51 +1907,11 @@ BOFERR Bof_CreateThread(const std::string &_rName_S, BofThreadFunction _ThreadFu } return Rts_E; } -/*! - * Description - * This function gets the exit code of the thread - * - * Parameters - * _Thread_h - The handle obtained by the call to Bof_CreateThread - * _pRetCode - The exit code of the thread - * - * Returns - * BOF_ERR_EINVAL - Invalid arg - * BOF_ERR_RUNNING - thread still running - * BOF_ERR_NO_ERROR - The operation was successful - * - * Remarks - * None - */ -BOFERR Bof_GetThreadExitCode(BOF_THREAD &_rThread_X, BOFERR *_pRtsCode_E) -{ - BOFERR Rts_E = BOF_ERR_EINVAL; - if (_rThread_X.Magic_U32 == BOF_THREAD_MAGIC) - { - if (_rThread_X.ThreadRunning_B) - { - Rts_E = BOF_ERR_RUNNING; - } - else - { - Rts_E = BOF_ERR_NO_ERROR; - if (_pRtsCode_E != nullptr) - { - *_pRtsCode_E = _rThread_X.ThreadExitCode_E; - } - } - } - return Rts_E; -} bool Bof_IsThreadValid(BOF_THREAD &_rThread_X) { return (_rThread_X.Magic_U32 == BOF_THREAD_MAGIC); } -int Bof_BofThreadBalance() -{ - return S_BofThreadBalance.load(); -} static void *S_ThreadLauncher(void *_pThreadContext) { @@ -1967,94 +2200,6 @@ BOFERR Bof_StopThread(BOF_THREAD &_rThread_X) return Rts_E; } -uint32_t Bof_CurrentThreadId() -{ -#if defined(_WIN32) - uint32_t Rts_U32 = static_cast(GetCurrentThreadId()); -#else - uint32_t Rts_U32 = static_cast(pthread_self()); -#endif - return Rts_U32; -} - -BOFERR Bof_SetCurrentThreadPriorityLevel(BOF_THREAD_SCHEDULER_POLICY _Policy_E, BOF_THREAD_PRIORITY _Priority_E) -{ - BOFERR Rts_E = BOF_ERR_PRIORITY; - int32_t Priority_i = Bof_PriorityValueFromThreadPriority(_Priority_E); -#if defined(__EMSCRIPTEN__) || defined(__linux__) - int Status_i = 0; - int Policy_i = 0; - pthread_t Thread_h = pthread_self(); - struct sched_param Params_X; - - Params_X.sched_priority = Priority_i; - Status_i = pthread_setschedparam(Thread_h, _Policy_E, &Params_X); - if (Status_i == 0) - { - Status_i = pthread_getschedparam(Thread_h, &Policy_i, &Params_X); - if ((Policy_i == _Policy_E) && (Params_X.sched_priority == Priority_i)) - { - Rts_E = BOF_ERR_NO_ERROR; - } - } -#else - // if (SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)); // Get the current process and set it to "Realtime" priority class. - HANDLE Thread_h = GetCurrentThread(); - if (BOF_IS_HANDLE_VALID(Thread_h)) - { - if (SetThreadPriority(Thread_h, Priority_i)) // THREAD_PRIORITY_LOWEST))// Priority_i)) - { - Rts_E = BOF_ERR_NO_ERROR; - } - } -#endif - return Rts_E; -} - -uint32_t Bof_InterlockedCompareExchange(volatile uint32_t *_pDestination_U32, uint32_t _ValueToSetIfEqual_U32, uint32_t _CheckIfEqualToThis_U32) -{ - uint32_t Rts_U32; - -#if defined(_WIN32) - // The function returns the initial value of the Destination parameter. - static_assert(sizeof(LONG) == sizeof(uint32_t)); - Rts_U32 = InterlockedCompareExchange(_pDestination_U32, _ValueToSetIfEqual_U32, _CheckIfEqualToThis_U32); -#else - // The function returns the initial value of the Destination parameter. - Rts_U32 = __sync_val_compare_and_swap(_pDestination_U32, _CheckIfEqualToThis_U32, _ValueToSetIfEqual_U32); -#endif - return Rts_U32; -} - -BOFERR Bof_GetMemoryState(uint64_t &_rAvailableFreeMemory_U64, uint64_t &_rTotalMemorySize_U64) -{ - BOFERR Rts_E = BOF_ERR_INTERNAL; - -#if defined(_WIN32) - MEMORYSTATUSEX Ms_X; - Ms_X.dwLength = sizeof(Ms_X); - if (GlobalMemoryStatusEx(&Ms_X)) - { - _rAvailableFreeMemory_U64 = Ms_X.ullAvailPhys; - _rTotalMemorySize_U64 = Ms_X.ullTotalPhys; - - Rts_E = BOF_ERR_NO_ERROR; - } - else - { - _rAvailableFreeMemory_U64 = 0; - _rTotalMemorySize_U64 = 0; - } -#else - int PageSize_i = static_cast(sysconf(_SC_PAGE_SIZE)); - - _rAvailableFreeMemory_U64 = (get_avphys_pages() * PageSize_i); - _rTotalMemorySize_U64 = (get_phys_pages() * PageSize_i); - Rts_E = BOF_ERR_NO_ERROR; -#endif - return Rts_E; -} - BOFERR Bof_GetLastError(bool _NetError_B, int32_t *_pNativeErrorCode_S32) { BOFERR Rts_E; @@ -2647,68 +2792,14 @@ BOFERR Bof_GetLastError(bool _NetError_B, int32_t *_pNativeErrorCode_S32) } } #else - (void)_NetError_B; - if (_pNativeErrorCode_S32) - { - *_pNativeErrorCode_S32 = errno; - } - Rts_E = static_cast(errno); -#endif - return Rts_E; -} - -bool Bof_IsPidRunning(uint32_t _Pid_U32) -{ - bool Rts_B = false; - -#if defined(_WIN32) - /* - * GetModuleFileNameEx(process, 0, buffer, 256); - * EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) - * GetModuleBaseName(hProcess, 0, buffer, 50); - */ - void *Process_h; - uint32_t ExitCode_U32; - - Process_h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, _Pid_U32); - - if (Process_h) + (void)_NetError_B; + if (_pNativeErrorCode_S32) { - GetExitCodeProcess(Process_h, (DWORD *)&ExitCode_U32); - - if (ExitCode_U32 == STILL_ACTIVE) - { - Rts_B = true; - } - CloseHandle(Process_h); - } -#else - /* - * In Linux, use the kill subroutine to send the signal specified by the Signal parameter to the process specified by the Process - * parameter (processId). The Signal parameter is a null value, the error checking is performed, but no signal is sent. - */ - if ((kill(_Pid_U32, 0) == -1) && (errno == ESRCH) // No process can be found corresponding to processId - ) - { - } - else - { - Rts_B = true; - } -#endif - return Rts_B; -} - -uint32_t Bof_GetCurrentPid() -{ - uint32_t Rts_U32; - -#if defined(_WIN32) - Rts_U32 = GetCurrentProcessId(); -#else - Rts_U32 = getpid(); + *_pNativeErrorCode_S32 = errno; + } + Rts_E = static_cast(errno); #endif - return Rts_U32; + return Rts_E; } bool Bof_PatternCompare(const char *_pString_c, const char *_pPattern_c) @@ -2719,7 +2810,7 @@ bool Bof_PatternCompare(const char *_pString_c, const char *_pPattern_c) // Bof_PatternCompare(_pString_c, _pPattern_c + 1) || *_pString_c && Bof_PatternCompare(_pString_c + 1, _pPattern_c); return *_pPattern_c - '*' ? *_pString_c ? (*_pPattern_c == '?') || (((*_pString_c) == (*_pPattern_c)) && Bof_PatternCompare(_pString_c + 1, _pPattern_c + 1)) : !*_pPattern_c - : Bof_PatternCompare(_pString_c, _pPattern_c + 1) || (*_pString_c && Bof_PatternCompare(_pString_c + 1, _pPattern_c)); + : Bof_PatternCompare(_pString_c, _pPattern_c + 1) || (*_pString_c && Bof_PatternCompare(_pString_c + 1, _pPattern_c)); } else { @@ -2727,589 +2818,232 @@ bool Bof_PatternCompare(const char *_pString_c, const char *_pPattern_c) } } -BOFERR Bof_Exec(const std::string &_rCommand_S, std::string *_pCapturedOutput_S, int32_t &_rExitCode_S32) -{ - BOFERR Rts_E = BOF_ERR_CANNOT_START; - FILE *pPipeOut_X; - char pData_c[4096]; - std::string Command_S, CapturedOutput_S; - - _rExitCode_S32 = -1; - Command_S = Bof_Sprintf("%s 2>&1", _rCommand_S.c_str()); - -#if defined(_WIN32) - pPipeOut_X = _popen(Command_S.c_str(), "r"); -#else - pPipeOut_X = popen(Command_S.c_str(), "r"); -#endif - if (pPipeOut_X) - { - while (fgets(pData_c, sizeof(pData_c), pPipeOut_X) != nullptr) - { - if (_pCapturedOutput_S) - { - CapturedOutput_S += pData_c; - } - } - Rts_E = BOF_ERR_NO_ERROR; - if (_pCapturedOutput_S) - { - *_pCapturedOutput_S = CapturedOutput_S; - } -#if defined(_WIN32) - _rExitCode_S32 = _pclose(pPipeOut_X); -#else - _rExitCode_S32 = pclose(pPipeOut_X); -#endif - _rExitCode_S32 = _rExitCode_S32 / 256; // Exit code is in upper bits - } - - return (Rts_E); -} - -const char *Bof_GetEnvVar(const char *_pName_c) -{ - const char *pRts_c = nullptr; - - if (_pName_c) - { - pRts_c = getenv(_pName_c); - } - return (pRts_c); -} - -int Bof_SetEnvVar(const char *_pName_c, const char *_pValue_c, int _Overwrite_i) -{ - int Rts_i = -1; - - if ((_pName_c) && (_pValue_c)) - { - if (_Overwrite_i) - { - Rts_i = 0; - } - else - { - Rts_i = (Bof_GetEnvVar(_pName_c) != nullptr) ? -2 : 0; - } - if (Rts_i == 0) - { -#if defined(_WIN32) - Rts_i = _putenv_s(_pName_c, _pValue_c); -#else - char pEnv_c[1024]; - snprintf(pEnv_c, sizeof(pEnv_c), "%s=%s", _pName_c, _pValue_c); - Rts_i = putenv(pEnv_c); -#endif - } - } - return (Rts_i); -} - -//_OsAdvice_i mainly for MADV_DONTFORK option in madvise -BOFERR Bof_LockMem(int _OsAdvice_i, uint64_t _SizeInByte_U64, void *_pData) -{ - BOFERR Rts_E; - -#if defined(_WIN32) - // Rts_E = VirtualLock(_pData, _SizeInByte_U64) ? BOF_ERR_NO_ERROR : BOF_ERR_LOCK; - Rts_E = BOF_ERR_LOCK; -#else - int Sts_i; - if (_OsAdvice_i) - { - Sts_i = madvise(_pData, _SizeInByte_U64, _OsAdvice_i); - Rts_E = (Sts_i == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_SET; - if (Rts_E == BOF_ERR_NO_ERROR) - { - Sts_i = mlock(_pData, _SizeInByte_U64); - Rts_E = (Sts_i == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_LOCK; - } - } - else - { - Rts_E = BOF_ERR_NO_ERROR; - } - if (Rts_E == BOF_ERR_NO_ERROR) - { - Sts_i = mlock(_pData, _SizeInByte_U64); - Rts_E = (Sts_i == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_LOCK; - } -#endif - return Rts_E; -} -BOFERR Bof_UnlockMem(uint64_t _SizeInByte_U64, void *_pData) +uint32_t Bof_InterlockedCompareExchange(volatile uint32_t *_pDestination_U32, uint32_t _ValueToSetIfEqual_U32, uint32_t _CheckIfEqualToThis_U32) { - BOFERR Rts_E; + uint32_t Rts_U32; #if defined(_WIN32) - // Rts_E = VirtualUnlock(_pData, _SizeInByte_U64) ? BOF_ERR_NO_ERROR : BOF_ERR_LOCK; - Rts_E = BOF_ERR_LOCK; + // The function returns the initial value of the Destination parameter. + static_assert(sizeof(LONG) == sizeof(uint32_t)); + Rts_U32 = InterlockedCompareExchange(_pDestination_U32, _ValueToSetIfEqual_U32, _CheckIfEqualToThis_U32); #else - Rts_E = (munlock(_pData, _SizeInByte_U64) == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_LOCK; + // The function returns the initial value of the Destination parameter. + Rts_U32 = __sync_val_compare_and_swap(_pDestination_U32, _CheckIfEqualToThis_U32, _ValueToSetIfEqual_U32); #endif - return Rts_E; -} -bool Bof_AlignedMemCpy8(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32) -{ - bool Rts_B = true; - uint32_t i_U32; - volatile uint8_t *pDst_U8 = reinterpret_cast(_pDst); - const volatile uint8_t *pSrc_U8 = reinterpret_cast(_pSrc); - - for (i_U32 = 0; i_U32 < _SizeInByte_U32; i_U32++) - { - pDst_U8[i_U32] = pSrc_U8[i_U32]; - } - return Rts_B; -} - -bool Bof_AlignedMemCpy16(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32) -{ - bool Rts_B = false; - uint32_t i_U32, SizeInWord_U32; - volatile uint16_t *pDst_U16 = reinterpret_cast(_pDst); - const volatile uint16_t *pSrc_U16 = reinterpret_cast(_pSrc); - - if (((reinterpret_cast(_pDst) & 0x01) == 0) && ((reinterpret_cast(_pSrc) & 0x01) == 0)) - { - SizeInWord_U32 = _SizeInByte_U32 >> 1; - for (i_U32 = 0; i_U32 < SizeInWord_U32; i_U32++) - { - pDst_U16[i_U32] = pSrc_U16[i_U32]; - } - Rts_B = true; - } - return Rts_B; + return Rts_U32; } -bool Bof_AlignedMemCpy32(volatile void *_pDst, const volatile void *_pSrc, uint32_t _SizeInByte_U32) +bool Bof_IsPidRunning(uint32_t _Pid_U32) { bool Rts_B = false; - uint32_t i_U32, SizeInDword_U32; - volatile uint32_t *pDst_U32 = reinterpret_cast(_pDst); - const volatile uint32_t *pSrc_U32 = reinterpret_cast(_pSrc); - if (((reinterpret_cast(_pDst) & 0x03) == 0) && ((reinterpret_cast(_pSrc) & 0x03) == 0)) - { - // SizeInDword_U32 = (_SizeInByte_U32 & 0x00000003) ? ((_SizeInByte_U32 | 0x00000003) + 1) >> 2 : _SizeInByte_U32 >> 2; - SizeInDword_U32 = _SizeInByte_U32 >> 2; - for (i_U32 = 0; i_U32 < SizeInDword_U32; i_U32++) - { - pDst_U32[i_U32] = pSrc_U32[i_U32]; - } - Rts_B = true; - } - return Rts_B; -} +#if defined(_WIN32) + /* + * GetModuleFileNameEx(process, 0, buffer, 256); + * EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) + * GetModuleBaseName(hProcess, 0, buffer, 50); + */ + void *Process_h; + uint32_t ExitCode_U32; -// https://stackoverflow.com/questions/32652833/how-to-allocate-huge-pages-for-c-application-on-linux -// constexpr char MMGW_HUGE_PAGE_PATH[]="/sys/kernel/mm/hugepages/hugepages-2048kB/page_%08X"; //"/var/lib/hugetlbfs/global/pagesize-2MB/page_%08X"; -constexpr char BOF_HUGE_PAGE_PATH[] = "/tmp/hugepages/page_%08X"; -constexpr uint32_t BOF_HUGE_PAGE_SIZE = 2 * 1024 * 1024; -//_OsAdvice_i mainly for MADV_DONTFORK option in madvise -BOFERR Bof_AlignedMemAlloc(BOF_BUFFER_ALLOCATE_ZONE _AllocateZone_E, uint32_t _AligmentInByte_U32, uint32_t _SizeInByte_U32, bool _LockIt_B, int _OsAdvice_i, bool _ClearIt_B, BOF_BUFFER &_rAllocatedBuffer_X) //, uint32_t _Offset_U32) -{ - BOFERR Rts_E = BOF_ERR_EINVAL; - BOF_BUFFER_ALLOCATE_HEADER AllocateBuffer_X; - static std::atomic S_HugePageId(0); + Process_h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, _Pid_U32); - _rAllocatedBuffer_X.Reset(); - if (Bof_IsAPowerOf2(_AligmentInByte_U32)) + if (Process_h) { - Rts_E = BOF_ERR_ENOMEM; - - _rAllocatedBuffer_X.Deleter_E = BOF_BUFFER_DELETER_ALIGNED_FREE; - _rAllocatedBuffer_X.Capacity_U64 = _SizeInByte_U32; - _rAllocatedBuffer_X.Size_U64 = 0; - _rAllocatedBuffer_X.pData_U8 = nullptr; - AllocateBuffer_X.AllocateZone_E = _AllocateZone_E; - switch (_AllocateZone_E) - { - default: - case BOF_BUFFER_ALLOCATE_ZONE::BOF_BUFFER_ALLOCATE_ZONE_RAM: -#if defined(_WIN32) - _rAllocatedBuffer_X.pData_U8 = reinterpret_cast(_aligned_malloc(_SizeInByte_U32, _AligmentInByte_U32)); // malloc(size); // TODO pChannel->getBoard()->getNUMANode() !!! -#else - _rAllocatedBuffer_X.pData_U8 = reinterpret_cast(aligned_alloc(_AligmentInByte_U32, _SizeInByte_U32)); // malloc(size); // TODO pChannel->getBoard()->getNUMANode() !!! -#endif - break; - - /* - * On a NUMA platform, the kernel will attempt to distribute the huge page pool - over all the set of allowed nodes specified by the NUMA memory policy of the - task that modifies nr_hugepages. https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt - */ - case BOF_BUFFER_ALLOCATE_ZONE::BOF_BUFFER_ALLOCATE_ZONE_HUGE_PAGE: -#if defined(_WIN32) -#else - void *pBuffer; + GetExitCodeProcess(Process_h, (DWORD *)&ExitCode_U32); - S_HugePageId++; - snprintf(AllocateBuffer_X.pHugePath_c, sizeof(AllocateBuffer_X.pHugePath_c), BOF_HUGE_PAGE_PATH, S_HugePageId.load()); - AllocateBuffer_X.Io_i = open(AllocateBuffer_X.pHugePath_c, O_CREAT | O_RDWR, 0755); - if (AllocateBuffer_X.Io_i >= 0) - { - // BOFERR Bof_OpenSharedMemory(const std::string &_rName_S, uint32_t _SizeInByte_U32, BOF_SHARED_MEMORY &_rSharedMemory_X) - pBuffer = ::mmap(0, _SizeInByte_U32 < BOF_HUGE_PAGE_SIZE ? BOF_HUGE_PAGE_SIZE : _SizeInByte_U32, PROT_READ | PROT_WRITE, MAP_SHARED, AllocateBuffer_X.Io_i, 0); - if (pBuffer == MAP_FAILED) - { - ::close(AllocateBuffer_X.Io_i); - unlink(AllocateBuffer_X.pHugePath_c); - } - else - { - _rAllocatedBuffer_X.pData_U8 = reinterpret_cast(pBuffer); - } - } -#endif - break; - } - if (_rAllocatedBuffer_X.pData_U8) + if (ExitCode_U32 == STILL_ACTIVE) { - _rAllocatedBuffer_X.pUser = new BOF_BUFFER_ALLOCATE_HEADER; - if (_rAllocatedBuffer_X.pUser) - { - Rts_E = BOF_ERR_NO_ERROR; - *reinterpret_cast(_rAllocatedBuffer_X.pUser) = AllocateBuffer_X; - if (_LockIt_B) - { - Rts_E = Bof_LockMem(_OsAdvice_i, _SizeInByte_U32, _rAllocatedBuffer_X.pData_U8); - if (Rts_E != BOF_ERR_NO_ERROR) - { - Bof_AlignedMemFree(_rAllocatedBuffer_X); - } - } - else - { -#if defined(_WIN32) -#else - if (_OsAdvice_i) - { - Rts_E = (madvise(_rAllocatedBuffer_X.pData_U8, _SizeInByte_U32, _OsAdvice_i) == 0) ? BOF_ERR_NO_ERROR : BOF_ERR_SET; - } -#endif - } - if (Rts_E == BOF_ERR_NO_ERROR) - { - if (_ClearIt_B) - { - memset(_rAllocatedBuffer_X.pData_U8, 0, _SizeInByte_U32); - } - } + Rts_B = true; + } + CloseHandle(Process_h); + } +#else + /* + * In Linux, use the kill subroutine to send the signal specified by the Signal parameter to the process specified by the Process + * parameter (processId). The Signal parameter is a null value, the error checking is performed, but no signal is sent. + */ + if ((kill(_Pid_U32, 0) == -1) && (errno == ESRCH) // No process can be found corresponding to processId + ) + { } else { - _rAllocatedBuffer_X.Deleter_E = BOF_BUFFER_DELETER_NONE; - _rAllocatedBuffer_X.pUser = &AllocateBuffer_X; - Bof_AlignedMemFree(_rAllocatedBuffer_X); + Rts_B = true; } - } - } - // printf("=======> alloc Zone %d Must %d handle %x:%p data %x:%p\n",AllocateBuffer_X.AllocateZone_E, _rAllocatedBuffer_X.MustBeDeleted_B, sizeof(BOF_BUFFER_ALLOCATE_HEADER), _rAllocatedBuffer_X.pUser, _SizeInByte_U32, _rAllocatedBuffer_X.pData_U8); - return Rts_E; +#endif + return Rts_B; } -BOFERR Bof_AlignedMemFree(BOF_BUFFER &_rBuffer_X) +uint32_t Bof_GetCurrentPid() { - BOF_BUFFER_ALLOCATE_HEADER *pAllocateBuffer_X; - BOFERR Rts_E = BOF_ERR_EINVAL; + uint32_t Rts_U32; - pAllocateBuffer_X = reinterpret_cast(_rBuffer_X.pUser); - if (pAllocateBuffer_X) - { - Rts_E = BOF_ERR_NO_ERROR; - if (pAllocateBuffer_X->Locked_B) - { - Rts_E = Bof_UnlockMem(_rBuffer_X.Capacity_U64, _rBuffer_X.pData_U8); - } - switch (pAllocateBuffer_X->AllocateZone_E) - { - default: - case BOF_BUFFER_ALLOCATE_ZONE::BOF_BUFFER_ALLOCATE_ZONE_RAM: #if defined(_WIN32) - _aligned_free(_rBuffer_X.pData_U8); - // VirtualFree(_rBuffer_X.pData_U8, _rBuffer_X.Capacity_U64, MEM_RELEASE); + Rts_U32 = GetCurrentProcessId(); #else - free(_rBuffer_X.pData_U8); + Rts_U32 = getpid(); #endif - break; + return Rts_U32; +} + +BOFERR Bof_Exec(const std::string &_rCommand_S, std::string *_pCapturedOutput_S, int32_t &_rExitCode_S32) +{ + BOFERR Rts_E = BOF_ERR_CANNOT_START; + FILE *pPipeOut_X; + char pData_c[4096]; + std::string Command_S, CapturedOutput_S; + + _rExitCode_S32 = -1; + Command_S = Bof_Sprintf("%s 2>&1", _rCommand_S.c_str()); - case BOF_BUFFER_ALLOCATE_ZONE::BOF_BUFFER_ALLOCATE_ZONE_HUGE_PAGE: #if defined(_WIN32) + pPipeOut_X = _popen(Command_S.c_str(), "r"); #else - ::munmap(_rBuffer_X.pData_U8, _rBuffer_X.Size_U64); - ::close(pAllocateBuffer_X->Io_i); - unlink(pAllocateBuffer_X->pHugePath_c); + pPipeOut_X = popen(Command_S.c_str(), "r"); #endif - break; + if (pPipeOut_X) + { + while (fgets(pData_c, sizeof(pData_c), pPipeOut_X) != nullptr) + { + if (_pCapturedOutput_S) + { + CapturedOutput_S += pData_c; + } } - // printf("=======> DELETE Zone %d Must %d handle %x:%p data %lx:%p\n",pAllocateBuffer_X->AllocateZone_E, _rBuffer_X.MustBeDeleted_B, sizeof(BOF_BUFFER_ALLOCATE_HEADER), _rBuffer_X.pUser, _rBuffer_X.SizeInByte_U64, _rBuffer_X.pData_U8); - - _rBuffer_X.Deleter_E = BOF_BUFFER_DELETER_NONE; // Done by free or _aligned_free - BOF_SAFE_DELETE(pAllocateBuffer_X); - _rBuffer_X.Reset(); + Rts_E = BOF_ERR_NO_ERROR; + if (_pCapturedOutput_S) + { + *_pCapturedOutput_S = CapturedOutput_S; + } +#if defined(_WIN32) + _rExitCode_S32 = _pclose(pPipeOut_X); +#else + _rExitCode_S32 = pclose(pPipeOut_X); +#endif + _rExitCode_S32 = _rExitCode_S32 / 256; // Exit code is in upper bits } - return Rts_E; + + return (Rts_E); } -std::string Bof_DumpMemoryZone(const BOF_DUMP_MEMORY_ZONE_PARAM &_rDumpMemoryZoneParam_X) +const char *Bof_GetEnvVar(const char *_pName_c) { - const uint32_t MAX_NBBYTEPERLINE = 1024; - uint32_t i_U32, j_U32, IndexInMemoryZone_U32, NbBytePerRead_U32, MemoryZoneSizeInByte_U32, NbItemBytePerLine_U32; - int32_t Remain_S32; - uint8_t Data_U8, pData_U8[8]; - const volatile uint8_t *pMemoryZone_U8; - char *pBinaryData_c, pBinary_c[2 + 8 + 1 + (MAX_NBBYTEPERLINE * 5) + MAX_NBBYTEPERLINE + 2 + 1], pAscii_c[MAX_NBBYTEPERLINE + 1]; // 2: 0x 1: Separator 5: 0x%2Separator - std::string Rts_S = ""; - uint64_t VirtualOffset_S64; - volatile const uint64_t *pDataVal_U64; - volatile uint64_t *pDataPtr_U64; - volatile const uint32_t *pDataVal_U32; - volatile uint32_t *pDataPtr_U32; - volatile const uint16_t *pDataVal_U16; - volatile uint16_t *pDataPtr_U16; + const char *pRts_c = nullptr; - if ((_rDumpMemoryZoneParam_X.pMemoryZone) && (_rDumpMemoryZoneParam_X.Separator_c != 0)) + if (_pName_c) { - pMemoryZone_U8 = reinterpret_cast(_rDumpMemoryZoneParam_X.pMemoryZone); - if ((_rDumpMemoryZoneParam_X.GenerateVirtualOffset) || (_rDumpMemoryZoneParam_X.GenerateBinaryData_B) || (_rDumpMemoryZoneParam_X.GenerateAsciiData_B)) - { - IndexInMemoryZone_U32 = 0; - VirtualOffset_S64 = (_rDumpMemoryZoneParam_X.VirtualOffset_S64 == -1) ? reinterpret_cast(_rDumpMemoryZoneParam_X.pMemoryZone) : _rDumpMemoryZoneParam_X.VirtualOffset_S64; - switch (_rDumpMemoryZoneParam_X.AccessSize_E) - { - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_64: - NbBytePerRead_U32 = 8; - MemoryZoneSizeInByte_U32 = (_rDumpMemoryZoneParam_X.NbItemToDump_U32 * NbBytePerRead_U32); - Remain_S32 = static_cast(MemoryZoneSizeInByte_U32) & 0xFFFFFFF8; - break; - - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_32: - NbBytePerRead_U32 = 4; - MemoryZoneSizeInByte_U32 = (_rDumpMemoryZoneParam_X.NbItemToDump_U32 * NbBytePerRead_U32); - Remain_S32 = static_cast(MemoryZoneSizeInByte_U32) & 0xFFFFFFFC; - break; - - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_16: - NbBytePerRead_U32 = 2; - MemoryZoneSizeInByte_U32 = (_rDumpMemoryZoneParam_X.NbItemToDump_U32 * NbBytePerRead_U32); - Remain_S32 = static_cast(MemoryZoneSizeInByte_U32) & 0xFFFFFFFE; - break; - - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_8: - default: - NbBytePerRead_U32 = 1; - MemoryZoneSizeInByte_U32 = (_rDumpMemoryZoneParam_X.NbItemToDump_U32 * NbBytePerRead_U32); - Remain_S32 = static_cast(MemoryZoneSizeInByte_U32) & 0xFFFFFFFF; - break; - } - if (_rDumpMemoryZoneParam_X.NbItemPerLine_U32 <= (MAX_NBBYTEPERLINE / NbBytePerRead_U32)) - { - while (Remain_S32 > 0) - { - pBinaryData_c = pBinary_c; - if (_rDumpMemoryZoneParam_X.GenerateVirtualOffset) - { - if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) - { - if (VirtualOffset_S64 > 0xFFFFFFFF) - { - pBinaryData_c += sprintf(pBinaryData_c, "0x%016" PRIX64 "%c%c%c", VirtualOffset_S64, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c); - } - else - { - pBinaryData_c += sprintf(pBinaryData_c, "0x%08X%c%c%c", static_cast(VirtualOffset_S64), _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c); - } - } - else - { - if (VirtualOffset_S64 > 0xFFFFFFFF) - { - pBinaryData_c += sprintf(pBinaryData_c, "%016" PRIX64 "%c%c%c", VirtualOffset_S64, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c); - } - else - { - pBinaryData_c += sprintf(pBinaryData_c, "%08X%c%c%c", static_cast(VirtualOffset_S64), _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c, _rDumpMemoryZoneParam_X.Separator_c); - } - } - } - - NbItemBytePerLine_U32 = _rDumpMemoryZoneParam_X.NbItemPerLine_U32 * NbBytePerRead_U32; - for (i_U32 = 0; i_U32 < NbItemBytePerLine_U32; i_U32 += NbBytePerRead_U32) - { - if (IndexInMemoryZone_U32 >= MemoryZoneSizeInByte_U32) - { - if (_rDumpMemoryZoneParam_X.GenerateBinaryData_B) - { - switch (_rDumpMemoryZoneParam_X.AccessSize_E) - { - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_64: - if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) - { - pBinaryData_c += sprintf(pBinaryData_c, " "); - } - else - { - pBinaryData_c += sprintf(pBinaryData_c, " "); - } - break; - - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_32: - if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) - { - pBinaryData_c += sprintf(pBinaryData_c, " "); - } - else - { - pBinaryData_c += sprintf(pBinaryData_c, " "); - } - break; + pRts_c = getenv(_pName_c); + } + return (pRts_c); +} - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_16: - if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) - { - pBinaryData_c += sprintf(pBinaryData_c, " "); - } - else - { - pBinaryData_c += sprintf(pBinaryData_c, " "); - } - break; +int Bof_SetEnvVar(const char *_pName_c, const char *_pValue_c, int _Overwrite_i) +{ + int Rts_i = -1; - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_8: - default: - if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) - { - pBinaryData_c += sprintf(pBinaryData_c, " "); - } - else - { - pBinaryData_c += sprintf(pBinaryData_c, " "); - } - break; - } - } - if (_rDumpMemoryZoneParam_X.GenerateAsciiData_B) - { - for (j_U32 = 0; j_U32 < NbBytePerRead_U32; j_U32++) - { - pAscii_c[i_U32 + j_U32] = ' '; - } - } - } - else - { - if (_rDumpMemoryZoneParam_X.GenerateBinaryData_B) - { - switch (_rDumpMemoryZoneParam_X.AccessSize_E) - { - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_64: - // *(uint64_t *)pData_U8 = *(uint64_t *)(&pMemoryZone_U8[IndexInMemoryZone_U32]); - pDataPtr_U64 = reinterpret_cast(pData_U8); - pDataVal_U64 = reinterpret_cast(&pMemoryZone_U8[IndexInMemoryZone_U32]); - *pDataPtr_U64 = *pDataVal_U64; - if (_rDumpMemoryZoneParam_X.ReverseEndianness_B) - { - BOF_SWAP64PTR(pData_U8); - } + if ((_pName_c) && (_pValue_c)) + { + if (_Overwrite_i) + { + Rts_i = 0; + } + else + { + Rts_i = (Bof_GetEnvVar(_pName_c) != nullptr) ? -2 : 0; + } + if (Rts_i == 0) + { +#if defined(_WIN32) + Rts_i = _putenv_s(_pName_c, _pValue_c); +#else + char pEnv_c[1024]; + snprintf(pEnv_c, sizeof(pEnv_c), "%s=%s", _pName_c, _pValue_c); + Rts_i = putenv(pEnv_c); +#endif + } + } + return (Rts_i); +} - if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) - { - pBinaryData_c += sprintf(pBinaryData_c, "0x%016" PRIX64 "%c", *pDataPtr_U64, _rDumpMemoryZoneParam_X.Separator_c); - } - else - { - pBinaryData_c += sprintf(pBinaryData_c, "%016" PRIX64 "%c", *pDataPtr_U64, _rDumpMemoryZoneParam_X.Separator_c); - } +// Min and Max value are include +int32_t Bof_Random(bool _Reset_B, int32_t _MinValue_S32, int32_t _MaxValue_S32) +{ + int32_t Rts_S32, Range_S32; - break; + if (_Reset_B) + { + S_RandomGenerator.seed(std::random_device{}()); + } + if (_MinValue_S32 > _MaxValue_S32) + { + std::swap(_MinValue_S32, _MaxValue_S32); + } + Range_S32 = _MaxValue_S32 - _MinValue_S32 + 1; - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_32: - // *(uint32_t *)pData_U8 = *(uint32_t *)(&pMemoryZone_U8[IndexInMemoryZone_U32]); - pDataPtr_U32 = reinterpret_cast(pData_U8); - pDataVal_U32 = reinterpret_cast(&pMemoryZone_U8[IndexInMemoryZone_U32]); - *pDataPtr_U32 = *pDataVal_U32; + Rts_S32 = _MinValue_S32 + static_cast(S_RandomFloatDistribution(S_RandomGenerator) * static_cast(Range_S32)); - if (_rDumpMemoryZoneParam_X.ReverseEndianness_B) - { - BOF_SWAP32PTR(pData_U8); - } - if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) - { - pBinaryData_c += sprintf(pBinaryData_c, "0x%08X%c", *pDataPtr_U32, _rDumpMemoryZoneParam_X.Separator_c); - } - else - { - pBinaryData_c += sprintf(pBinaryData_c, "%08X%c", *pDataPtr_U32, _rDumpMemoryZoneParam_X.Separator_c); - } - break; + return Rts_S32; +} - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_16: - // *(uint16_t *)pData_U8 = *(uint16_t *)(&pMemoryZone_U8[IndexInMemoryZone_U32]); - pDataPtr_U16 = reinterpret_cast(pData_U8); - pDataVal_U16 = reinterpret_cast(&pMemoryZone_U8[IndexInMemoryZone_U32]); - *pDataPtr_U16 = *pDataVal_U16; +std::string Bof_Random(bool _Reset_B, uint32_t _Size_U32, char _MinValue_c, char _MaxValue_c) +{ + std::string Rts_S; + uint32_t i_U32; - if (_rDumpMemoryZoneParam_X.ReverseEndianness_B) - { - BOF_SWAP16PTR(pData_U8); - } - if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) - { - pBinaryData_c += sprintf(pBinaryData_c, "0x%04X%c", *pDataPtr_U16, _rDumpMemoryZoneParam_X.Separator_c); - } - else - { - pBinaryData_c += sprintf(pBinaryData_c, "%04X%c", *pDataPtr_U16, _rDumpMemoryZoneParam_X.Separator_c); - } - break; + for (i_U32 = 0; i_U32 < _Size_U32; i_U32++) + { + Rts_S += static_cast(Bof_Random(_Reset_B, _MinValue_c, _MaxValue_c)); + } + return Rts_S; +} - case BOF_ACCESS_SIZE::BOF_ACCESS_SIZE_8: - default: - pData_U8[0] = pMemoryZone_U8[IndexInMemoryZone_U32 + 0]; - if (_rDumpMemoryZoneParam_X.ShowHexaPrefix_B) - { - pBinaryData_c += sprintf(pBinaryData_c, "0x%02X%c", *pData_U8, _rDumpMemoryZoneParam_X.Separator_c); - } - else - { - pBinaryData_c += sprintf(pBinaryData_c, "%02X%c", *pData_U8, _rDumpMemoryZoneParam_X.Separator_c); - } - break; - } - } - if (_rDumpMemoryZoneParam_X.GenerateAsciiData_B) - { - for (j_U32 = 0; j_U32 < NbBytePerRead_U32; j_U32++) - { - Data_U8 = pMemoryZone_U8[IndexInMemoryZone_U32 + j_U32]; - pAscii_c[i_U32 + j_U32] = ((Data_U8 < 32) || (Data_U8 > 127)) ? '?' : Data_U8; - } - } - IndexInMemoryZone_U32 += NbBytePerRead_U32; - Remain_S32 -= NbBytePerRead_U32; - } // else if (IndexInMemoryZone_U32 >= _MemoryZoneSizeInByte_U32) - } // for (i_U32 = 0; i_U32 < _NbDataPerLine_U32; i_U32++) - if (_rDumpMemoryZoneParam_X.GenerateBinaryData_B) - { - Rts_S += pBinary_c; - } - if (_rDumpMemoryZoneParam_X.GenerateAsciiData_B) - { - pAscii_c[NbItemBytePerLine_U32] = 0; - Rts_S += pAscii_c; - } - Rts_S += '\n'; // same for linux and windows Bof_Eol(); - VirtualOffset_S64 += NbItemBytePerLine_U32; - } // while (Remain_S32 > 0) - } - } // if ((_GenerateVirtualOffset) || (_GenerateBinaryData_B) || (_GenerateAsciiData_B)) - } // if ((_pMemoryZone_U8) && (_NbDataPerLine_U32 <= MAX_NBBYTEPERLINE) && (_Separator_c != 0)) - // printf("%s", Rts_S.c_str()); +std::string Bof_RandomHexa(bool _Reset_B, uint32_t _Size_U32, bool _Upper_B) +{ + std::string Rts_S; + uint32_t i_U32; + int32_t Val_S32; + std::stringstream Ss; + + if (_Upper_B) + { + for (i_U32 = 0; i_U32 < _Size_U32; i_U32++) + { + Val_S32 = Bof_Random(_Reset_B, 0, 255); + Ss << std::setfill('0') << std::setw(2) << std::uppercase << std::hex << Val_S32; + } + } + else + { + for (i_U32 = 0; i_U32 < _Size_U32; i_U32++) + { + Val_S32 = Bof_Random(_Reset_B, 0, 255); + Ss << std::setfill('0') << std::setw(2) << std::nouppercase << std::hex << Val_S32; + } + } + Rts_S = Ss.str(); return Rts_S; } +BOFERR Bof_ReEvaluateTimeout(uint32_t _Start_U32, uint32_t &_rNewTimeOut_U32) +{ + BOFERR Rts_E = BOF_ERR_NO_ERROR; + uint32_t Delta_U32; + + Delta_U32 = Bof_ElapsedMsTime(_Start_U32); + if (Delta_U32 >= _rNewTimeOut_U32) + { + Rts_E = BOF_ERR_ETIMEDOUT; + _rNewTimeOut_U32 = 0; + } + else + { + _rNewTimeOut_U32 -= Delta_U32; + } + + return Rts_E; +} + void Bof_MsSleep(uint32_t _Ms_U32) { if (_Ms_U32 == 0) @@ -3328,6 +3062,7 @@ void Bof_MsSleep(uint32_t _Ms_U32) #endif } } + void Bof_UsSleep(uint32_t _Us_U32) { if (_Us_U32 == 0) @@ -3352,6 +3087,7 @@ uint32_t Bof_GetMsTickCount() uint64_t NbMs_U64 = std::chrono::steady_clock::now().time_since_epoch() / std::chrono::milliseconds(1); return static_cast(NbMs_U64); } + // change if system time/date change uint64_t Bof_GetUsTickCount() { @@ -3365,6 +3101,7 @@ uint64_t Bof_GetUsTickCount() return Rts_U64; } + uint64_t Bof_GetNsTickCount() { uint64_t Rts_U64; @@ -3396,89 +3133,11 @@ uint64_t Bof_ElapsedNsTime(uint64_t _StartInNs_U64) return Rts_U64; } -BOFERR Bof_ReEvaluateTimeout(uint32_t _Start_U32, uint32_t &_rNewTimeOut_U32) -{ - BOFERR Rts_E = BOF_ERR_NO_ERROR; - uint32_t Delta_U32; - - Delta_U32 = Bof_ElapsedMsTime(_Start_U32); - if (Delta_U32 >= _rNewTimeOut_U32) - { - Rts_E = BOF_ERR_ETIMEDOUT; - _rNewTimeOut_U32 = 0; - } - else - { - _rNewTimeOut_U32 -= Delta_U32; - } - - return Rts_E; -} - bool Bof_IsElapsedTimeInMs(uint32_t _Start_U32, uint32_t _TimeoutInMs_U32) { return (Bof_ElapsedMsTime(_Start_U32) >= _TimeoutInMs_U32); } -// Min and Max value are include -int32_t Bof_Random(bool _Reset_B, int32_t _MinValue_S32, int32_t _MaxValue_S32) -{ - int32_t Rts_S32, Range_S32; - - if (_Reset_B) - { - S_RandomGenerator.seed(std::random_device{}()); - } - if (_MinValue_S32 > _MaxValue_S32) - { - std::swap(_MinValue_S32, _MaxValue_S32); - } - Range_S32 = _MaxValue_S32 - _MinValue_S32 + 1; - - Rts_S32 = _MinValue_S32 + static_cast(S_RandomFloatDistribution(S_RandomGenerator) * static_cast(Range_S32)); - - return Rts_S32; -} - -std::string Bof_Random(bool _Reset_B, uint32_t _Size_U32, char _MinValue_c, char _MaxValue_c) -{ - std::string Rts_S; - uint32_t i_U32; - - for (i_U32 = 0; i_U32 < _Size_U32; i_U32++) - { - Rts_S += static_cast(Bof_Random(_Reset_B, _MinValue_c, _MaxValue_c)); - } - return Rts_S; -} - -std::string Bof_RandomHexa(bool _Reset_B, uint32_t _Size_U32, bool _Upper_B) -{ - std::string Rts_S; - uint32_t i_U32; - int32_t Val_S32; - std::stringstream Ss; - - if (_Upper_B) - { - for (i_U32 = 0; i_U32 < _Size_U32; i_U32++) - { - Val_S32 = Bof_Random(_Reset_B, 0, 255); - Ss << std::setfill('0') << std::setw(2) << std::uppercase << std::hex << Val_S32; - } - } - else - { - for (i_U32 = 0; i_U32 < _Size_U32; i_U32++) - { - Val_S32 = Bof_Random(_Reset_B, 0, 255); - Ss << std::setfill('0') << std::setw(2) << std::nouppercase << std::hex << Val_S32; - } - } - Rts_S = Ss.str(); - return Rts_S; -} - BOFERR Bof_SystemUsageInfo(const char *_pDiskName_c, BOF_SYSTEM_USAGE_INFO &_rSystemUsageInfo_X) { BOFERR Rts_E = BOF_ERR_EINVAL; diff --git a/lib/src/bofthreadapi.cpp b/oldies/bofthreadapi.cpp similarity index 100% rename from lib/src/bofthreadapi.cpp rename to oldies/bofthreadapi.cpp diff --git a/lib/include/bofstd/bofthreadapi.h b/oldies/bofthreadapi.h similarity index 100% rename from lib/include/bofstd/bofthreadapi.h rename to oldies/bofthreadapi.h diff --git a/lib/src/bofthreadgeneric.cpp b/oldies/bofthreadgeneric.cpp similarity index 100% rename from lib/src/bofthreadgeneric.cpp rename to oldies/bofthreadgeneric.cpp diff --git a/lib/include/bofstd/bofthreadgeneric.h b/oldies/bofthreadgeneric.h similarity index 100% rename from lib/include/bofstd/bofthreadgeneric.h rename to oldies/bofthreadgeneric.h diff --git a/tests/src/main.cpp b/tests/src/main.cpp index 0948cd15..4ec1cbe7 100644 --- a/tests/src/main.cpp +++ b/tests/src/main.cpp @@ -126,6 +126,7 @@ int main(int argc, char *argv[]) //::testing::GTEST_FLAG(filter) = "DateTime_Test.StringDateTime:SocketTcp_Test.TcpClientTest:DateTime_Test.ValidateDateTime:SocketOs_Test.SocketAddress"; // ::testing::GTEST_FLAG(filter) = "Logger_Test.*:ut_logger_ibofloggerfactory.*"; // ::testing::GTEST_FLAG(filter) = "ut_logger_ibofloggerfactory.*"; + //::testing::GTEST_FLAG(filter) = "BofThread_Test.*:Threading_Test.*"; // ::testing::GTEST_FLAG(filter) = "ut_spsc.*:ut_mpmc.*:CircularBuffer_Test.Perf"; //::testing::GTEST_FLAG(filter) = "CircularBuffer_Test.PerfThread"; diff --git a/tests/src/ut_system.cpp b/tests/src/ut_system.cpp index 6d2808d4..04812e23 100644 --- a/tests/src/ut_system.cpp +++ b/tests/src/ut_system.cpp @@ -457,8 +457,8 @@ TEST(System_Test, NanoTickCount) Start_U64 = Bof_GetNsTickCount(); Bof_MsSleep(BOF_S_TO_MS(1)); Delta_U64 = Bof_ElapsedNsTime(Start_U64); - EXPECT_GE(Delta_U64, BOF_S_TO_NANO(1)); - EXPECT_LT(Delta_U64, BOF_S_TO_NANO(1) * 1.1); + EXPECT_GE(Delta_U64, BOF_S_TO_NS(1)); + EXPECT_LT(Delta_U64, BOF_S_TO_NS(1) * 1.1); } TEST(System_Test, MsTickCount)