@@ -40,7 +40,7 @@ import sys
4040from collections.abc import Sequence
4141from typing import TYPE_CHECKING
4242
43- from cuda.core._memory._copy_enums import CopyOptions
43+ from cuda.core._memory._copy_enums import CopyOptions, _reject_unsupported_during_api_call
4444from cuda.core._utils.pycompat import BufferProtocol
4545from cuda.core._dlpack import classify_dl_device, make_py_capsule
4646from cuda.core._device import Device
@@ -221,8 +221,14 @@ cdef void _dispatch_buffer_copy(
221221 if _with_attributes_available():
222222 _do_copy_with_attributes(dst, src, nbytes, options, as_cu(s._h_stream))
223223 else :
224- # Matches copy_batch: options are silently ignored on the
225- # pre-CUDA-13.2 driver/bindings fallback path.
224+ _reject_unsupported_during_api_call(
225+ options.src_access_order,
226+ " cuda.bindings and the driver to both report CUDA 13.2 or newer "
227+ " (cuMemcpyWithAttributesAsync is unavailable here)" ,
228+ )
229+ # STREAM and ANY never require access sooner than stream order, so
230+ # cuMemcpyAsync satisfies them; options are otherwise silently
231+ # ignored on this pre-CUDA-13.2 fallback path, matching copy_batch.
226232 with nogil:
227233 HANDLE_RETURN(cydriver.cuMemcpyAsync(dst, src, nbytes, as_cu(s._h_stream)))
228234
@@ -482,15 +488,22 @@ cdef class Buffer:
482488 Not accepted with ``LEGACY_DEFAULT_STREAM`` or a capturing stream
483489 (matches :func:`utils.copy_batch`); use ``PER_THREAD_DEFAULT_STREAM``
484490 or :meth:`graph.GraphNode.memcpy` instead. On cuda.bindings/driver
485- older than CUDA 13.2, the copy falls back to ``cuMemcpyAsync`` with
486- ``options`` silently ignored.
491+ older than CUDA 13.2, ``src_access_order`` values of ``STREAM``
492+ and ``ANY`` fall back to ``cuMemcpyAsync`` silently; ``DURING_API_CALL``
493+ raises instead of silently downgrading its guarantee.
487494
488495 Raises
489496 ------
490497 TypeError
491498 If ``options`` is not a :class:`~utils.CopyOptions` instance , or
492499 if ``options`` is given together with ``LEGACY_DEFAULT_STREAM``
493500 or a stream currently in graph capture mode.
501+ RuntimeError
502+ If ``options.src_access_order`` is ``DURING_API_CALL`` and
503+ cuda.bindings/driver older than CUDA 13.2 makes the native
504+ ``cuMemcpyWithAttributesAsync`` path unavailable: the
505+ ``cuMemcpyAsync`` fallback reads the source in stream order
506+ only , which cannot honor that guarantee.
494507
495508 """
496509 cdef Stream s = Stream_accept(stream)
@@ -527,15 +540,22 @@ cdef class Buffer:
527540 Not accepted with ``LEGACY_DEFAULT_STREAM`` or a capturing stream
528541 (matches :func:`utils.copy_batch`); use ``PER_THREAD_DEFAULT_STREAM``
529542 or :meth:`graph.GraphNode.memcpy` instead. On cuda.bindings/driver
530- older than CUDA 13.2, the copy falls back to ``cuMemcpyAsync`` with
531- ``options`` silently ignored.
543+ older than CUDA 13.2, ``src_access_order`` values of ``STREAM``
544+ and ``ANY`` fall back to ``cuMemcpyAsync`` silently; ``DURING_API_CALL``
545+ raises instead of silently downgrading its guarantee.
532546
533547 Raises
534548 ------
535549 TypeError
536550 If ``options`` is not a :class:`~utils.CopyOptions` instance , or
537551 if ``options`` is given together with ``LEGACY_DEFAULT_STREAM``
538552 or a stream currently in graph capture mode.
553+ RuntimeError
554+ If ``options.src_access_order`` is ``DURING_API_CALL`` and
555+ cuda.bindings/driver older than CUDA 13.2 makes the native
556+ ``cuMemcpyWithAttributesAsync`` path unavailable: the
557+ ``cuMemcpyAsync`` fallback reads the source in stream order
558+ only , which cannot honor that guarantee.
539559 """
540560 cdef Stream s = Stream_accept(stream)
541561 cdef size_t dst_size = self ._size
0 commit comments