Skip to main content

baracuda_runtime/
green.rs

1//! Green contexts (Runtime API, CUDA 13.1+) — lightweight sub-contexts
2//! that share the primary context's memory but carve out an SM subset.
3//!
4//! Returns [`crate::Error::FeatureNotSupported`] on older drivers.
5//!
6//! For the Driver-side API see `baracuda_driver::green`.
7
8use baracuda_cuda_sys::runtime::runtime;
9use baracuda_cuda_sys::runtime::types::{cudaGreenCtx_t, cudaStream_t};
10use baracuda_types::CudaVersion;
11
12use crate::error::{check, Error, Result};
13use crate::event::Event;
14use crate::stream::Stream;
15
16fn require_green_ctx() -> Result<()> {
17    let installed = crate::init::driver_version()?;
18    // The runtime green-context API lands in CUDA 13.1.
19    if installed.at_least(13, 1) {
20        Ok(())
21    } else {
22        Err(Error::FeatureNotSupported {
23            api: "cudaGreenCtx*",
24            since: CudaVersion::from_major_minor(13, 1),
25        })
26    }
27}
28
29/// A green context. Drop destroys it.
30pub struct GreenContext {
31    handle: cudaGreenCtx_t,
32}
33
34unsafe impl Send for GreenContext {}
35unsafe impl Sync for GreenContext {}
36
37impl core::fmt::Debug for GreenContext {
38    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
39        f.debug_struct("GreenContext")
40            .field("handle", &self.handle)
41            .finish()
42    }
43}
44
45impl GreenContext {
46    /// Create a green context from an opaque `cudaDevResourceDesc`
47    /// pointer (built via the driver-side resource-desc APIs).
48    ///
49    /// # Safety
50    ///
51    /// `desc` must be a valid `cudaDevResourceDesc` descriptor.
52    pub unsafe fn from_resource_desc(desc: *const core::ffi::c_void, flags: u32) -> Result<Self> { unsafe {
53        require_green_ctx()?;
54        let r = runtime()?;
55        let cu = r.cuda_device_create_green_ctx()?;
56        let mut h: cudaGreenCtx_t = core::ptr::null_mut();
57        check(cu(&mut h, desc, flags))?;
58        Ok(Self { handle: h })
59    }}
60
61    /// Wrap an already-created handle.
62    ///
63    /// # Safety
64    ///
65    /// `handle` must be live. Drop destroys it.
66    pub unsafe fn from_raw(handle: cudaGreenCtx_t) -> Self {
67        Self { handle }
68    }
69
70    #[inline]
71    pub fn as_raw(&self) -> cudaGreenCtx_t {
72        self.handle
73    }
74
75    /// Record `event` on this green context.
76    pub fn record_event(&self, event: &Event) -> Result<()> {
77        let r = runtime()?;
78        let cu = r.cuda_green_ctx_record_event()?;
79        check(unsafe { cu(self.handle, event.as_raw()) })
80    }
81
82    /// Wait for `event` on this green context.
83    pub fn wait_event(&self, event: &Event) -> Result<()> {
84        let r = runtime()?;
85        let cu = r.cuda_green_ctx_wait_event()?;
86        check(unsafe { cu(self.handle, event.as_raw()) })
87    }
88
89    /// Create a stream on this green context.
90    pub fn create_stream(&self, flags: u32, priority: i32) -> Result<Stream> {
91        let r = runtime()?;
92        let cu = r.cuda_green_ctx_stream_create()?;
93        let mut s: cudaStream_t = core::ptr::null_mut();
94        check(unsafe { cu(&mut s, self.handle, flags, priority) })?;
95        // SAFETY: driver returned a live stream; Stream::from_raw adopts
96        // ownership (drops with cudaStreamDestroy).
97        unsafe { Ok(Stream::from_raw(s)) }
98    }
99}
100
101impl Drop for GreenContext {
102    fn drop(&mut self) {
103        if let Ok(r) = runtime() {
104            if let Ok(cu) = r.cuda_green_ctx_destroy() {
105                let _ = unsafe { cu(self.handle) };
106            }
107        }
108    }
109}