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

1# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 

2# 

3# SPDX-License-Identifier: Apache-2.0 

4  

5from libc.stdint cimport uintptr_t 

6from libc.stdlib cimport malloc 

7from libc.string cimport memcpy as c_memcpy 

8  

9from cuda.bindings cimport cydriver 

10  

11from cuda.core._resource_handles cimport ( 

12 OpaqueHandle, 

13 make_opaque_malloc, 

14 make_opaque_py, 

15) 

16  

17import ctypes as ct 

18  

19  

20cdef void _py_host_trampoline(void* data) noexcept with gil: 

21 (<object>data)() 

22  

23  

24cdef bint _is_py_host_trampoline(cydriver.CUhostFn fn) noexcept nogil: 

25 return fn == <cydriver.CUhostFn>_py_host_trampoline 1efghi

26  

27  

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. 

34  

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

62  

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