//////////////////////////////////////////////////////////////////// // // To achieve determinism of replay logs, the driver is not allowed // to touch the malloc heap. We've given the driver its own // separate heap. The driver's heap is accessed using umm_malloc, // umm_free, and umm_realloc. // // To initialize the umm heap, you allocate a single large // block of RAM from the OS, perhaps 4M. You pass that block // to umm_heap_init. The umm_malloc routine will allocate out of // that block. The umm heap cannot grow, if the block fills up, umm_malloc // will fail. It is fine to get the initial heap block from the // regular system malloc! That doesn't compromise determinism, // since you're always allocating the same 4M block. // // The UMM malloc library is distributed under the MIT license // by Ralph Hempel. This is a slightly-modified version, you can // find the original online. Mr. Hempel considers this to be a malloc // for microcontrollers, but it works just fine on workstations. // Of all the mallocs to choose from, I picked this one because it // satisfies three main criteria: it works out of a fixed block // of RAM, it's not terribly inefficient, and it's not too complicated // to modify. // // Warning! Don't forget that using the C++ STL tends to use malloc // all over the place. For example, if you create a std::string, // you're using malloc! Don't use normal STL classes in the driver! // Fortunately, most STL classes allow you to specify a custom // allocator class. The following classes use the UMM allocator: // // UmmString - same as std::string. // UmmVector - same as std::vector. // UmmMap - same as std::map // UmmSet - same as std::set // // Sadly, routines that accept std::string, std::vector, std::map, // or std::set do not accept their Umm equivalents. It is possible // to write a routine that accepts both std::string and UmmString // by accepting a std::string_view parameter. Other than that, // these types are separate. // //////////////////////////////////////////////////////////////////// #ifndef UMM_MALLOC_HPP #define UMM_MALLOC_HPP #include #include #include #include #include #include #include void umm_init_heap(void *ptr, size_t size); void *umm_malloc(size_t size); void *umm_realloc(void *ptr, size_t size); void umm_free(void *ptr); void umm_info(); void *umm_malloc_ssl(size_t size, const char *file, int line); void *umm_realloc_ssl(void *ptr, size_t size, const char *file, int line); void umm_free_ssl(void *ptr, const char *file, int line); template class UmmAllocator { public: using value_type = T; UmmAllocator() noexcept {} template UmmAllocator(UmmAllocator const&) noexcept {} value_type* allocate(std::size_t n) { return static_cast(umm_malloc(n*sizeof(value_type))); } void deallocate(value_type* p, std::size_t) noexcept { umm_free(p); } }; template bool operator==(UmmAllocator const&, UmmAllocator const&) noexcept { return true; } template bool operator!=(UmmAllocator const&, UmmAllocator const&) noexcept { return false; } using UmmString = std::basic_string, UmmAllocator>; template using UmmVector = std::vector>; template > using UmmMap = std::map>>; template > using UmmSet = std::set>; #endif // UMM_MALLOC_HPP