1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "platform.h" |
7 | #include <vector> |
8 | #include <set> |
9 | |
10 | namespace embree |
11 | { |
12 | #define ALIGNED_STRUCT_(align) \ |
13 | void* operator new(size_t size) { return alignedMalloc(size,align); } \ |
14 | void operator delete(void* ptr) { alignedFree(ptr); } \ |
15 | void* operator new[](size_t size) { return alignedMalloc(size,align); } \ |
16 | void operator delete[](void* ptr) { alignedFree(ptr); } |
17 | |
18 | #define ALIGNED_CLASS_(align) \ |
19 | public: \ |
20 | ALIGNED_STRUCT_(align) \ |
21 | private: |
22 | |
23 | /*! aligned allocation */ |
24 | void* alignedMalloc(size_t size, size_t align); |
25 | void alignedFree(void* ptr); |
26 | |
27 | /*! allocator that performs aligned allocations */ |
28 | template<typename T, size_t alignment> |
29 | struct aligned_allocator |
30 | { |
31 | typedef T value_type; |
32 | typedef T* pointer; |
33 | typedef const T* const_pointer; |
34 | typedef T& reference; |
35 | typedef const T& const_reference; |
36 | typedef std::size_t size_type; |
37 | typedef std::ptrdiff_t difference_type; |
38 | |
39 | __forceinline pointer allocate( size_type n ) { |
40 | return (pointer) alignedMalloc(n*sizeof(value_type),alignment); |
41 | } |
42 | |
43 | __forceinline void deallocate( pointer p, size_type n ) { |
44 | return alignedFree(p); |
45 | } |
46 | |
47 | __forceinline void construct( pointer p, const_reference val ) { |
48 | new (p) T(val); |
49 | } |
50 | |
51 | __forceinline void destroy( pointer p ) { |
52 | p->~T(); |
53 | } |
54 | }; |
55 | |
56 | /*! allocates pages directly from OS */ |
57 | bool win_enable_selockmemoryprivilege(bool verbose); |
58 | bool os_init(bool hugepages, bool verbose); |
59 | void* os_malloc (size_t bytes, bool& hugepages); |
60 | size_t os_shrink (void* ptr, size_t bytesNew, size_t bytesOld, bool hugepages); |
61 | void os_free (void* ptr, size_t bytes, bool hugepages); |
62 | void os_advise (void* ptr, size_t bytes); |
63 | |
64 | /*! allocator that performs OS allocations */ |
65 | template<typename T> |
66 | struct os_allocator |
67 | { |
68 | typedef T value_type; |
69 | typedef T* pointer; |
70 | typedef const T* const_pointer; |
71 | typedef T& reference; |
72 | typedef const T& const_reference; |
73 | typedef std::size_t size_type; |
74 | typedef std::ptrdiff_t difference_type; |
75 | |
76 | __forceinline os_allocator () |
77 | : hugepages(false) {} |
78 | |
79 | __forceinline pointer allocate( size_type n ) { |
80 | return (pointer) os_malloc(n*sizeof(value_type),hugepages); |
81 | } |
82 | |
83 | __forceinline void deallocate( pointer p, size_type n ) { |
84 | return os_free(p,n*sizeof(value_type),hugepages); |
85 | } |
86 | |
87 | __forceinline void construct( pointer p, const_reference val ) { |
88 | new (p) T(val); |
89 | } |
90 | |
91 | __forceinline void destroy( pointer p ) { |
92 | p->~T(); |
93 | } |
94 | |
95 | bool hugepages; |
96 | }; |
97 | |
98 | /*! allocator for IDs */ |
99 | template<typename T, size_t max_id> |
100 | struct IDPool |
101 | { |
102 | typedef T value_type; |
103 | |
104 | IDPool () |
105 | : nextID(0) {} |
106 | |
107 | T allocate() |
108 | { |
109 | /* return ID from list */ |
110 | if (!IDs.empty()) |
111 | { |
112 | T id = *IDs.begin(); |
113 | IDs.erase(IDs.begin()); |
114 | return id; |
115 | } |
116 | |
117 | /* allocate new ID */ |
118 | else |
119 | { |
120 | if (size_t(nextID)+1 > max_id) |
121 | return -1; |
122 | |
123 | return nextID++; |
124 | } |
125 | } |
126 | |
127 | /* adds an ID provided by the user */ |
128 | bool add(T id) |
129 | { |
130 | if (id > max_id) |
131 | return false; |
132 | |
133 | /* check if ID should be in IDs set */ |
134 | if (id < nextID) { |
135 | auto p = IDs.find(id); |
136 | if (p == IDs.end()) return false; |
137 | IDs.erase(p); |
138 | return true; |
139 | } |
140 | |
141 | /* otherwise increase ID set */ |
142 | else |
143 | { |
144 | for (T i=nextID; i<id; i++) { |
145 | IDs.insert(i); |
146 | } |
147 | nextID = id+1; |
148 | return true; |
149 | } |
150 | } |
151 | |
152 | void deallocate( T id ) |
153 | { |
154 | assert(id < nextID); |
155 | MAYBE_UNUSED auto done = IDs.insert(id).second; |
156 | assert(done); |
157 | } |
158 | |
159 | private: |
160 | std::set<T> IDs; //!< stores deallocated IDs to be reused |
161 | T nextID; //!< next ID to use when IDs vector is empty |
162 | }; |
163 | } |
164 | |
165 | |