1use std::sync::Arc;
9
10use baracuda_cuda_sys::types::{CUdevResource, CUdevResourceType, CUdevSmResource};
11use baracuda_cuda_sys::{driver, CUcontext, CUdevResourceDesc, CUgreenCtx, CUstream};
12
13use crate::device::Device;
14use crate::error::{check, Result};
15
16pub fn device_sm_resource(device: &Device) -> Result<CUdevResource> {
19 let d = driver()?;
20 let cu = d.cu_device_get_dev_resource()?;
21 let mut r = CUdevResource::default();
22 check(unsafe { cu(device.as_raw(), &mut r, CUdevResourceType::SM) })?;
23 Ok(r)
24}
25
26pub fn sm_resource_split_by_count(
29 input: &CUdevResource,
30 min_count: u32,
31) -> Result<(Vec<CUdevResource>, CUdevResource)> {
32 let d = driver()?;
33 let cu = d.cu_dev_sm_resource_split_by_count()?;
34 let mut nb: core::ffi::c_uint = 0;
36 let mut remaining = CUdevResource::default();
37 check(unsafe {
38 cu(
39 core::ptr::null_mut(),
40 &mut nb,
41 input,
42 &mut remaining,
43 0,
44 min_count,
45 )
46 })?;
47 let mut result = vec![CUdevResource::default(); nb as usize];
48 if nb > 0 {
49 check(unsafe {
50 cu(
51 result.as_mut_ptr(),
52 &mut nb,
53 input,
54 &mut remaining,
55 0,
56 min_count,
57 )
58 })?;
59 }
60 Ok((result, remaining))
61}
62
63#[derive(Clone)]
66pub struct GreenContext {
67 inner: Arc<GreenContextInner>,
68}
69
70struct GreenContextInner {
71 handle: CUgreenCtx,
72}
73
74unsafe impl Send for GreenContextInner {}
75unsafe impl Sync for GreenContextInner {}
76
77impl core::fmt::Debug for GreenContextInner {
78 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79 f.debug_struct("GreenContext")
80 .field("handle", &self.handle)
81 .finish_non_exhaustive()
82 }
83}
84
85impl core::fmt::Debug for GreenContext {
86 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
87 self.inner.fmt(f)
88 }
89}
90
91impl GreenContext {
92 pub fn from_resource(device: &Device, mut resource: CUdevResource) -> Result<Self> {
95 let d = driver()?;
96 let generate = d.cu_dev_resource_generate_desc()?;
99 let mut desc: CUdevResourceDesc = core::ptr::null_mut();
100 check(unsafe { generate(&mut desc, &mut resource, 1) })?;
101 let create = d.cu_green_ctx_create()?;
103 let mut handle: CUgreenCtx = core::ptr::null_mut();
104 check(unsafe { create(&mut handle, desc, device.as_raw(), 0) })?;
105 Ok(Self {
106 inner: Arc::new(GreenContextInner { handle }),
107 })
108 }
109
110 pub fn as_ctx_raw(&self) -> Result<CUcontext> {
113 let d = driver()?;
114 let cu = d.cu_ctx_from_green_ctx()?;
115 let mut out: CUcontext = core::ptr::null_mut();
116 check(unsafe { cu(&mut out, self.inner.handle) })?;
117 Ok(out)
118 }
119
120 pub fn sm_resource(&self) -> Result<CUdevSmResource> {
122 let d = driver()?;
123 let cu = d.cu_green_ctx_get_dev_resource()?;
124 let mut r = CUdevResource::default();
125 check(unsafe { cu(self.inner.handle, &mut r, CUdevResourceType::SM) })?;
126 Ok(r.as_sm())
127 }
128
129 pub fn create_stream_raw(&self, flags: u32, priority: i32) -> Result<CUstream> {
133 let d = driver()?;
134 let cu = d.cu_green_ctx_stream_create()?;
135 let mut s: CUstream = core::ptr::null_mut();
136 check(unsafe { cu(&mut s, self.inner.handle, flags, priority) })?;
137 Ok(s)
138 }
139
140 pub unsafe fn from_raw(handle: CUgreenCtx) -> Self {
148 Self {
149 inner: Arc::new(GreenContextInner { handle }),
150 }
151 }
152
153 pub fn into_raw(self) -> CUgreenCtx {
156 match Arc::try_unwrap(self.inner) {
157 Ok(mut inner) => {
158 let h = inner.handle;
159 inner.handle = core::ptr::null_mut();
160 h
161 }
162 Err(arc) => arc.handle,
163 }
164 }
165
166 #[inline]
167 pub fn as_raw(&self) -> CUgreenCtx {
168 self.inner.handle
169 }
170}
171
172impl Drop for GreenContextInner {
173 fn drop(&mut self) {
174 if self.handle.is_null() {
175 return;
176 }
177 if let Ok(d) = driver() {
178 if let Ok(cu) = d.cu_green_ctx_destroy() {
179 let _ = unsafe { cu(self.handle) };
180 }
181 }
182 }
183}