From 1b3dff41d2eb53fbda936845d45041d1a30c154d Mon Sep 17 00:00:00 2001 From: carvalhof Date: Tue, 12 Mar 2024 10:34:46 -0400 Subject: [PATCH 1/4] [runtime] Enhancement: Create into_buf in MemoryRuntime --- src/rust/runtime/memory/mod.rs | 63 ++++++++++++++++------------------ 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/src/rust/runtime/memory/mod.rs b/src/rust/runtime/memory/mod.rs index 121c8006c..5276dd4f7 100644 --- a/src/rust/runtime/memory/mod.rs +++ b/src/rust/runtime/memory/mod.rs @@ -61,6 +61,28 @@ pub trait MemoryRuntime { }) } + /// Converts a scatter-gather array into a buffer. + fn into_buf(&self, sga: &demi_sgarray_t) -> Result { + // Check arguments. + // TODO: Drop this check once we support scatter-gather arrays with multiple segments. + if sga.sga_numsegs != 1 { + return Err(Fail::new(libc::EINVAL, "demi_sgarray_t has invalid segment count")); + } + + if sga.sga_buf == ptr::null_mut() { + return Err(Fail::new(libc::EINVAL, "demi_sgarray_t has invalid DemiBuffer token")); + } + + // Convert back to a DemiBuffer + // Safety: The `NonNull::new_unchecked()` call is safe, as we verified `sga.sga_buf` is not null above. + let token: NonNull = unsafe { NonNull::new_unchecked(sga.sga_buf as *mut u8) }; + // Safety: The `DemiBuffer::from_raw()` call *should* be safe, as the `sga_buf` field in the `demi_sgarray_t` + // contained a valid `DemiBuffer` token when we provided it to the user (and the user shouldn't change it). + let buf: DemiBuffer = unsafe { DemiBuffer::from_raw(token) }; + + Ok(buf) + } + /// Allocates a scatter-gather array. fn sgaalloc(&self, size: usize) -> Result { // TODO: Allocate an array of buffers if requested size is too large for a single buffer. @@ -98,45 +120,18 @@ pub trait MemoryRuntime { /// Releases a scatter-gather array. fn sgafree(&self, sga: demi_sgarray_t) -> Result<(), Fail> { - // Check arguments. - // TODO: Drop this check once we support scatter-gather arrays with multiple segments. - if sga.sga_numsegs != 1 { - return Err(Fail::new(libc::EINVAL, "demi_sgarray_t has invalid segment count")); - } - - if sga.sga_buf == ptr::null_mut() { - return Err(Fail::new(libc::EINVAL, "demi_sgarray_t has invalid DemiBuffer token")); + match self.into_buf(&sga) { + Ok(buf) => { + drop(buf); + Ok(()) + }, + Err(e) => Err(e), } - - // Convert back to a DemiBuffer and drop it. - // Safety: The `NonNull::new_unchecked()` call is safe, as we verified `sga.sga_buf` is not null above. - let token: NonNull = unsafe { NonNull::new_unchecked(sga.sga_buf as *mut u8) }; - // Safety: The `DemiBuffer::from_raw()` call *should* be safe, as the `sga_buf` field in the `demi_sgarray_t` - // contained a valid `DemiBuffer` token when we provided it to the user (and the user shouldn't change it). - let buf: DemiBuffer = unsafe { DemiBuffer::from_raw(token) }; - drop(buf); - - Ok(()) } /// Clones a scatter-gather array. fn clone_sgarray(&self, sga: &demi_sgarray_t) -> Result { - // Check arguments. - // TODO: Drop this check once we support scatter-gather arrays with multiple segments. - if sga.sga_numsegs != 1 { - return Err(Fail::new(libc::EINVAL, "demi_sgarray_t has invalid segment count")); - } - - if sga.sga_buf == ptr::null_mut() { - return Err(Fail::new(libc::EINVAL, "demi_sgarray_t has invalid DemiBuffer token")); - } - - // Convert back to a DemiBuffer. - // Safety: The `NonNull::new_unchecked()` call is safe, as we verified `sga.sga_buf` is not null above. - let token: NonNull = unsafe { NonNull::new_unchecked(sga.sga_buf as *mut u8) }; - // Safety: The `DemiBuffer::from_raw()` call *should* be safe, as the `sga_buf` field in the `demi_sgarray_t` - // contained a valid `DemiBuffer` token when we provided it to the user (and the user shouldn't change it). - let buf: DemiBuffer = unsafe { DemiBuffer::from_raw(token) }; + let buf: DemiBuffer = self.into_buf(sga)?; let mut clone: DemiBuffer = buf.clone(); // Don't drop buf, as it holds the same reference to the data as the sgarray (which should keep it). From e15aac7e63893b6ae450b29149c67133b41d32dd Mon Sep 17 00:00:00 2001 From: carvalhof Date: Tue, 12 Mar 2024 10:43:33 -0400 Subject: [PATCH 2/4] [libos] Enhancement: Update push function --- src/rust/demikernel/libos/network/libos.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rust/demikernel/libos/network/libos.rs b/src/rust/demikernel/libos/network/libos.rs index 26ead50ca..22ac367d9 100644 --- a/src/rust/demikernel/libos/network/libos.rs +++ b/src/rust/demikernel/libos/network/libos.rs @@ -355,7 +355,9 @@ impl SharedNetworkLibOS { /// coroutine that asynchronously runs the push and any synchronous multi-queue functionality before the push /// begins. pub fn push(&mut self, qd: QDesc, sga: &demi_sgarray_t) -> Result { - let buf: DemiBuffer = self.transport.clone_sgarray(sga)?; + trace!("push() qd={:?}", qd); + + let buf: DemiBuffer = self.transport.into_buf(sga)?; if buf.len() == 0 { let cause: String = format!("zero-length buffer"); warn!("push(): {}", cause); From c95288b33686ae4229b2da70ac74d09f84948e9a Mon Sep 17 00:00:00 2001 From: carvalhof Date: Tue, 12 Mar 2024 10:47:45 -0400 Subject: [PATCH 3/4] [libos] Enhancement: Update pushto function --- src/rust/demikernel/libos/network/libos.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/demikernel/libos/network/libos.rs b/src/rust/demikernel/libos/network/libos.rs index 22ac367d9..24a974316 100644 --- a/src/rust/demikernel/libos/network/libos.rs +++ b/src/rust/demikernel/libos/network/libos.rs @@ -402,7 +402,7 @@ impl SharedNetworkLibOS { pub fn pushto(&mut self, qd: QDesc, sga: &demi_sgarray_t, remote: SocketAddr) -> Result { trace!("pushto() qd={:?}", qd); - let buf: DemiBuffer = self.transport.clone_sgarray(sga)?; + let buf: DemiBuffer = self.transport.into_buf(sga)?; if buf.len() == 0 { return Err(Fail::new(libc::EINVAL, "zero-length buffer")); } From f73cb797929b165353361cf1c8e92cda90f208f7 Mon Sep 17 00:00:00 2001 From: carvalhof Date: Mon, 8 Apr 2024 17:11:08 -0400 Subject: [PATCH 4/4] [runtime] Enhancement: Create unit tests --- src/rust/runtime/memory/mod.rs | 53 ++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/rust/runtime/memory/mod.rs b/src/rust/runtime/memory/mod.rs index 5276dd4f7..f87849e52 100644 --- a/src/rust/runtime/memory/mod.rs +++ b/src/rust/runtime/memory/mod.rs @@ -173,3 +173,56 @@ pub trait MemoryRuntime { Ok(clone) } } + +//====================================================================================================================== +// Unit Tests +//====================================================================================================================== + +#[cfg(test)] +mod tests { + use crate::{ + expect_ok, + demi_sgarray_t, + runtime::memory::MemoryRuntime, + }; + use ::test::{ + black_box, + Bencher, + }; + + // The buffer size. + const BUFSIZE: usize = 1024; + + pub struct DummyRuntime { } + + impl MemoryRuntime for DummyRuntime {} + + #[bench] + fn benchmark_clone_sgarray(b: &mut Bencher) { + let runtime: DummyRuntime = DummyRuntime { }; + + let sga: demi_sgarray_t = match runtime.sgaalloc(BUFSIZE) { + Ok(sga) => sga, + Err(e) => panic!("failed to allocate sgarray: {:?}", e), + }; + + b.iter(|| { + black_box(expect_ok!(runtime.clone_sgarray(&sga), "failed to clone sgarray")); + }); + } + + #[bench] + fn benchmark_into_buf(b: &mut Bencher) { + let runtime: DummyRuntime = DummyRuntime { }; + + let sga: demi_sgarray_t = match runtime.sgaalloc(BUFSIZE) { + Ok(sga) => sga, + Err(e) => panic!("failed to allocate sgarray: {:?}", e), + }; + + b.iter(|| { + black_box(expect_ok!(runtime.into_buf(&sga), "failed to convert sgarray")); + }); + } + +} \ No newline at end of file