Make the pagemap global typed.
The pagemap global is now an inline static of a template class, so that we will see different symbols for the different types. Issue #84 showed that it's possible to compile two compilation units with different pagemaps, link them together, and have them attempt to interpret the global pagemap as two different types. This change should make that impossible. Also make the `pagemap()` function static so that it can be used from static functions, avoiding other things that directly reference the global pagemap.
This commit is contained in:
committed by
David Chisnall
parent
2efa4b14fb
commit
d2dc653af2
@@ -55,24 +55,40 @@ namespace snmalloc
|
||||
FlatPagemap<SUPERSLAB_BITS, uint8_t>,
|
||||
Pagemap<SUPERSLAB_BITS, uint8_t, 0>>;
|
||||
|
||||
HEADER_GLOBAL SuperslabPagemap global_pagemap;
|
||||
|
||||
/**
|
||||
* Mixin used by `SuperslabMap` to directly access the pagemap via a global
|
||||
* variable. This should be used from within the library or program that
|
||||
* owns the pagemap.
|
||||
*
|
||||
* This class makes the global pagemap a static field so that its name
|
||||
* includes the type mangling. If two compilation units try to instantiate
|
||||
* two different types of pagemap then they will see two distinct pagemaps.
|
||||
* This will prevent allocating with one and freeing with the other (because
|
||||
* the memory will show up as not owned by any allocator in the other
|
||||
* compilation unit) but will prevent the same memory being interpreted as
|
||||
* having two different types.
|
||||
*/
|
||||
struct GlobalPagemap
|
||||
template<typename T>
|
||||
class GlobalPagemapTemplate
|
||||
{
|
||||
/**
|
||||
* The global pagemap variable. The name of this symbol will include the
|
||||
* type of `T`.
|
||||
*/
|
||||
inline static T global_pagemap;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the pagemap.
|
||||
*/
|
||||
SuperslabPagemap& pagemap()
|
||||
static SuperslabPagemap& pagemap()
|
||||
{
|
||||
return global_pagemap;
|
||||
}
|
||||
};
|
||||
|
||||
using GlobalPagemap = GlobalPagemapTemplate<SuperslabPagemap>;
|
||||
|
||||
/**
|
||||
* Optionally exported function that accesses the global pagemap provided by
|
||||
* a shared library.
|
||||
@@ -91,7 +107,7 @@ namespace snmalloc
|
||||
/**
|
||||
* A pointer to the pagemap.
|
||||
*/
|
||||
SuperslabPagemap* external_pagemap;
|
||||
inline static SuperslabPagemap* external_pagemap;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -110,7 +126,7 @@ namespace snmalloc
|
||||
/**
|
||||
* Returns the exported pagemap.
|
||||
*/
|
||||
SuperslabPagemap& pagemap()
|
||||
static SuperslabPagemap& pagemap()
|
||||
{
|
||||
return *external_pagemap;
|
||||
}
|
||||
@@ -531,7 +547,7 @@ namespace snmalloc
|
||||
error("Unsupported");
|
||||
UNUSED(p);
|
||||
#else
|
||||
uint8_t size = global_pagemap.get(address_cast(p));
|
||||
uint8_t size = PageMap::pagemap().get(address_cast(p));
|
||||
|
||||
Superslab* super = Superslab::get(p);
|
||||
if (size == PMSuperslab)
|
||||
@@ -561,7 +577,7 @@ namespace snmalloc
|
||||
{
|
||||
// This is a large alloc redirect.
|
||||
ss = ss - (1ULL << (size - 64));
|
||||
size = global_pagemap.get(ss);
|
||||
size = PageMap::pagemap().get(ss);
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
@@ -593,7 +609,7 @@ namespace snmalloc
|
||||
static size_t alloc_size(void* p)
|
||||
{
|
||||
// This must be called on an external pointer.
|
||||
size_t size = global_pagemap.get(address_cast(p));
|
||||
size_t size = PageMap::pagemap().get(address_cast(p));
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
|
||||
@@ -210,14 +210,13 @@ extern "C"
|
||||
SNMALLOC_EXPORT void* SNMALLOC_NAME_MANGLE(snmalloc_pagemap_global_get)(
|
||||
PagemapConfig const** config)
|
||||
{
|
||||
auto& pm = GlobalPagemap::pagemap();
|
||||
if (config)
|
||||
{
|
||||
*config = &decltype(snmalloc::global_pagemap)::config;
|
||||
assert(
|
||||
decltype(snmalloc::global_pagemap)::cast_to_pagemap(
|
||||
&snmalloc::global_pagemap, *config) == &snmalloc::global_pagemap);
|
||||
*config = &SuperslabPagemap::config;
|
||||
assert(SuperslabPagemap::cast_to_pagemap(&pm, *config) == &pm);
|
||||
}
|
||||
return &snmalloc::global_pagemap;
|
||||
return ±
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user