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
10namespace 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