-
Notifications
You must be signed in to change notification settings - Fork 0
/
dmk_memory.h
152 lines (139 loc) · 3.84 KB
/
dmk_memory.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#pragma once
#include "dmk.h"
#include "dmk_assert.h"
#include <memory>
#include <type_traits>
#if defined( DMK_OS_WIN )
#include <windows.h>
#endif
namespace dmk
{
template <size_t alignment>
void* aligned_malloc( size_t size )
{
if ( alignment <= sizeof( size_t ) )
return malloc( size );
else
return _mm_malloc( size, alignment );
}
template <size_t alignment>
void aligned_free( void* memory )
{
if ( alignment <= sizeof( size_t ) )
free( memory );
else
_mm_free( memory );
}
struct allocator_base
{
public:
typedef size_t size_type;
typedef void* pointer;
typedef const void* const_pointer;
typedef void* zeroed_pointer;
public:
template <size_t alignment>
static size_t align_down( size_t size )
{
return ( size ) & ~( alignment - 1 );
}
template <size_t alignment>
static size_t align_up( size_t size )
{
return ( size + alignment - 1 ) & ~( alignment - 1 );
}
static void zeroize( pointer begin, pointer end )
{
std::memset( begin, 0, ( size_t )end - ( size_t )begin );
}
static void move( const_pointer begin, const_pointer end, pointer destination )
{
std::memmove( destination, begin, ( size_t )end - ( size_t )begin );
}
template <size_t itemsize>
static void fill( pointer begin, pointer end, const_pointer source )
{
for ( ; begin != end; begin++ )
{
std::memmove( begin, source, itemsize );
}
}
public:
};
struct malloc_allocator : public allocator_base
{
public:
static pointer allocate( size_type& size )
{
size = align_up<sizeof( size_t )>( size );
return std::malloc( size );
}
static zeroed_pointer allocate_zeroed( size_type& size )
{
zeroed_pointer memory = allocate( size );
zeroize( memory, ( uint8_t* )memory + size );
return memory;
}
static void deallocate( pointer memory )
{
std::free( memory );
}
};
enum
{
PageSize = 4096,
CacheSize = 64,
SSESize = 16,
AVXSize = 32
};
enum
{
PageAllocationGranularity = 65536
};
DMK_ALIGNED_ALLOCATOR( PageSize ) void* paged_malloc( size_t size )
{
return ::VirtualAlloc( NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
}
void paged_free( void* memory )
{
::VirtualFree( ( PVOID )memory, 0, MEM_RELEASE );
}
template <size_t alignment>
struct aligned_allocator : public allocator_base
{
public:
static pointer allocate( size_type& size )
{
size = align_up<sizeof( size_t )>( size );
return aligned_malloc<alignment>( size );
}
static zeroed_pointer allocate_zeroed( size_type& size )
{
zeroed_pointer memory = allocate( size );
zeroize( memory, ( uint8_t* )memory + size );
return memory;
}
static void deallocate( pointer memory )
{
aligned_free<alignment>( memory );
}
};
template <>
struct aligned_allocator<PageSize> : public allocator_base
{
public:
static pointer allocate( size_type& size )
{
size = align_up<PageAllocationGranularity>( size );
return paged_malloc( size );
}
static zeroed_pointer allocate_zeroed( size_type& size )
{
return allocate( size );
}
static void deallocate( pointer memory )
{
paged_free( memory );
}
};
} // namespace dmk