Lots of work on removing malloc from driver
This commit is contained in:
108
luprex/core/cpp/umm-malloc.hpp
Normal file
108
luprex/core/cpp/umm-malloc.hpp
Normal file
@@ -0,0 +1,108 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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<T> - same as std::vector<T>.
|
||||
// UmmMap<K,V> - same as std::map<K,V>
|
||||
// UmmSet<T> - same as std::set<T>
|
||||
//
|
||||
// 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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
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 T>
|
||||
class UmmAllocator
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
UmmAllocator() noexcept {}
|
||||
template <class U> UmmAllocator(UmmAllocator<U> const&) noexcept {}
|
||||
|
||||
value_type* allocate(std::size_t n)
|
||||
{
|
||||
return static_cast<value_type*>(umm_malloc(n*sizeof(value_type)));
|
||||
}
|
||||
|
||||
void deallocate(value_type* p, std::size_t) noexcept
|
||||
{
|
||||
umm_free(p);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
bool operator==(UmmAllocator<T> const&, UmmAllocator<U> const&) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool operator!=(UmmAllocator<T> const&, UmmAllocator<U> const&) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using UmmString = std::basic_string<char, std::char_traits<char>, UmmAllocator<char>>;
|
||||
|
||||
template <class T>
|
||||
using UmmVector = std::vector<T, UmmAllocator<T>>;
|
||||
|
||||
template <class K, class T, class C=std::less<K>>
|
||||
using UmmMap = std::map<K, T, C, UmmAllocator<std::pair<const K, T>>>;
|
||||
|
||||
template <class K, class C=std::less<K>>
|
||||
using UmmSet = std::set<K, C, UmmAllocator<K>>;
|
||||
|
||||
#endif // UMM_MALLOC_HPP
|
||||
Reference in New Issue
Block a user