@@ -4,8 +4,9 @@ use std::ffi::CString;
44use std:: os:: raw:: c_void;
55use std:: ptr;
66// use async_trait::async_trait;
7- use crate :: { check_err, Error , InferenceRequest , InferenceResponse } ;
8- use crate :: Server ;
7+ use crate :: { check_err, Error , InferenceRequest , InferenceResponse , Server } ;
8+ #[ cfg( not( test) ) ]
9+ use crate :: to_TRITONSERVER_Error;
910use tokio:: sync:: oneshot;
1011
1112// // #[async_trait]
@@ -119,61 +120,171 @@ extern "C" fn response_alloc(
119120 unsafe {
120121 * actual_memory_type = preferred_memory_type;
121122 * actual_memory_type_id = preferred_memory_type_id;
122-
123- if byte_size == 0 {
123+ }
124+ if byte_size == 0 {
125+ unsafe {
124126 * buffer = ptr:: null_mut ( ) ;
125127 * buffer_userp = ptr:: null_mut ( ) ;
126- return ptr:: null_mut ( ) ;
127128 }
129+ return ptr:: null_mut ( ) ;
130+ }
128131
129- let allocated_ptr = match preferred_memory_type {
130- // Implement memory allocation based on type (CPU/GPU)
131- _ => libc:: malloc ( byte_size) ,
132- } ;
132+ let allocated_ptr = match preferred_memory_type {
133+ // Implement memory allocation based on type (CPU/GPU)
134+ triton_sys:: TRITONSERVER_memorytype_enum_TRITONSERVER_MEMORY_CPU => unsafe {
135+ libc:: malloc ( byte_size)
136+ } ,
137+ triton_sys:: TRITONSERVER_memorytype_enum_TRITONSERVER_MEMORY_CPU_PINNED =>
138+ unsafe {
139+ * actual_memory_type =
140+ triton_sys:: TRITONSERVER_memorytype_enum_TRITONSERVER_MEMORY_CPU ;
141+ * actual_memory_type_id = 0 ;
142+ libc:: malloc ( byte_size)
143+ } ,
144+ triton_sys:: TRITONSERVER_memorytype_enum_TRITONSERVER_MEMORY_GPU => {
145+ return to_TRITONSERVER_Error ( "GPU memory not implemented" . into ( ) ) ;
146+ } ,
147+ _ => {
148+ return to_TRITONSERVER_Error ( "Invalid memory type requested" . into ( ) ) ;
149+ } ,
150+ } ;
133151
134- if !allocated_ptr. is_null ( ) {
135- * buffer = allocated_ptr;
136- * buffer_userp = Box :: into_raw ( Box :: new ( CString :: from_vec_unchecked (
137- std:: ffi:: CStr :: from_ptr ( tensor_name) . to_bytes ( ) . to_vec ( ) ,
138- ) ) ) as * mut c_void ;
139- }
152+ if allocated_ptr. is_null ( ) {
153+ return to_TRITONSERVER_Error ( "Failed to allocate memory for response" . into ( ) ) ;
154+ }
140155
141- ptr:: null_mut ( ) // Success
156+ // Store tensor name on Rust heap
157+ let tensor_name = unsafe { CString :: from_vec_unchecked (
158+ std:: ffi:: CStr :: from_ptr ( tensor_name) . to_bytes ( ) . to_vec ( ) ) } ;
159+ let tensor_name = Box :: into_raw ( Box :: new ( tensor_name) ) ;
160+ unsafe {
161+ * buffer = allocated_ptr;
162+ * buffer_userp = tensor_name as * mut c_void ;
142163 }
164+
165+ ptr:: null_mut ( ) // Success
143166}
144167
145168extern "C" fn response_release (
146169 _allocator : * mut triton_sys:: TRITONSERVER_ResponseAllocator ,
147170 buffer : * mut c_void ,
148171 buffer_userp : * mut c_void ,
149- _byte_size : libc:: size_t ,
172+ byte_size : libc:: size_t ,
150173 memory_type : triton_sys:: TRITONSERVER_MemoryType ,
151174 _memory_type_id : i64 ,
152175) -> * mut triton_sys:: TRITONSERVER_Error {
153- unsafe {
154- if !buffer. is_null ( ) {
155- match memory_type {
156- triton_sys:: TRITONSERVER_memorytype_enum_TRITONSERVER_MEMORY_CPU => {
157- libc:: free ( buffer)
158- }
159- _ => libc:: free ( buffer) , // Simplified for example
160- } ;
161- }
162-
163- if !buffer_userp. is_null ( ) {
164- drop ( Box :: from_raw ( buffer_userp as * mut CString ) ) ;
176+ if !buffer. is_null ( ) {
177+ match memory_type {
178+ triton_sys:: TRITONSERVER_memorytype_enum_TRITONSERVER_MEMORY_CPU =>
179+ unsafe {
180+ // Detect use after free errors
181+ libc:: free ( libc:: memset ( buffer, 123 , byte_size) ) ;
182+ // libc::free(buffer);
183+ } ,
184+ _ => unimplemented ! ( "Memory type not implemented" ) ,
165185 }
186+ }
166187
167- ptr:: null_mut ( ) // Success
188+ if !buffer_userp. is_null ( ) {
189+ let tensor_name = unsafe { Box :: from_raw ( buffer_userp as * mut CString ) } ;
190+ drop ( tensor_name) ;
168191 }
192+
193+ ptr:: null_mut ( ) // Success
169194}
170195
171196#[ cfg( test) ]
172197mod tests {
173- // use super::*;
174- // use std::ptr;
198+ use super :: * ;
199+ use std:: ptr;
175200// use tokio::test;
176- //
201+
202+ #[ test]
203+ fn test_allocation_cpu ( ) {
204+ let allocator = ptr:: null_mut ( ) ;
205+ let tensor_name = c"foo" ;
206+ let byte_size: libc:: size_t = 123 ;
207+ let mut memory_type =
208+ triton_sys:: TRITONSERVER_memorytype_enum_TRITONSERVER_MEMORY_CPU ;
209+ let mut memory_type_id: i64 = 321 ;
210+ let mut buffer = ptr:: null_mut ( ) ;
211+ let mut buffer_userp = ptr:: null_mut ( ) ;
212+
213+ let r = response_alloc ( allocator, tensor_name. as_ptr ( ) , byte_size,
214+ memory_type, memory_type_id, ptr:: null_mut ( ) ,
215+ & mut buffer, & mut buffer_userp,
216+ & mut memory_type, & mut memory_type_id) ;
217+ assert ! ( r. is_null( ) ) ;
218+ assert ! ( !buffer. is_null( ) ) ;
219+ assert ! ( !buffer_userp. is_null( ) ) ;
220+ assert_eq ! ( memory_type, 0 ) ;
221+ assert_eq ! ( memory_type_id, 321 ) ;
222+
223+ let slice: & mut [ u8 ] = unsafe {
224+ std:: slice:: from_raw_parts_mut ( buffer as * mut u8 , 123 )
225+ } ;
226+ slice[ 122 ] = 0xff ; // poke in buffer
227+ let tensor_name = unsafe { Box :: from_raw ( buffer_userp as * mut CString ) } ;
228+ assert_eq ! ( tensor_name. as_c_str( ) , c"foo" ) ; // peek
229+ Box :: leak ( tensor_name) ; // avoid double free
230+
231+ let r = response_release ( allocator, buffer, buffer_userp, byte_size,
232+ memory_type, memory_type_id) ;
233+ assert ! ( r. is_null( ) ) ;
234+ }
235+
236+ #[ test]
237+ fn test_allocation_cpu_pinned ( ) {
238+ let allocator = ptr:: null_mut ( ) ;
239+ let tensor_name = c"bar" ;
240+ let byte_size: libc:: size_t = 123 ;
241+ let mut memory_type =
242+ triton_sys:: TRITONSERVER_memorytype_enum_TRITONSERVER_MEMORY_CPU_PINNED ;
243+ let mut memory_type_id: i64 = 321 ;
244+ let mut buffer = ptr:: null_mut ( ) ;
245+ let mut buffer_userp = ptr:: null_mut ( ) ;
246+
247+ let r = response_alloc ( allocator, tensor_name. as_ptr ( ) , byte_size,
248+ memory_type, memory_type_id, ptr:: null_mut ( ) ,
249+ & mut buffer, & mut buffer_userp,
250+ & mut memory_type, & mut memory_type_id) ;
251+ assert ! ( r. is_null( ) ) ;
252+ assert ! ( !buffer. is_null( ) ) ;
253+ assert ! ( !buffer_userp. is_null( ) ) ;
254+ assert_eq ! ( memory_type, 0 ) ; // <-- changed PINNED -> Regular
255+ assert_eq ! ( memory_type_id, 0 ) ; // changed 321 -> 0
256+
257+ let slice: & mut [ u8 ] = unsafe {
258+ std:: slice:: from_raw_parts_mut ( buffer as * mut u8 , 123 )
259+ } ;
260+ slice[ 122 ] = 0xff ; // poke in buffer
261+ let tensor_name = unsafe { Box :: from_raw ( buffer_userp as * mut CString ) } ;
262+ assert_eq ! ( tensor_name. as_c_str( ) , c"bar" ) ; // peek
263+ Box :: leak ( tensor_name) ; // avoid double free
264+
265+ let r = response_release ( allocator, buffer, buffer_userp, byte_size,
266+ memory_type, memory_type_id) ;
267+ assert ! ( r. is_null( ) ) ;
268+ }
269+
270+ #[ test]
271+ fn test_allocation_gpu ( ) {
272+ let allocator = ptr:: null_mut ( ) ;
273+ let tensor_name = c"baz" ;
274+ let byte_size: libc:: size_t = 123 ;
275+ let mut memory_type =
276+ triton_sys:: TRITONSERVER_memorytype_enum_TRITONSERVER_MEMORY_GPU ;
277+ let mut memory_type_id: i64 = 321 ;
278+ let mut buffer = ptr:: null_mut ( ) ;
279+ let mut buffer_userp = ptr:: null_mut ( ) ;
280+
281+ let r = response_alloc ( allocator, tensor_name. as_ptr ( ) , byte_size,
282+ memory_type, memory_type_id, ptr:: null_mut ( ) ,
283+ & mut buffer, & mut buffer_userp,
284+ & mut memory_type, & mut memory_type_id) ;
285+ assert ! ( !r. is_null( ) ) ;
286+ }
287+
177288// #[test]
178289// async fn test_executor_creation() {
179290// // Create with null server pointer for test
@@ -184,3 +295,11 @@ mod tests {
184295// let executor = executor.unwrap();
185296// }
186297}
298+
299+ // TEST STUB
300+ #[ cfg( test) ]
301+ #[ allow( non_snake_case) ]
302+ pub fn to_TRITONSERVER_Error ( _err : Error ) -> * mut triton_sys:: TRITONSERVER_Error {
303+ std:: ptr:: NonNull :: < triton_sys:: TRITONSERVER_Error > :: dangling ( ) . as_ptr ( )
304+ }
305+
0 commit comments