Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
unique_range.cpp
Go to the documentation of this file.
1 #include "precompiled.h"
3 
4 #include "lib/bits.h" // is_pow2, round_up
5 #include "lib/sysdep/cpu.h" // cpu_AtomicAdd
6 #include "lib/sysdep/rtl.h" // rtl_FreeAligned
7 
8 
9 static void FreeNone(void* UNUSED(pointer), size_t UNUSED(size))
10 {
11  // (providing a deleter function for idxDeleterNone avoids
12  // having to check whether deleters[idxDeleter] == 0)
13 }
14 
15 static void FreeAligned(void* pointer, size_t UNUSED(size))
16 {
17  return rtl_FreeAligned(pointer);
18 }
19 
20 
22 
24 
25 
26 // NB: callers should skip this if *idxDeleterOut != 0 (avoids the overhead
27 // of an unnecessary indirect function call)
28 void RegisterUniqueRangeDeleter(UniqueRangeDeleter deleter, volatile IdxDeleter* idxDeleterOut)
29 {
30  ENSURE(deleter);
31 
32  if(!cpu_CAS(idxDeleterOut, idxDeleterNone, -1)) // not the first call for this deleter
33  {
34  // wait until an index has been assigned
35  while(*idxDeleterOut <= 0)
36  cpu_Pause();
37  return;
38  }
39 
40  const IdxDeleter idxDeleter = cpu_AtomicAdd(&numDeleters, 1);
41  ENSURE(idxDeleter < (IdxDeleter)ARRAY_SIZE(deleters));
42  deleters[idxDeleter] = deleter;
44  *idxDeleterOut = idxDeleter;
45 }
46 
47 
48 NOTHROW_DEFINE void CallUniqueRangeDeleter(void* pointer, size_t size, IdxDeleter idxDeleter)
49 {
50  ASSERT(idxDeleter < numDeleters);
51  // (some deleters do not tolerate null pointers)
52  if(pointer)
53  deleters[idxDeleter](pointer, size);
54 }
55 
56 
57 UniqueRange AllocateAligned(size_t size, size_t alignment)
58 {
59  ENSURE(is_pow2(alignment));
60  alignment = std::max(alignment, allocationAlignment);
61 
62  const size_t alignedSize = round_up(size, alignment);
63  const UniqueRange::pointer p = rtl_AllocateAligned(alignedSize, alignment);
64 
65  static volatile IdxDeleter idxDeleterAligned;
66  if(idxDeleterAligned == 0) // (optional optimization)
67  RegisterUniqueRangeDeleter(FreeAligned, &idxDeleterAligned);
68 
69  return RVALUE(UniqueRange(p, size, idxDeleterAligned));
70 }
71 
72 
73 UniqueRange AllocateVM(size_t size, vm::PageType pageType, int prot)
74 {
75  const UniqueRange::pointer p = vm::Allocate(size, pageType, prot);
76 
77  static volatile IdxDeleter idxDeleter;
78  if(idxDeleter == 0) // (optional optimization)
80 
81  return RVALUE(UniqueRange(p, size, idxDeleter));
82 }
#define RVALUE(lvalue)
convert anything (lvalue or rvalue) to an rvalue
void * rtl_AllocateAligned(size_t size, size_t align)
Definition: gcc.cpp:66
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
#define COMPILER_FENCE
prevent the compiler from reordering loads or stores across this point.
intptr_t IdxDeleter
Definition: unique_range.h:21
void(* UniqueRangeDeleter)(void *pointer, size_t size)
Definition: unique_range.h:26
static UniqueRangeDeleter deleters[allocationAlignment]
T round_up(T n, T multiple)
round number up/down to the next given multiple.
Definition: bits.h:265
#define NOTHROW_DEFINE
#define ASSERT(expr)
same as ENSURE in debug mode, does nothing in release mode.
Definition: debug.h:310
intptr_t cpu_AtomicAdd(volatile intptr_t *location, intptr_t increment)
add a signed value to a variable without the possibility of interference from other threads/CPUs...
Definition: arm.cpp:31
#define ARRAY_SIZE(name)
void RegisterUniqueRangeDeleter(UniqueRangeDeleter deleter, volatile IdxDeleter *idxDeleterOut)
register a deleter, returning its index within the table.
NOTHROW_DEFINE void CallUniqueRangeDeleter(void *pointer, size_t size, IdxDeleter idxDeleter)
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
static void FreeAligned(void *pointer, size_t size)
PageType
Definition: vm.h:42
static IdxDeleter numDeleters
static Status AllocateAligned(shared_ptr< T > &p, size_t size, size_t alignment=cacheLineSize)
Definition: shared_ptr.h:66
static const IdxDeleter idxDeleterNone
Definition: unique_range.h:24
static void FreeNone(void *pointer, size_t size)
Definition: unique_range.cpp:9
bool cpu_CAS(volatile intptr_t *location, intptr_t expected, intptr_t newValue)
atomic &quot;compare and swap&quot;.
Definition: arm.cpp:36
bool is_pow2(T n)
Definition: bits.h:164
void * Allocate(size_t size, PageType pageType, int prot)
reserve address space and commit memory.
Definition: uvm.cpp:98
void rtl_FreeAligned(void *alignedPointer)
Definition: gcc.cpp:93
UniqueRange AllocateVM(size_t size, vm::PageType pageType, int prot)
void * pointer
Definition: unique_range.h:56
void Free(void *p, size_t size)
decommit memory and release address space.
Definition: uvm.cpp:113
static const size_t allocationAlignment
Definition: alignment.h:69
void cpu_Pause()
pause in spin-wait loops, as a performance optimisation.
Definition: cpu.h:91