Fix a race condition between the "ephemeral watchpoint disabling" and commands the...
[lldb.git] / parallel-libs / streamexecutor / include / streamexecutor / HostMemory.h
1 //===-- HostMemory.h - Types for registered host memory ---------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 ///
12 /// This file defines types that represent registered host memory buffers. Host
13 /// memory must be registered to participate in asynchronous copies to or from
14 /// device memory.
15 ///
16 //===----------------------------------------------------------------------===//
17
18 #ifndef STREAMEXECUTOR_HOSTMEMORY_H
19 #define STREAMEXECUTOR_HOSTMEMORY_H
20
21 #include <cassert>
22 #include <cstddef>
23 #include <type_traits>
24
25 #include "llvm/ADT/ArrayRef.h"
26
27 namespace streamexecutor {
28
29 class Device;
30 template <typename ElemT> class RegisteredHostMemory;
31
32 /// A mutable slice of registered host memory.
33 ///
34 /// The memory is registered in the sense of
35 /// streamexecutor::Device::registerHostMemory.
36 ///
37 /// Holds a reference to an underlying registered host memory buffer. Must not
38 /// be used after the underlying buffer is freed or unregistered.
39 template <typename ElemT> class MutableRegisteredHostMemorySlice {
40 public:
41   using ElementTy = ElemT;
42
43   MutableRegisteredHostMemorySlice(RegisteredHostMemory<ElemT> &Registered)
44       : MutableArrayRef(Registered.getPointer(), Registered.getElementCount()) {
45   }
46
47   ElemT *getPointer() const { return MutableArrayRef.data(); }
48   size_t getElementCount() const { return MutableArrayRef.size(); }
49
50   /// Chops off the first DropCount elements of the slice.
51   LLVM_ATTRIBUTE_UNUSED_RESULT
52   MutableRegisteredHostMemorySlice slice(size_t DropCount) const {
53     return MutableRegisteredHostMemorySlice(MutableArrayRef.slice(DropCount));
54   }
55
56   /// Chops off the first DropCount elements of the slice and keeps the next
57   /// TakeCount elements.
58   LLVM_ATTRIBUTE_UNUSED_RESULT
59   MutableRegisteredHostMemorySlice slice(size_t DropCount,
60                                          size_t TakeCount) const {
61     return MutableRegisteredHostMemorySlice(
62         MutableArrayRef.slice(DropCount, TakeCount));
63   }
64
65   /// Chops off the last DropCount elements of the slice.
66   LLVM_ATTRIBUTE_UNUSED_RESULT
67   MutableRegisteredHostMemorySlice drop_back(size_t DropCount) const {
68     return MutableRegisteredHostMemorySlice(
69         MutableArrayRef.drop_back(DropCount));
70   }
71
72 private:
73   MutableRegisteredHostMemorySlice(llvm::MutableArrayRef<ElemT> MutableArrayRef)
74       : MutableArrayRef(MutableArrayRef) {}
75
76   llvm::MutableArrayRef<ElemT> MutableArrayRef;
77 };
78
79 /// An immutable slice of registered host memory.
80 ///
81 /// The memory is registered in the sense of
82 /// streamexecutor::Device::registerHostMemory.
83 ///
84 /// Holds a reference to an underlying registered host memory buffer. Must not
85 /// be used after the underlying buffer is freed or unregistered.
86 template <typename ElemT> class RegisteredHostMemorySlice {
87 public:
88   using ElementTy = ElemT;
89
90   RegisteredHostMemorySlice(const RegisteredHostMemory<ElemT> &Registered)
91       : ArrayRef(Registered.getPointer(), Registered.getElementCount()) {}
92
93   RegisteredHostMemorySlice(
94       MutableRegisteredHostMemorySlice<ElemT> MutableSlice)
95       : ArrayRef(MutableSlice.getPointer(), MutableSlice.getElementCount()) {}
96
97   const ElemT *getPointer() const { return ArrayRef.data(); }
98   size_t getElementCount() const { return ArrayRef.size(); }
99
100   /// Chops off the first N elements of the slice.
101   LLVM_ATTRIBUTE_UNUSED_RESULT
102   RegisteredHostMemorySlice slice(size_t N) const {
103     return RegisteredHostMemorySlice(ArrayRef.slice(N));
104   }
105
106   /// Chops off the first N elements of the slice and keeps the next M elements.
107   LLVM_ATTRIBUTE_UNUSED_RESULT
108   RegisteredHostMemorySlice slice(size_t N, size_t M) const {
109     return RegisteredHostMemorySlice(ArrayRef.slice(N, M));
110   }
111
112   /// Chops off the last N elements of the slice.
113   LLVM_ATTRIBUTE_UNUSED_RESULT
114   RegisteredHostMemorySlice drop_back(size_t N) const {
115     return RegisteredHostMemorySlice(ArrayRef.drop_back(N));
116   }
117
118 private:
119   llvm::ArrayRef<ElemT> ArrayRef;
120 };
121
122 namespace internal {
123
124 /// Helper function to unregister host memory.
125 ///
126 /// This is a thin wrapper around streamexecutor::Device::unregisterHostMemory.
127 /// It is defined so this operation can be performed from the destructor of the
128 /// template class RegisteredHostMemory without including Device.h in this
129 /// header and creating a header inclusion cycle.
130 void destroyRegisteredHostMemoryInternals(Device *TheDevice, void *Pointer);
131
132 } // namespace internal
133
134 /// Registered host memory that knows how to unregister itself upon destruction.
135 ///
136 /// The memory is registered in the sense of
137 /// streamexecutor::Device::registerHostMemory.
138 ///
139 /// ElemT is the type of element stored in the host buffer.
140 template <typename ElemT> class RegisteredHostMemory {
141 public:
142   using ElementTy = ElemT;
143
144   RegisteredHostMemory(Device *TheDevice, ElemT *Pointer, size_t ElementCount)
145       : TheDevice(TheDevice), Pointer(Pointer), ElementCount(ElementCount) {
146     assert(TheDevice != nullptr && "cannot construct a "
147                                    "RegisteredHostMemoryBase with a null "
148                                    "platform device");
149   }
150
151   RegisteredHostMemory(const RegisteredHostMemory &) = delete;
152   RegisteredHostMemory &operator=(const RegisteredHostMemory &) = delete;
153
154   RegisteredHostMemory(RegisteredHostMemory &&Other) noexcept
155       : TheDevice(Other.TheDevice), Pointer(Other.Pointer),
156         ElementCount(Other.ElementCount) {
157     Other.TheDevice = nullptr;
158     Other.Pointer = nullptr;
159   }
160
161   RegisteredHostMemory &operator=(RegisteredHostMemory &&Other) noexcept {
162     TheDevice = Other.TheDevice;
163     Pointer = Other.Pointer;
164     ElementCount = Other.ElementCount;
165     Other.TheDevice = nullptr;
166     Other.Pointer = nullptr;
167   }
168
169   ~RegisteredHostMemory() {
170     internal::destroyRegisteredHostMemoryInternals(TheDevice, Pointer);
171   }
172
173   ElemT *getPointer() { return static_cast<ElemT *>(Pointer); }
174   const ElemT *getPointer() const { return static_cast<ElemT *>(Pointer); }
175   size_t getElementCount() const { return ElementCount; }
176
177   /// Creates an immutable slice for the entire contents of this memory.
178   RegisteredHostMemorySlice<ElemT> asSlice() const {
179     return RegisteredHostMemorySlice<ElemT>(*this);
180   }
181
182   /// Creates a mutable slice for the entire contents of this memory.
183   MutableRegisteredHostMemorySlice<ElemT> asSlice() {
184     return MutableRegisteredHostMemorySlice<ElemT>(*this);
185   }
186
187 private:
188   Device *TheDevice;
189   void *Pointer;
190   size_t ElementCount;
191 };
192
193 } // namespace streamexecutor
194
195 #endif // STREAMEXECUTOR_HOSTMEMORY_H