Coverage for cuda/core/graph/_host_callback.pyx: 84.62%
26 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-29 01:38 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-29 01:38 +0000
1# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2#
3# SPDX-License-Identifier: Apache-2.0
5from libc.stdint cimport uintptr_t
6from libc.stdlib cimport malloc
7from libc.string cimport memcpy as c_memcpy
9from cuda.bindings cimport cydriver
11from cuda.core._resource_handles cimport (
12 OpaqueHandle,
13 make_opaque_malloc,
14 make_opaque_py,
15)
17import ctypes as ct
20cdef void _py_host_trampoline(void* data) noexcept with gil:
21 (<object>data)()
24cdef bint _is_py_host_trampoline(cydriver.CUhostFn fn) noexcept nogil:
25 return fn == <cydriver.CUhostFn>_py_host_trampoline 1efghi
28cdef void _resolve_host_callback(
29 object fn, object user_data,
30 cydriver.CUhostFn* out_fn, void** out_user_data,
31 OpaqueHandle* out_fn_owner, OpaqueHandle* out_data_owner) except *:
32 """Resolve a Python callable or ctypes CFuncPtr into a C callback pair and
33 the owners that keep it alive.
35 On return ``*out_fn`` / ``*out_user_data`` are ready to pass to
36 ``cuGraphAddHostNode`` or ``cuLaunchHostFunc``. ``*out_fn_owner`` owns the
37 callback object; ``*out_data_owner`` owns a copied ``user_data`` buffer and
38 is left null otherwise. The caller attaches both owners to the graph node.
39 """
40 if isinstance(fn, ct._CFuncPtr): 2l a b m j c sbn o p q r s t u v w x y z A B e C D d E f F G H I J K L M N O g P h Q i R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrb
41 out_fn[0] = <cydriver.CUhostFn><uintptr_t>ct.cast(fn, ct.c_void_p).value 1abcnqsuwyAdE
42 if user_data is None: 1abcnqsuwyAdE
43 out_user_data[0] = NULL 1nqsuwyAE
44 elif isinstance(user_data, int): 1abcd
45 out_user_data[0] = <void*><uintptr_t>user_data
46 else:
47 buf = bytes(user_data) 1abcd
48 if len(buf): 1abcd
49 out_user_data[0] = malloc(len(buf)) 1abcd
50 if out_user_data[0] == NULL: 1abcd
51 raise MemoryError("failed to allocate user_data buffer")
52 c_memcpy(out_user_data[0], <const char*>buf, len(buf)) 1abcd
53 out_data_owner[0] = make_opaque_malloc(out_user_data[0]) 1abcd
54 else:
55 out_user_data[0] = NULL
56 else:
57 if user_data is not None: 2l m j sbo p r t v x z B e C D f F G H I J K L M N O g P h Q i R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrb
58 raise ValueError( 2j sb
59 "user_data is only supported with ctypes function pointers")
60 out_fn[0] = <cydriver.CUhostFn>_py_host_trampoline 2l m j o p r t v x z B e C D f F G H I J K L M N O g P h Q i R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrb
61 out_user_data[0] = <void*>fn 2l m j o p r t v x z B e C D f F G H I J K L M N O g P h Q i R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrb
63 out_fn_owner[0] = make_opaque_py(fn) 2l a b m j c n o p q r s t u v w x y z A B e C D d E f F G H I J K L M N O g P h Q i R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrb