use std::{collections::HashMap, sync::Mutex};
use crate::{
driver::{CuContext, Driver},
memory::PinnedUploadStagingPool,
};
use super::host_budget::SharedCudaHostBudget;
use super::{CompiledKernel, CompiledKernelKey, ContextResourceLifecycle};
#[derive(Debug, Clone, Copy)]
pub(crate) enum ContextOwnership {
Owned,
RetainedPrimary { device: crate::driver::CuDevice },
}
pub(crate) struct ContextInner {
pub(crate) driver: Driver,
pub(crate) context: CuContext,
pub(crate) ownership: ContextOwnership,
pub(crate) device_ordinal: usize,
pub(crate) modules: Mutex<HashMap<CompiledKernelKey, CompiledKernel>>,
pub(crate) pinned_upload_operation: Mutex<()>,
pub(crate) pinned_upload_staging: Mutex<PinnedUploadStagingPool>,
pub(crate) host_budget: std::sync::Arc<SharedCudaHostBudget>,
pub(crate) resource_lifecycle: ContextResourceLifecycle,
}
impl Drop for ContextInner {
fn drop(&mut self) {
if !self.context.is_null() {
let can_release_individually = self.resource_lifecycle.can_release_individually()
&& self.set_current_for_resource_release().is_ok();
if can_release_individually {
let pinned_upload_staging = match self.pinned_upload_staging.get_mut() {
Ok(pinned_upload_staging) => pinned_upload_staging,
Err(poisoned) => poisoned.into_inner(),
};
for mut staging in pinned_upload_staging.drain_cached() {
let _ = staging.free(&self.driver);
}
for mut staging in pinned_upload_staging.drain_uncertain() {
let _ = staging.free(&self.driver);
}
let modules = match self.modules.get_mut() {
Ok(modules) => modules,
Err(poisoned) => poisoned.into_inner(),
};
for compiled in modules.drain().map(|(_, compiled)| compiled) {
let _ = unsafe { (self.driver.cu_module_unload)(compiled.module) };
}
}
match self.ownership {
ContextOwnership::Owned => {
let _ = unsafe { (self.driver.cu_ctx_destroy)(self.context) };
}
ContextOwnership::RetainedPrimary { device } => {
let _ = unsafe { (self.driver.cu_device_primary_ctx_release)(device) };
}
}
self.host_budget.clear_pinned_after_context_drop();
}
}
}
unsafe impl Send for ContextInner {}
unsafe impl Sync for ContextInner {}