/* * (c) Copyright, Real-Time Innovations, 2002-2024. * All rights reserved. * * No duplications, whole or partial, manual or electronic, may be made * without express written permission. Any such copies, or * revisions thereof, must display this notice unaltered. * This code contains trade secrets of Real-Time Innovations, Inc. */ #ifndef osapi_heap_h #define osapi_heap_h #include "osapi/osapi_type.h" #include "osapi/osapi_dll.h" #include "osapi/osapi_alignment.h" #include "osapi/osapi_heapContext.h" #include "osapi/osapi_utility.h" #ifdef __cplusplus extern "C" { #endif /** @internal * @brief Maximum allocation size across platforms * We subtract 1024 because our memory allocation * routines do operations with the allocation size * that can cause it to overflow. */ #define RTI_OSAPI_HEAP_MAX_ALLOC_SIZE (RTI_INT32_MAX - 1024) /** @internal \file * \brief Heap utilities */ /** @internal \defgroup RTIOsapiHeapClass RTIOsapiHeap * \ingroup RTIOsapiModule * * \brief OS-independent way to use the heap (Malloc/Free) * * There are 4 Allocate/Free combinations: to allocate * a C-structure, an array of C-structures, a string and a buffer * of chosen size and alignment. It is important that the * correct allocation and Free method are combined. * All methods initialize the allocated space with 0's. * * Memory allocation statistics are maintained if the API * RTIOsapiHeap_enableMonitoring is called * * The application can get the current statistics calling RTIOsapiHeap_statGet * statistics counter can be reset calling RTIOsapiHeap_statReset. * * While statistic-collection is turned on, the system will allocate a * larger block than it is requested. The extra space is used to store some * extra information such as the size of the block, a blockId, a pointer to * the actual memory, etc. * * Statistics are updated each time a memory Allocation/Free/Reallocation is * performed using any of the RTIOsapiHeap_* functions. */ /** @internal \ingroup RTIOsapiHeap * * @brief Memory Heap usage statistics * * This structure is used to return Heap statistics. The heap statistic count * the incremental memory consumption, number of allocations and number of frees * that have occurred since the statistics were last reset. * * Note that the statistics count the bytes requested (cumulative sum of the * sizes requested on the calls to RTIOsapiHeap_* functions). The bytes actually * consumed will be slightly greater due to the extra bytes to hold the header * information that supports the statistics (about 16 Bytes per block). The * reason for reporting the requested bytes is that this number will match the * actual allocated bytes when statistics-collection is turned off which is the * typical case for a deployed system. * * \b Example: * * The following gets the current statistics. * * \verbatim * RTIOsapiHeapStat stat; * * RTIOsapiHeap_statGet(&stat); * \endverbatim * * @see RTIOsapiHeap_statGet RTIOsapiHeap_statReset */ struct RTIOsapiHeapStat { /** @internal current heap used in Bytes. This stat does not * include the additional memory that is added as headers to * each allocation in order to keep track of it for heap * monitoring. That additional overhead is accounted for in the * currentUsageWithHeaders stat. */ RTI_INT64 currentUsage; /** @internal current heap used in Bytes. This stat includes * the memory that is allocated for the headers that are * added to each memory allocation when heap monitoring is * enabled. */ RTI_INT64 currentUsageWithHeaders; /** @internal maximum heap usage in Bytes */ RTI_INT64 highWatermark; /** @internal minimum heap usage in Bytes */ RTI_INT64 lowWatermark; /** @internal number of allocations (Realloc counted as Malloc + Free) */ RTI_INT64 allocCount; /** @internal number of frees (Realloc counted as Malloc + Free) */ RTI_INT64 freeCount; /** @internal the ID that will be assigned to the next allocated block 0 => Statistics are not being gathered 1 => No block have been allocated This value is not affected by a call to RTIOsapiStat_statReset */ RTI_UINT64 nextBlockId; }; #define RTI_OSAPI_HEAP_STAT_DEFAULT \ { \ 0 /* currentUsage */, \ 0 /* currentUsageWithHeaders */, \ 0 /* highWatermark */, \ 0 /* lowWatermark */, \ 0 /* allocCount */, \ 0 /* freeCount */, \ 0 /* nextBlockId */ \ } /** @internal \ingroup RTIOsapiHeap * All the ALLOC RTIOsapiHeapAllocatorKind share the same prefix. * It is used to check if the signature is RTI_OSAPI_*_ALLOC and not * RTI_OSAPI_FREED_BLOCK. */ #define RTI_OSAPI_HEAP_ALLOC_PREFIX 0x4E444440 typedef enum RTIOsapiHeapAllocatorKind { RTI_OSAPI_STRUCT_ALLOC = 0x4E444441, RTI_OSAPI_STRING_ALLOC = 0x4E444442, RTI_OSAPI_ARRAY_ALLOC = 0x4E444443, RTI_OSAPI_BUFFER_ALLOC = 0x4E444444, RTI_OSAPI_BUFFER_ALIGN_ALLOC = 0x4E444445, RTI_OSAPI_MALLOC_ALLOC = 0x4E444446, RTI_OSAPI_FREED_BLOCK = 0x7b9b9b9b } RTIOsapiHeapAllocatorKind; /** @internal \ingroup RTIOsapiHeapClass * \brief Get statistics on the Heap. See documentation on the * struct RTIOsapiHeapStat for a description of the statistics. * * The statistics count the number of bytes and allocations since the * last time RTIOsapiHeap_statReset was called. Therefore statistics * taken right after RTIOsapiHeap_statReset is called and before doing * any allocations or frees will result in all counters (with the exception * of the lastBlockId to be zero. * * The counters currentUsage, lowWatermark, and freeCount can take negative * values if an application frees more memory than it allocates after calling * RTIOsapiHeap_statReset. * * This operation can be called even if heap monitoring was not enabled. * If this is the case all statistic counters will return zero and the * lastBlockId will be -1. * * @param stat \b out. Must point to valid memory. Cannot be NULL * * @see RTIOsapiHeap_statReset */ extern RTIOsapiDllExport void RTIOsapiHeap_statGet( struct RTIOsapiHeapStat *stat); /** @internal \ingroup RTIOsapiHeapClass * \brief Reset all statistics counters. Does not reset the nextBlockId. * * This function resets all the statistics counters with the exception * of the nextBlockId. This is done so that blocks can still get a unique * Id. * * This operation has no effect if heap monitoring is not enabled. * * @see RTIOsapiHeap_statGet */ extern RTIOsapiDllExport void RTIOsapiHeap_statReset(void); /** @internal \ingroup RTIOsapiHeapClass * \brief Get information on a memory block. * * This function only works if heap monitoring is enabled and * can only be used on a block allocated with one of the RTIOsapiHeap_* * functions. If either of this is not true the function will return * RTI_FALSE. * * @see RTIOsapiHeap_statGet */ extern RTIOsapiDllExport RTIBool RTIOsapiHeap_blockInfoGet( const void *address, RTI_UINT64 *blockId, RTI_UINT64 *blockSize); /** @internal \ingroup RTIOsapiHeapClass * \brief Transition function to replace malloc. Should only be used * while refactoring * * This function performs the logical equivalent as a malloc() except that * the Memory Statistics are updated and the memory is initialize to zeros * * This function should only be used temporarily as a convenience while * migrating code that uses malloc(). The correct solution is to use * the proper function that depends on what is allocated, such as * \ref RTIOsapiHeap_allocateStructure */ extern RTIOsapiDllExport void *RTIOsapiHeap_malloc(size_t size); /** @internal \ingroup RTIOsapiHeapClass * @brief Calling RTIOsapiHeap_malloc but forcing not removing Heap Header. * @param size \b In. This is the size of the memory block, in bytes. * @return A pointer to the allocated memory, or NULL if the request fails. */ extern RTIOsapiDllExport void *RTIOsapiHeap_mallocWithoutHeapHeader( size_t size); /** @internal \ingroup RTIOsapiHeapClass * \brief Transition function to replace calloc. Should only be used * while refactoring * * This function performs the logical equivalent as a malloc() except that * the Memory Statistics are updated and the memory is initialize to zeros * * This function should only be used temporarily as a convenience while * migrating code that uses calloc(). The correct solution is to use * the proper function that depends on what is allocated, such as * \ref RTIOsapiHeap_allocateArray or \ref RTIOsapiHeap_allocateBuffer */ extern RTIOsapiDllExport void *RTIOsapiHeap_calloc( size_t numElem, size_t elemSize); /** @internal \ingroup RTIOsapiHeapClass * \brief Transition function to replace realloc. Should only be used * while refactoring * * This function performs the logical equivalent as a realloc() except that * the Memory Statistics are updated and the memory is initialize to zeros * * This function should only be used temporarily as a convenience while * migrating code that uses malloc/calloc. */ extern RTIOsapiDllExport void *RTIOsapiHeap_realloc(void *ptr, size_t size); /** @internal \ingroup RTIOsapiHeapClass * \brief Transition function to replace free. Should only be used * while refactoring * * This function performs the logical equivalent as a free() except that * the Memory Statistics are updated and the memory is initialize to zeros * * This function should only be used temporarily as a convenience while * migrating code that uses malloc/calloc. */ extern RTIOsapiDllExport void RTIOsapiHeap_free(void *ptr); /** @internal \ingroup RTIOsapiHeapClass * @brief Calling RTIOsapiHeap_free but forcing not including Heap Header. * @param ptr \b In. Pointer to a memory block previously allocate. * @param ptr \b In. Size of the memory to be freed. * It is just used to update the variable 'memCurrentIncludingHeaders'. */ extern RTIOsapiDllExport void RTIOsapiHeap_freeWithoutHeapHeader( void *ptr, size_t size); /** @internal \ingroup RTIOsapiHeapClass * Specify the format of the output of the snapshot. */ typedef enum { /* The output of the snapshot will be in plain text */ RTI_OSAPI_HEAP_SNAPSHOT_OUTPUT_FORMAT_STANDARD = 1, /* * The output of the snapshot will be compressed using * Zlib techonology. * The file can be uncompressed using zlib-flate. */ RTI_OSAPI_HEAP_SNAPSHOT_OUTPUT_FORMAT_COMPRESSED = 2, } RTIOsapiHeapSnapshotOutputFormat; /** @internal \ingroup RTIOsapiHeapClass * It is a bitmap to decide which information of the snapshot will be displayed * for the optional fields. */ typedef unsigned int RTIOsapiHeapSnapshotContentBitmap; #define RTI_OSAPI_HEAP_SNAPSHOT_CONTENT_BIT_TOPIC 0x1 #define RTI_OSAPI_HEAP_SNAPSHOT_CONTENT_BIT_FUNCTION 0x2 #define RTI_OSAPI_HEAP_SNAPSHOT_CONTENT_BIT_ACTIVITY 0x4 #define RTI_OSAPI_HEAP_SNAPSHOT_CONTENT_MASK_DEFAULT \ (RTI_OSAPI_HEAP_SNAPSHOT_CONTENT_BIT_TOPIC \ | RTI_OSAPI_HEAP_SNAPSHOT_CONTENT_BIT_FUNCTION \ | RTI_OSAPI_HEAP_SNAPSHOT_CONTENT_BIT_ACTIVITY) #define RTI_OSAPI_HEAP_SNAPSHOT_CONTENT_MINIMAL 0x0 /** @internal \ingroup RTIOsapiHeapClass * Properties for the Heap monitoring feature. * They will be used for configuring the format of the snapshot. */ struct RTIOsapiHeapMonitoringProperty { /* Specify the format of the output of the snapshot. */ RTIOsapiHeapSnapshotOutputFormat outputFormat; /* * It is a bitmap to decide which information of the snapshot will be * displayed. */ RTIOsapiHeapSnapshotContentBitmap contentFormat; }; #define RTIOsapiHeapMonitoringProperty_INITIALIZER \ { \ RTI_OSAPI_HEAP_SNAPSHOT_OUTPUT_FORMAT_STANDARD, /* outputFormat */ \ RTI_OSAPI_HEAP_SNAPSHOT_CONTENT_MASK_DEFAULT /* contentFormat */ \ } /** @internal \ingroup RTIOsapiHeapClass * @brief Initialize the fields of the RTIOsapiHeapMonitoringProperty structure. * @param self \b In. The RTIOsapiHeapMonitoringProperty to initialize. */ extern RTIOsapiDllExport void RTIOsapiHeapMonitoringProperty_initialize( struct RTIOsapiHeapMonitoringProperty *self); /** @internal \ingroup RTIOsapiHeapClass * @brief Copy the fields of src into self. * @param self \b Out. The RTIOsapiHeapMonitoringProperty to be copied. * @param self \b In. The RTIOsapiHeapMonitoringProperty to copy. */ extern RTIOsapiDllExport void RTIOsapiHeapMonitoringProperty_copy( struct RTIOsapiHeapMonitoringProperty *self, const struct RTIOsapiHeapMonitoringProperty *src); /** @internal \ingroup RTIOsapiHeapClass * \brief Disables heap monitoring * This function is not thread safe */ extern RTIOsapiDllExport void RTIOsapiHeap_disableMonitoring(void); /** @internal \ingroup RTIOsapiHeapClass * \brief Enables heap monitoring * This function is not thread safe */ extern RTIOsapiDllExport RTIBool RTIOsapiHeap_enableMonitoring(void); /** @internal \ingroup RTIOsapiHeapClass * @brief Enables heap monitoring. * * @param property \b In. The the properties to enable. * * This function is not thread safe */ extern RTIOsapiDllExport RTIBool RTIOsapiHeap_enableMonitoringWithParams( const struct RTIOsapiHeapMonitoringProperty *property); /** @internal \ingroup RTIOsapiHeapClass * \brief Indicates if monitoring is enabled * This function is thread safe */ extern RTIOsapiDllExport RTIBool RTIOsapiHeap_isMonitoringEnabled(void); /** @internal \ingroup RTIOsapiHeapClass * \brief Pauses the monitoring process. * * This means that statistics will not be gathered for the memory allocated * while monitoring is paused * * This function is thread safe */ extern RTIOsapiDllExport RTIBool RTIOsapiHeap_pauseMonitoring(void); /** @internal \ingroup RTIOsapiHeapClass * \brief Resumes the monitoring process. * * This function is thread safe */ extern RTIOsapiDllExport RTIBool RTIOsapiHeap_resumeMonitoring(void); /** @internal \ingroup RTIOsapiHeapClass * \brief Saves a heap snapshot into a file * * This function is thread safe */ extern RTIOsapiDllExport RTIBool RTIOsapiHeap_snapshot( const char *fileName, RTIBool printDetails, const char *productVersion); #ifdef __cplusplus } /* extern "C" */ #endif #include "osapi/osapi_heap_impl.h" #endif /* osapi_heap_h */