1use std::sync::Arc;
4
5use super::{failure::DeviceMemoryFailureInfo, options::DeviceMemoryManagerOptions};
6use crate::core::error::{self, Result};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct DeviceMemoryManagerFailureCallbackState {
13 pub exists: bool,
14 pub failure_callback_installed: bool,
15 pub current_resource_installed: bool,
16 pub failure_callback_panicked: bool,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub struct DeviceMemoryManagerInstallationIdentity {
23 pub owner_fingerprint: [u8; 16],
25 pub callback_version: u32,
27 pub partition_fingerprint: [u8; 16],
29}
30
31impl DeviceMemoryManagerInstallationIdentity {
32 pub const fn new(owner_fingerprint: [u8; 16], callback_version: u32, partition_fingerprint: [u8; 16]) -> Self {
37 Self { owner_fingerprint, callback_version, partition_fingerprint }
38 }
39}
40
41#[derive(Clone, Default)]
47pub struct InstallSpec {
48 pub options: DeviceMemoryManagerOptions,
49 pub owner: Option<DeviceMemoryManagerInstallationIdentity>,
50 pub on_failure: Option<Arc<dyn Fn(DeviceMemoryFailureInfo) + Send + Sync + 'static>>,
53}
54
55pub(super) fn installation_identity_to_sys(
56 identity: DeviceMemoryManagerInstallationIdentity,
57) -> cudf_sys::cudf_memory_manager_installation_identity_t {
58 cudf_sys::cudf_memory_manager_installation_identity_t {
59 owner_fingerprint: identity.owner_fingerprint,
60 callback_version: identity.callback_version,
61 reserved_padding: 0,
62 partition_fingerprint: identity.partition_fingerprint,
63 }
64}
65
66fn installation_identity_from_sys(
67 identity: cudf_sys::cudf_memory_manager_installation_identity_t,
68) -> DeviceMemoryManagerInstallationIdentity {
69 DeviceMemoryManagerInstallationIdentity::new(
70 identity.owner_fingerprint,
71 identity.callback_version,
72 identity.partition_fingerprint,
73 )
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78#[non_exhaustive]
79pub enum DeviceMemoryManagerInstallationStatus {
80 Uninstalled,
82 Incomplete,
84 Owned,
86 Unidentified,
88 CallbackPanicked,
90}
91
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94#[non_exhaustive]
95pub enum DeviceMemoryManagerInstallationRetry {
96 Installable,
98 Retryable,
100 Reusable,
102 PermanentlyUnusable,
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108#[non_exhaustive]
109pub enum DeviceMemoryManagerInstallationCause {
110 None,
112 CurrentResourceInstallFailed,
114 CurrentResourceReplaced,
116 FailureCallbackPanicked,
118 FailureCallbackMissing,
120 IdentityMissing,
122 OptionsMismatch,
124 IdentityMismatch,
126 CallbackBindingMismatch,
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132pub struct DeviceMemoryManagerInstallationState {
133 pub device_ordinal: usize,
135 pub status: DeviceMemoryManagerInstallationStatus,
137 pub retry: DeviceMemoryManagerInstallationRetry,
139 pub cause: DeviceMemoryManagerInstallationCause,
141 pub effective_options: Option<DeviceMemoryManagerOptions>,
143 pub identity: Option<DeviceMemoryManagerInstallationIdentity>,
145 pub installation_generation: Option<u64>,
147 pub failure_callback_installed: bool,
149 pub current_resource_installed: bool,
151 pub failure_callback_panicked: bool,
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq)]
157pub enum DeviceMemoryManagerInstallationOutcomeKind {
158 Installed,
159 Reused,
160}
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq)]
164pub struct DeviceMemoryManagerInstallationOutcome {
165 pub kind: DeviceMemoryManagerInstallationOutcomeKind,
166 pub state: DeviceMemoryManagerInstallationState,
167}
168
169#[derive(Debug)]
172pub struct DeviceMemoryManagerInstallationError {
173 pub(super) error: error::Error,
174 pub(super) state: Option<Box<DeviceMemoryManagerInstallationState>>,
175}
176
177impl From<error::Error> for DeviceMemoryManagerInstallationError {
178 fn from(error: error::Error) -> Self {
179 Self { error, state: None }
180 }
181}
182
183impl DeviceMemoryManagerInstallationError {
184 pub(super) fn with_state(error: error::Error, state: Option<DeviceMemoryManagerInstallationState>) -> Self {
185 Self { error, state: state.map(Box::new) }
186 }
187
188 pub fn error(&self) -> &error::Error {
190 &self.error
191 }
192
193 pub fn installation_state(&self) -> Option<DeviceMemoryManagerInstallationState> {
200 self.state.as_deref().copied()
201 }
202
203 pub fn into_error(self) -> error::Error {
205 self.error
206 }
207}
208
209impl std::fmt::Display for DeviceMemoryManagerInstallationError {
210 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
211 self.error.fmt(formatter)
212 }
213}
214
215impl std::error::Error for DeviceMemoryManagerInstallationError {
216 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
217 Some(&self.error)
218 }
219}
220
221pub(super) fn installation_state_from_native_record(
222 record: cudf_sys::cudf_memory_manager_installation_record_t,
223) -> Result<DeviceMemoryManagerInstallationState> {
224 if record.struct_size != core::mem::size_of::<cudf_sys::cudf_memory_manager_installation_record_t>() {
225 return Err(error::Error::new_with(
226 error::ErrorCode::ForeignInvariantViolation,
227 "memory::device_memory_manager::installation_state_for_device",
228 "native installation record returned an incompatible struct size",
229 )
230 .with_detail("struct_size", record.struct_size.to_string()));
231 }
232 let status = match record.status {
233 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_UNINSTALLED => DeviceMemoryManagerInstallationStatus::Uninstalled,
234 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_INCOMPLETE => DeviceMemoryManagerInstallationStatus::Incomplete,
235 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_OWNED => DeviceMemoryManagerInstallationStatus::Owned,
236 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_UNIDENTIFIED => DeviceMemoryManagerInstallationStatus::Unidentified,
237 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_CALLBACK_PANICKED => {
238 DeviceMemoryManagerInstallationStatus::CallbackPanicked
239 },
240 value => {
241 return Err(error::Error::new_with(
242 error::ErrorCode::ForeignInvariantViolation,
243 "memory::device_memory_manager::installation_state_for_device",
244 "native installation record returned an unknown status",
245 )
246 .with_detail("status", value.to_string()));
247 },
248 };
249 let retry = match record.retry {
250 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_INSTALLABLE => DeviceMemoryManagerInstallationRetry::Installable,
251 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_RETRYABLE => DeviceMemoryManagerInstallationRetry::Retryable,
252 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_REUSABLE => DeviceMemoryManagerInstallationRetry::Reusable,
253 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_PERMANENTLY_UNUSABLE => {
254 DeviceMemoryManagerInstallationRetry::PermanentlyUnusable
255 },
256 value => {
257 return Err(error::Error::new_with(
258 error::ErrorCode::ForeignInvariantViolation,
259 "memory::device_memory_manager::installation_state_for_device",
260 "native installation record returned an unknown retry classification",
261 )
262 .with_detail("retry", value.to_string()));
263 },
264 };
265 let cause = match record.cause {
266 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_CAUSE_NONE => DeviceMemoryManagerInstallationCause::None,
267 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_CAUSE_CURRENT_RESOURCE_INSTALL_FAILED => {
268 DeviceMemoryManagerInstallationCause::CurrentResourceInstallFailed
269 },
270 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_CAUSE_CURRENT_RESOURCE_REPLACED => {
271 DeviceMemoryManagerInstallationCause::CurrentResourceReplaced
272 },
273 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_CAUSE_FAILURE_CALLBACK_PANICKED => {
274 DeviceMemoryManagerInstallationCause::FailureCallbackPanicked
275 },
276 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_CAUSE_FAILURE_CALLBACK_MISSING => {
277 DeviceMemoryManagerInstallationCause::FailureCallbackMissing
278 },
279 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_CAUSE_IDENTITY_MISSING => {
280 DeviceMemoryManagerInstallationCause::IdentityMissing
281 },
282 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_CAUSE_OPTIONS_MISMATCH => {
283 DeviceMemoryManagerInstallationCause::OptionsMismatch
284 },
285 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_CAUSE_IDENTITY_MISMATCH => {
286 DeviceMemoryManagerInstallationCause::IdentityMismatch
287 },
288 cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_CAUSE_CALLBACK_BINDING_MISMATCH => {
289 DeviceMemoryManagerInstallationCause::CallbackBindingMismatch
290 },
291 value => {
292 return Err(error::Error::new_with(
293 error::ErrorCode::ForeignInvariantViolation,
294 "memory::device_memory_manager::installation_state_for_device",
295 "native installation record returned an unknown cause",
296 )
297 .with_detail("cause", value.to_string()));
298 },
299 };
300 let exists = record.flags & cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_FLAG_EXISTS != 0;
301 let has_identity = record.flags & cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_FLAG_HAS_IDENTITY != 0;
302 let device_ordinal = usize::try_from(record.device_ordinal).map_err(|_| {
303 error::Error::new_with(
304 error::ErrorCode::ForeignInvariantViolation,
305 "memory::device_memory_manager::installation_state_for_device",
306 "native installation record returned a negative device ordinal",
307 )
308 })?;
309 Ok(DeviceMemoryManagerInstallationState {
310 device_ordinal,
311 status,
312 retry,
313 cause,
314 effective_options: exists
315 .then(|| DeviceMemoryManagerOptions::from_sys(record.effective_options))
316 .transpose()?,
317 identity: has_identity.then(|| installation_identity_from_sys(record.identity)),
318 installation_generation: (record.installation_generation != 0).then_some(record.installation_generation),
319 failure_callback_installed: record.flags
320 & cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_FLAG_FAILURE_CALLBACK_INSTALLED
321 != 0,
322 current_resource_installed: record.flags
323 & cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_FLAG_CURRENT_RESOURCE_INSTALLED
324 != 0,
325 failure_callback_panicked: record.flags & cudf_sys::CUDF_MEMORY_MANAGER_INSTALLATION_FLAG_CALLBACK_PANICKED
326 != 0,
327 })
328}