-
Notifications
You must be signed in to change notification settings - Fork 0
Fixed buffer pool #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
3221ce0
22dfee8
ff98c60
a8f4e74
e1c1ec5
a575b30
1b67f1a
4fde269
faec133
f67f1e3
3f7d1d5
7106610
561c91a
bdf7900
7716cca
ee14daa
3926f5b
5fe79f1
c876027
9ea1a08
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,3 +5,4 @@ pub mod mock_store; | |
| pub mod rpc; | ||
| pub mod utils; | ||
| pub use io_mode::IoMode; | ||
| pub mod memory; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| use std::{io, os::raw::c_void, ptr::null_mut}; | ||
|
|
||
| use io_uring::IoUring; | ||
|
|
||
| use crate::memory::{ | ||
| page::Slice, pool::{FIXED_BUFFER_BITS, FIXED_BUFFER_SIZE_BYTES}, segment::{SEGMENT_SIZE, SEGMENT_SIZE_BITS, Segment} | ||
| }; | ||
|
|
||
| pub struct Arena { | ||
| size: usize, | ||
| slices: Vec<Slice>, | ||
| used_bitmap: Vec<u8>, | ||
| /** | ||
| * Segments need to be aligned to 32MB boundaries. Hence the first segment's starting address | ||
| * could be different from the starting address of the allocated memory | ||
| */ | ||
| aligned_start_ptr: *mut u8, | ||
| actual_start_ptr: *mut u8, | ||
| buffers_registered: bool, | ||
| } | ||
|
|
||
| unsafe impl Send for Arena {} | ||
| unsafe impl Sync for Arena {} | ||
|
|
||
| impl Arena { | ||
| pub fn new(capacity: usize) -> Arena { | ||
| let mem_start = Self::allocate_memory_from_os(capacity); | ||
| assert_ne!(mem_start, null_mut()); | ||
| let mem_end = mem_start.wrapping_add(capacity); | ||
| let ptr_aligned = (mem_start as usize >> SEGMENT_SIZE_BITS) << SEGMENT_SIZE_BITS; | ||
| let mut slice_start = ptr_aligned; | ||
| if ptr_aligned != (mem_start as usize) { | ||
| slice_start = ptr_aligned + SEGMENT_SIZE; | ||
| } | ||
| let mut slices = Vec::new(); | ||
| while slice_start + SEGMENT_SIZE <= mem_end as usize { | ||
| slices.push(Slice { | ||
| ptr: slice_start as *mut u8, | ||
| size: SEGMENT_SIZE, | ||
| }); | ||
| slice_start += SEGMENT_SIZE; | ||
| } | ||
| let mut used_bitmap = Vec::new(); | ||
| used_bitmap.resize(slices.len(), 0); | ||
|
|
||
| Arena { | ||
| size: capacity, | ||
| slices: slices, | ||
| used_bitmap: used_bitmap, | ||
| aligned_start_ptr: ptr_aligned as *mut u8, | ||
| actual_start_ptr: mem_start, | ||
| buffers_registered: false, | ||
| } | ||
| } | ||
|
|
||
| fn allocate_memory_from_os(capacity: usize) -> *mut u8 { | ||
| let prot = libc::PROT_READ | libc::PROT_WRITE; | ||
| let flags = libc::MAP_ANONYMOUS | libc::MAP_PRIVATE; | ||
| unsafe { libc::mmap64(null_mut(), capacity, prot, flags, -1, 0) as *mut u8 } | ||
| } | ||
|
|
||
| pub fn allocate_segment(self: &mut Self, size: usize) -> Option<*mut Segment> { | ||
| let num_slices = (size + SEGMENT_SIZE - 1) / SEGMENT_SIZE; | ||
| let mut contiguous = 0; | ||
| let mut result: i32 = -1; | ||
|
|
||
| for index in 0..self.used_bitmap.len() { | ||
| let bit = self.used_bitmap[index]; | ||
| if bit == 0 { | ||
| contiguous += 1; | ||
| if contiguous == num_slices { | ||
| result = (index + 1 - contiguous) as i32; | ||
| break; | ||
| } | ||
| } else { | ||
| contiguous = 0; | ||
| } | ||
| } | ||
| if result == -1 { | ||
| return None; | ||
| } | ||
| for i in 0..contiguous { | ||
| self.used_bitmap[result as usize + i] = 1; | ||
| } | ||
| let combined_slice = Slice { | ||
| ptr: self.slices[result as usize].ptr, | ||
| size: num_slices * SEGMENT_SIZE, | ||
| }; | ||
| Some(Segment::new_from_slice(combined_slice)) | ||
| } | ||
|
|
||
| pub(crate) fn start_ptr(self: &Self) -> *mut u8 { | ||
| self.aligned_start_ptr | ||
| } | ||
|
|
||
| pub(crate) fn retire_segment(self: &mut Self, segment: *mut Segment) { | ||
| debug_assert!((self.slices[0].ptr as usize) <= segment as usize); | ||
| let segment_idx = (segment as usize - self.slices[0].ptr as usize) / SEGMENT_SIZE; | ||
| self.used_bitmap[segment_idx] = 0; | ||
|
Comment on lines
+96
to
+99
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
| } | ||
|
Comment on lines
+96
to
+100
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The pub(crate) fn retire_segment(self: &mut Self, segment: *mut Segment) {
if self.slices.is_empty() {
return;
}
debug_assert!((self.slices[0].ptr as usize) <= segment as usize);
let segment_idx = (segment as usize - self.slices[0].ptr as usize) / SEGMENT_SIZE;
self.used_bitmap[segment_idx] = 0;
} |
||
|
|
||
| pub(crate) fn register_buffers_with_ring(self: &mut Self, ring: &IoUring) -> io::Result<()> { | ||
| let num_buffers = self.size >> FIXED_BUFFER_BITS; | ||
| let mut buffers = Vec::<libc::iovec>::new(); | ||
| buffers.reserve(num_buffers); | ||
| let mut base_ptr = self.aligned_start_ptr; | ||
| for _i in 0..num_buffers { | ||
| buffers.push(libc::iovec {iov_base: base_ptr as *mut std::ffi::c_void, iov_len: FIXED_BUFFER_SIZE_BYTES}); | ||
| base_ptr = base_ptr.wrapping_add(FIXED_BUFFER_SIZE_BYTES); | ||
| } | ||
| let res = unsafe { | ||
| ring.submitter().register_buffers(&buffers) | ||
| }; | ||
| self.buffers_registered = res.is_ok(); | ||
| res | ||
| } | ||
| } | ||
|
|
||
| impl Drop for Arena { | ||
| fn drop(self: &mut Self) { | ||
| unsafe { | ||
| libc::munmap(self.actual_start_ptr as *mut c_void, self.size); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,6 @@ | ||||||
| pub mod page; | ||||||
| pub mod pool; | ||||||
| mod segment; | ||||||
| mod arena; | ||||||
| mod global_pool; | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This module declaration for
Suggested change
|
||||||
| mod tcache; | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.slicescan be empty if the arena is created with a capacity smaller thanSEGMENT_SIZE. Accessingself.slices[0]on this line would cause a panic in that case. It's better to handle this case gracefully, for example by adding a check forself.slices.is_empty()before this line.