Skip to content

Commit fe2d27d

Browse files
committed
cuda.core: inline resource state validation
Centralize open and valid state checks so hot Cython call paths use one consistent implementation.
1 parent 250a442 commit fe2d27d

30 files changed

Lines changed: 128 additions & 140 deletions

‎cuda_core/cuda/core/_context.pxd‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,9 @@ cdef class Context:
2323
cdef Context _from_green_ctx(type cls, GreenCtxHandle h_green_ctx, int device_id)
2424

2525
cpdef close(self)
26+
27+
28+
cdef inline int Context_check_open(Context self) except -1:
29+
if not self._h_context:
30+
raise RuntimeError("Context has been closed")
31+
return 0

‎cuda_core/cuda/core/_context.pyx‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ cdef class Context:
9696

9797
Raises :class:`RuntimeError` if the context has been closed.
9898
"""
99-
if not self._h_context:
100-
raise RuntimeError("Cannot query resources on a closed context")
99+
Context_check_open(self)
101100
return DeviceResources._init_from_ctx(self._h_context, self._device_id)
102101

103102
def create_stream(self, options: object = None) -> Stream:
@@ -116,8 +115,7 @@ cdef class Context:
116115
:obj:`~_stream.Stream`
117116
Newly created stream object.
118117
"""
119-
if not self._h_context:
120-
raise RuntimeError("Cannot create a stream on a closed context")
118+
Context_check_open(self)
121119
if not self.is_green:
122120
raise RuntimeError(
123121
"Context.create_stream() is only supported on green contexts. "

‎cuda_core/cuda/core/_device.pyx‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ from libcpp.vector cimport vector
1212

1313
import threading
1414

15-
from cuda.core._context cimport Context
15+
from cuda.core._context cimport Context, Context_check_open
1616
from cuda.core._context import ContextOptions
1717
from cuda.core._device_resources cimport DeviceResources, SMResource, WorkqueueResource
1818
from cuda.core._event cimport Event as cyEvent
@@ -1278,8 +1278,7 @@ class Device:
12781278
if ctx is not None:
12791279
# TODO: revisit once Context is cythonized
12801280
assert_type(ctx, Context)
1281-
if ctx.is_closed:
1282-
raise RuntimeError("Context has been closed")
1281+
Context_check_open(ctx)
12831282
if ctx._device_id != self._device_id:
12841283
raise RuntimeError(
12851284
"the provided context was created on the device with"

‎cuda_core/cuda/core/_event.pxd‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,7 @@ cdef class Event:
2323

2424

2525
cdef Event Event_accept(object arg)
26-
cdef int Event_check_open(Event self) except -1
26+
cdef inline int Event_check_open(Event self) except -1:
27+
if not self._h_event:
28+
raise RuntimeError("Event has been closed")
29+
return 0

‎cuda_core/cuda/core/_event.pyx‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -342,13 +342,6 @@ cdef class Event:
342342
if h_ctx and dev_id >= 0:
343343
return Context._from_handle(Context, h_ctx, dev_id)
344344

345-
346-
cdef int Event_check_open(Event self) except -1:
347-
if not self._h_event:
348-
raise RuntimeError("Event has been closed")
349-
return 0
350-
351-
352345
cdef Event Event_accept(object arg):
353346
if not isinstance(arg, Event):
354347
raise TypeError(f"Event expected, got {type(arg).__name__}")

‎cuda_core/cuda/core/_graphics.pyx‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ def _parse_register_flags(flags: str | Sequence[str] | None) -> int:
4545
return result
4646

4747

48+
cdef inline int GraphicsResource_check_open(GraphicsResource self) except -1:
49+
if not self._handle:
50+
raise RuntimeError("GraphicsResource has been closed")
51+
return 0
52+
53+
4854
cdef class GraphicsResource:
4955
"""RAII wrapper for a CUDA graphics resource (``CUgraphicsResource``).
5056
@@ -251,8 +257,7 @@ cdef class GraphicsResource:
251257
"""
252258
cdef cydriver.CUdeviceptr dev_ptr = 0
253259
cdef size_t size = 0
254-
if not self._handle:
255-
raise RuntimeError("GraphicsResource has been closed")
260+
GraphicsResource_check_open(self)
256261
if self._get_mapped_buffer() is not None:
257262
raise RuntimeError("GraphicsResource is already mapped")
258263

@@ -294,8 +299,7 @@ cdef class GraphicsResource:
294299
CUDAError
295300
If the unmapping fails.
296301
"""
297-
if not self._handle:
298-
raise RuntimeError("GraphicsResource has been closed")
302+
GraphicsResource_check_open(self)
299303
cdef object buf_obj = self._get_mapped_buffer()
300304
if buf_obj is None:
301305
raise RuntimeError("GraphicsResource is not mapped")

‎cuda_core/cuda/core/_kernel_arg_handler.pyx‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ from typing import Sequence, Any
1717
import numpy
1818

1919
from cuda.core._memory import Buffer
20+
from cuda.core._memory._buffer cimport Buffer as cyBuffer, Buffer_check_open
2021
from cuda.core._tensor_map import TensorMapDescriptor as _TensorMapDescriptor_py
2122
from cuda.core._tensor_map cimport TensorMapDescriptor
2223
from cuda.core.graph._graph_definition cimport GraphCondition
@@ -282,8 +283,7 @@ cdef class ParamHolder:
282283
for i, arg in enumerate(kernel_args):
283284
arg_type = type(arg)
284285
if arg_type is Buffer:
285-
if arg.is_closed:
286-
raise RuntimeError("Buffer has been closed")
286+
Buffer_check_open(<cyBuffer>arg)
287287
# we need the address of where the actual buffer address is stored
288288
if type(arg.handle) is int:
289289
# see note below on handling int arguments
@@ -329,8 +329,7 @@ cdef class ParamHolder:
329329
continue
330330
# If no exact types are found, fallback to slower `isinstance` check
331331
elif isinstance(arg, Buffer):
332-
if arg.is_closed:
333-
raise RuntimeError("Buffer has been closed")
332+
Buffer_check_open(<cyBuffer>arg)
334333
if isinstance(arg.handle, int):
335334
prepare_arg[intptr_t](self.data, self.data_addresses, arg.handle, i)
336335
continue

‎cuda_core/cuda/core/_linker.pyx‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ LinkerHandleT = Union["cuda.bindings.nvjitlink.nvJitLinkHandle", "cuda.bindings.
6363
# Principal class
6464
# =============================================================================
6565

66+
67+
cdef inline int Linker_check_open(Linker self) except -1:
68+
if self.is_closed:
69+
raise RuntimeError("Linker has been closed")
70+
return 0
71+
72+
6673
cdef class Linker:
6774
"""Represent a linking machinery to link one or more object codes into
6875
:class:`~cuda.core.ObjectCode`.
@@ -106,8 +113,7 @@ cdef class Linker:
106113
Ensure that input object codes were compiled with appropriate
107114
flags for linking (e.g., relocatable device code enabled).
108115
"""
109-
if self.is_closed:
110-
raise RuntimeError("Linker has been closed")
116+
Linker_check_open(self)
111117
return Linker_link(self, str(target_type))
112118

113119
def get_error_log(self) -> str:
@@ -121,8 +127,7 @@ cdef class Linker:
121127
# After link(), the decoded log is cached here.
122128
if self._error_log is not None:
123129
return self._error_log
124-
if self.is_closed:
125-
raise RuntimeError("Linker has been closed")
130+
Linker_check_open(self)
126131
cdef cynvjitlink.nvJitLinkHandle c_h
127132
cdef size_t c_log_size = 0
128133
cdef char* c_log_ptr
@@ -149,8 +154,7 @@ cdef class Linker:
149154
# After link(), the decoded log is cached here.
150155
if self._info_log is not None:
151156
return self._info_log
152-
if self.is_closed:
153-
raise RuntimeError("Linker has been closed")
157+
Linker_check_open(self)
154158
cdef cynvjitlink.nvJitLinkHandle c_h
155159
cdef size_t c_log_size = 0
156160
cdef char* c_log_ptr

‎cuda_core/cuda/core/_memory/_buffer.pxd‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,9 @@ cdef Buffer Buffer_from_deviceptr_handle(
5050
# prefetch_batch, discard_batch, discard_prefetch_batch). `single_hint`
5151
# names the per-buffer API to use instead when a bare Buffer is passed.
5252
cdef tuple Buffer_coerce_batch(object buffers, str what, str single_hint)
53-
cdef int Buffer_check_open(Buffer self) except -1
53+
54+
55+
cdef inline int Buffer_check_open(Buffer self) except -1:
56+
if not self._h_ptr:
57+
raise RuntimeError("Buffer has been closed")
58+
return 0

‎cuda_core/cuda/core/_memory/_buffer.pyx‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -882,13 +882,6 @@ cdef tuple Buffer_coerce_batch(object buffers, str what, str single_hint):
882882
out.append(item)
883883
return tuple(out)
884884

885-
886-
cdef int Buffer_check_open(Buffer self) except -1:
887-
if not self._h_ptr:
888-
raise RuntimeError("Buffer has been closed")
889-
return 0
890-
891-
892885
cdef inline void Buffer_set_deallocation_stream(Buffer self, object stream):
893886
"""Validate and replace a live buffer's deallocation recipe."""
894887
Buffer_check_open(self)

0 commit comments

Comments
 (0)