1use crate::buffer::{
6 Buffer, BufferAllocator as BufferAllocatorTrait, OwnedBuffer, round_down, round_up,
7};
8use event_listener::{Event, EventListener, Listener as _};
9use fuchsia_sync::Mutex;
10use futures::{Future, FutureExt as _};
11use std::collections::BTreeMap;
12use std::ops::Range;
13use std::pin::Pin;
14use std::sync::Arc;
15use std::task::{Context, Poll};
16
17#[cfg(target_os = "fuchsia")]
18mod buffer_source {
19 use fuchsia_runtime::vmar_root_self;
20 use std::ops::Range;
21 use std::sync::Arc;
22 use storage_ptr_slice::MutPtrByteSlice;
23
24 #[derive(Debug)]
26 pub struct BufferSource {
27 base: *mut u8,
28 size: usize,
29 vmo: Arc<zx::Vmo>,
30 }
31
32 unsafe impl Send for BufferSource {}
35 unsafe impl Sync for BufferSource {}
36
37 impl BufferSource {
38 pub fn new(size: usize) -> Self {
39 let vmo = Arc::new(zx::Vmo::create(size as u64).unwrap());
40 let name = zx::Name::new("transfer-buf").unwrap();
41 vmo.set_name(&name).unwrap();
42 let flags = zx::VmarFlags::PERM_READ
43 | zx::VmarFlags::PERM_WRITE
44 | zx::VmarFlags::MAP_RANGE
45 | zx::VmarFlags::REQUIRE_NON_RESIZABLE;
46 let base = vmar_root_self().map(0, &vmo, 0, size, flags).unwrap() as *mut u8;
47 Self { base, size, vmo }
48 }
49
50 pub fn slice(&self) -> *mut [u8] {
51 std::ptr::slice_from_raw_parts_mut(self.base, self.size)
52 }
53
54 pub fn size(&self) -> usize {
55 self.size
56 }
57
58 pub fn vmo(&self) -> &Arc<zx::Vmo> {
59 &self.vmo
60 }
61
62 pub(super) unsafe fn subslice_ptr(&self, range: &Range<usize>) -> MutPtrByteSlice<'_> {
69 assert!(range.start < self.size && range.end <= self.size);
70 unsafe {
73 MutPtrByteSlice::new(std::ptr::slice_from_raw_parts_mut(
74 self.base.add(range.start),
75 range.len(),
76 ))
77 }
78 }
79
80 pub(super) unsafe fn subslice_ptr_unbounded<'a>(
88 &self,
89 range: &Range<usize>,
90 ) -> MutPtrByteSlice<'a> {
91 assert!(range.start < self.size && range.end <= self.size);
92 unsafe {
95 MutPtrByteSlice::new(std::ptr::slice_from_raw_parts_mut(
96 self.base.add(range.start),
97 range.len(),
98 ))
99 }
100 }
101
102 pub fn commit_range(&self, range: Range<usize>) -> Result<(), zx::Status> {
104 self.vmo.op_range(zx::VmoOp::COMMIT, range.start as u64, range.len() as u64)
105 }
106
107 pub(super) unsafe fn clean_range(&self, range: Range<usize>) {
113 let _ = self.vmo.op_range(zx::VmoOp::ZERO, range.start as u64, range.len() as u64);
114 }
115 }
116
117 impl Drop for BufferSource {
118 fn drop(&mut self) {
119 unsafe {
121 let _ = vmar_root_self().unmap(self.base as usize, self.size);
122 }
123 }
124 }
125}
126
127#[cfg(not(target_os = "fuchsia"))]
128mod buffer_source {
129 use std::cell::UnsafeCell;
130 use std::ops::Range;
131 use std::pin::Pin;
132 use storage_ptr_slice::MutPtrByteSlice;
133
134 #[derive(Debug)]
136 pub struct BufferSource {
137 data: UnsafeCell<Pin<Vec<u8>>>,
142 }
143
144 unsafe impl Sync for BufferSource {}
147
148 impl BufferSource {
149 pub fn new(size: usize) -> Self {
150 Self { data: UnsafeCell::new(Pin::new(vec![0 as u8; size])) }
151 }
152
153 pub fn size(&self) -> usize {
154 unsafe { (&*self.data.get()).len() }
156 }
157
158 pub(super) unsafe fn subslice_ptr(&self, range: &Range<usize>) -> MutPtrByteSlice<'_> {
165 assert!(range.start < self.size() && range.end <= self.size());
166 unsafe {
169 let ptr = (&mut *self.data.get()).as_mut_ptr().add(range.start);
170 MutPtrByteSlice::new(std::ptr::slice_from_raw_parts_mut(ptr, range.len()))
171 }
172 }
173
174 pub(super) unsafe fn subslice_ptr_unbounded<'a>(
182 &self,
183 range: &Range<usize>,
184 ) -> MutPtrByteSlice<'a> {
185 assert!(range.start < self.size() && range.end <= self.size());
186 unsafe {
189 let ptr = (&mut *self.data.get()).as_mut_ptr().add(range.start);
190 MutPtrByteSlice::new(std::ptr::slice_from_raw_parts_mut(ptr, range.len()))
191 }
192 }
193
194 pub(super) unsafe fn clean_range(&self, range: Range<usize>) {
200 unsafe { self.subslice_ptr(&range) }.fill(0);
202 }
203 }
204}
205
206pub use buffer_source::BufferSource;
207
208type FreeList = Vec<usize>;
212
213#[derive(Debug)]
214struct Inner {
215 free_lists: Vec<FreeList>,
217 allocation_map: BTreeMap<usize, usize>,
219}
220
221#[derive(Debug)]
225pub struct BufferAllocator {
226 block_size: usize,
227 source: BufferSource,
228 inner: Mutex<Inner>,
229 event: Event,
230}
231
232fn order(size: usize, block_size: usize) -> usize {
234 if size <= block_size {
235 return 0;
236 }
237 let nblocks = round_up(size, block_size) / block_size;
238 nblocks.next_power_of_two().trailing_zeros() as usize
239}
240
241fn order_fit(size: usize, block_size: usize) -> usize {
243 assert!(size >= block_size);
244 let nblocks = round_up(size, block_size) / block_size;
245 if nblocks.is_power_of_two() {
246 nblocks.trailing_zeros() as usize
247 } else {
248 nblocks.next_power_of_two().trailing_zeros() as usize - 1
249 }
250}
251
252fn size_for_order(order: usize, block_size: usize) -> usize {
253 block_size * (1 << (order as u32))
254}
255
256fn initial_free_lists(size: usize, block_size: usize) -> Vec<FreeList> {
257 let size = round_down(size, block_size);
258 assert!(block_size <= size);
259 assert!(block_size.is_power_of_two());
260 let max_order = order_fit(size, block_size);
261 let mut free_lists = Vec::with_capacity(max_order + 1);
262 for _ in 0..=max_order {
263 free_lists.push(FreeList::new())
264 }
265 let mut offset = 0;
266 while offset < size {
267 let order = order_fit(size - offset, block_size);
268 let size = size_for_order(order, block_size);
269 free_lists[order].push(offset);
270 offset += size;
271 }
272 free_lists
273}
274
275pub struct BufferFuture<'a> {
277 allocator: &'a BufferAllocator,
278 size: usize,
279 listener: Option<EventListener>,
280}
281
282impl<'a> Future for BufferFuture<'a> {
283 type Output = Buffer<'a>;
284
285 fn poll(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
286 if let Some(listener) = self.listener.as_mut() {
287 futures::ready!(listener.poll_unpin(context));
288 }
289 loop {
292 match self.allocator.try_allocate_buffer(self.size) {
293 Ok(buffer) => return Poll::Ready(buffer),
294 Err(mut listener) => {
295 if listener.poll_unpin(context).is_pending() {
296 self.listener = Some(listener);
297 return Poll::Pending;
298 }
299 }
300 }
301 }
302 }
303}
304
305impl BufferAllocator {
306 pub fn new(block_size: usize, source: BufferSource) -> Self {
307 let free_lists = initial_free_lists(source.size(), block_size);
308 Self {
309 block_size,
310 source,
311 inner: Mutex::new(Inner { free_lists, allocation_map: BTreeMap::new() }),
312 event: Event::new(),
313 }
314 }
315
316 pub fn block_size(&self) -> usize {
317 self.block_size
318 }
319
320 pub fn buffer_source(&self) -> &BufferSource {
321 &self.source
322 }
323
324 pub fn take_buffer_source(self) -> BufferSource {
326 self.source
327 }
328
329 pub fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
341 BufferFuture { allocator: self, size, listener: None }
342 }
343
344 pub fn allocate_buffer_sync(&self, size: usize) -> Buffer<'_> {
351 loop {
352 match self.try_allocate_buffer(size) {
353 Ok(buffer) => return buffer,
354 Err(listener) => listener.wait(),
355 }
356 }
357 }
358
359 pub fn allocate_buffer_sync_owned(self: &Arc<Self>, size: usize) -> OwnedBuffer {
366 loop {
367 match self.try_allocate_buffer_owned(size) {
368 Ok(buffer) => return buffer,
369 Err(listener) => listener.wait(),
370 }
371 }
372 }
373
374 pub fn try_allocate_buffer_owned(
381 self: &Arc<Self>,
382 size: usize,
383 ) -> Result<OwnedBuffer, EventListener> {
384 let buffer = self.try_allocate_buffer(size)?;
385 let range = buffer.range();
386 let slice = unsafe { self.source.subslice_ptr_unbounded(&range) };
391 std::mem::forget(buffer);
392 Ok(OwnedBuffer::new(slice, range, self.clone() as Arc<dyn BufferAllocatorTrait>))
393 }
394
395 pub fn try_allocate_buffer(&self, size: usize) -> Result<Buffer<'_>, EventListener> {
402 if size > self.source.size() {
403 panic!("Allocation of {} bytes would exceed limit {}", size, self.source.size());
404 }
405 let mut inner = self.inner.lock();
406 let requested_order = order(size, self.block_size());
407 assert!(requested_order < inner.free_lists.len());
408 let mut order = {
410 let mut idx = requested_order;
411 loop {
412 if idx >= inner.free_lists.len() {
413 return Err(self.event.listen());
414 }
415 if !inner.free_lists[idx].is_empty() {
416 break idx;
417 }
418 idx += 1;
419 }
420 };
421
422 let offset = inner.free_lists[order].pop().unwrap();
424 while order > requested_order {
425 order -= 1;
426 assert!(inner.free_lists[order].is_empty());
427 inner.free_lists[order].push(offset + self.size_for_order(order));
428 }
429
430 inner.allocation_map.insert(offset, self.size_for_order(order));
431 let range = offset..offset + size;
432 log::debug!(range:?, bytes_used = self.size_for_order(order); "Allocated");
433
434 Ok(Buffer::new(unsafe { self.source.subslice_ptr(&range) }, range, self))
437 }
438}
439
440impl BufferAllocatorTrait for BufferAllocator {
441 fn free_buffer(&self, range: Range<usize>) {
442 self.free_buffer(range);
443 }
444}
445
446impl BufferAllocator {
447 #[doc(hidden)]
449 pub(super) fn free_buffer(&self, range: Range<usize>) {
450 let mut inner = self.inner.lock();
451 let mut offset = range.start;
452 let size = inner
453 .allocation_map
454 .remove(&offset)
455 .unwrap_or_else(|| panic!("No allocation record found for {:?}", range));
456 assert!(range.end - range.start <= size);
457 log::debug!(range:?, bytes_used = size; "Freeing");
458
459 let mut order = order(size, self.block_size());
461 while order < inner.free_lists.len() - 1 {
462 let buddy = self.find_buddy(offset, order);
463 let idx = if let Ok(idx) = inner.free_lists[order].binary_search(&buddy) {
464 idx
465 } else {
466 break;
467 };
468 inner.free_lists[order].remove(idx);
469 offset = std::cmp::min(offset, buddy);
470 order += 1;
471 }
472
473 let idx = match inner.free_lists[order].binary_search(&offset) {
474 Ok(_) => panic!("Unexpectedly found {} in free list {}", offset, order),
475 Err(idx) => idx,
476 };
477 inner.free_lists[order].insert(idx, offset);
478
479 self.event.notify(usize::MAX);
481 }
482
483 fn size_for_order(&self, order: usize) -> usize {
484 size_for_order(order, self.block_size)
485 }
486
487 fn find_buddy(&self, offset: usize, order: usize) -> usize {
488 offset ^ self.size_for_order(order)
489 }
490
491 pub fn clean_transfer_buffer(&self) {
493 let inner = self.inner.lock();
494 for (n, free_list) in inner.free_lists.iter().enumerate() {
495 for offset in free_list {
496 unsafe {
498 self.source.clean_range(*offset..(*offset + size_for_order(n, self.block_size)))
499 };
500 }
501 }
502 }
503}
504
505#[cfg(test)]
506mod tests {
507 use crate::buffer_allocator::{BufferAllocator, BufferSource, order};
508 use fuchsia_async as fasync;
509 use futures::future::join_all;
510 use futures::pin_mut;
511 use rand::seq::IndexedRandom;
512 use rand::{Rng, rng};
513 use std::sync::Arc;
514 use std::sync::atomic::{AtomicBool, Ordering};
515
516 #[fuchsia::test]
517 async fn test_odd_sized_buffer_source() {
518 let source = BufferSource::new(123);
519 let allocator = BufferAllocator::new(2, source);
520
521 let sizes = vec![64, 32, 16, 8, 2];
523 let mut bufs = vec![];
524 for size in sizes.iter() {
525 bufs.push(allocator.allocate_buffer(*size).await);
526 }
527 for (expected_size, buf) in sizes.iter().zip(bufs.iter()) {
528 assert_eq!(*expected_size, buf.len());
529 }
530 assert!(allocator.try_allocate_buffer(2).is_err());
531 }
532
533 #[fuchsia::test]
534 async fn test_allocate_buffer_read_write() {
535 let source = BufferSource::new(1024 * 1024);
536 let allocator = BufferAllocator::new(8192, source);
537
538 let mut buf = allocator.allocate_buffer(8192).await;
539 buf.as_mut_slice().fill(0xaa as u8);
540 let mut vec = vec![0 as u8; 8192];
541 vec.copy_from_slice(buf.as_slice());
542 assert_eq!(vec, vec![0xaa as u8; 8192]);
543 }
544
545 #[fuchsia::test]
546 async fn test_allocate_buffer_consecutive_calls_do_not_overlap() {
547 let source = BufferSource::new(1024 * 1024);
548 let allocator = BufferAllocator::new(8192, source);
549
550 let buf1 = allocator.allocate_buffer(8192).await;
551 let buf2 = allocator.allocate_buffer(8192).await;
552 assert!(buf1.range().end <= buf2.range().start || buf2.range().end <= buf1.range().start);
553 }
554
555 #[fuchsia::test]
556 async fn test_allocate_many_buffers() {
557 let source = BufferSource::new(1024 * 1024);
558 let allocator = BufferAllocator::new(8192, source);
559
560 for _ in 0..10 {
561 let _ = allocator.allocate_buffer(8192).await;
562 }
563 }
564
565 #[fuchsia::test]
566 async fn test_allocate_small_buffers_dont_overlap() {
567 let source = BufferSource::new(1024 * 1024);
568 let allocator = BufferAllocator::new(8192, source);
569
570 let buf1 = allocator.allocate_buffer(1).await;
571 let buf2 = allocator.allocate_buffer(1).await;
572 assert!(buf1.range().end <= buf2.range().start || buf2.range().end <= buf1.range().start);
573 }
574
575 #[fuchsia::test]
576 async fn test_allocate_large_buffer() {
577 let source = BufferSource::new(1024 * 1024);
578 let allocator = BufferAllocator::new(8192, source);
579
580 let mut buf = allocator.allocate_buffer(1024 * 1024).await;
581 assert_eq!(buf.len(), 1024 * 1024);
582 buf.as_mut_slice().fill(0xaa as u8);
583 let mut vec = vec![0 as u8; 1024 * 1024];
584 vec.copy_from_slice(buf.as_slice());
585 assert_eq!(vec, vec![0xaa as u8; 1024 * 1024]);
586 }
587
588 #[fuchsia::test]
589 async fn test_allocate_large_buffer_after_smaller_buffers() {
590 let source = BufferSource::new(1024 * 1024);
591 let allocator = BufferAllocator::new(8192, source);
592
593 {
594 let mut buffers = vec![];
595 while let Ok(buffer) = allocator.try_allocate_buffer(8192) {
596 buffers.push(buffer);
597 }
598 }
599 let buf = allocator.allocate_buffer(1024 * 1024).await;
600 assert_eq!(buf.len(), 1024 * 1024);
601 }
602
603 #[fuchsia::test]
604 async fn test_allocate_at_limits() {
605 let source = BufferSource::new(1024 * 1024);
606 let allocator = BufferAllocator::new(8192, source);
607
608 let mut buffers = vec![];
609 while let Ok(buffer) = allocator.try_allocate_buffer(8192) {
610 buffers.push(buffer);
611 }
612 buffers.pop();
614 let buf = allocator.allocate_buffer(8192).await;
615 assert_eq!(buf.len(), 8192);
616 }
617
618 #[fuchsia::test(threads = 10)]
619 async fn test_random_allocs_deallocs() {
620 let source = BufferSource::new(16 * 1024 * 1024);
621 let bs = 512;
622 let allocator = Arc::new(BufferAllocator::new(bs, source));
623
624 join_all((0..10).map(|_| {
625 let allocator = allocator.clone();
626 fasync::Task::spawn(async move {
627 let mut rng = rng();
628 enum Op {
629 Alloc,
630 Dealloc,
631 }
632 let ops = vec![Op::Alloc, Op::Dealloc];
633 let mut buffers = vec![];
634 for _ in 0..1000 {
635 match ops.choose(&mut rng).unwrap() {
636 Op::Alloc => {
637 let order: usize = rng.random_range(order(1, bs)..order(65536 + 1, bs));
642 let size: usize = rng.random_range(
643 bs * 2_usize.pow(order as u32)..bs * 2_usize.pow(order as u32 + 1),
644 );
645 if let Ok(mut buf) = allocator.try_allocate_buffer(size) {
646 let val = rng.random::<u8>();
647 buf.as_mut_slice().fill(val);
648 for v in buf.as_slice() {
649 assert_eq!(v, &val);
650 }
651 buffers.push(buf);
652 }
653 }
654 Op::Dealloc if !buffers.is_empty() => {
655 let idx = rng.random_range(0..buffers.len());
656 buffers.remove(idx);
657 }
658 _ => {}
659 };
660 }
661 })
662 }))
663 .await;
664 }
665
666 #[fuchsia::test]
667 async fn test_buffer_refs() {
668 let source = BufferSource::new(1024 * 1024);
669 let allocator = BufferAllocator::new(512, source);
670
671 let _buf = allocator.allocate_buffer(512).await;
674 let mut buf = allocator.allocate_buffer(4096).await;
675 let base = buf.range().start;
676 {
677 let mut bref = buf.subslice_mut(1000..2000);
678 assert_eq!(bref.len(), 1000);
679 assert_eq!(bref.range(), base + 1000..base + 2000);
680 bref.as_mut_slice().fill(0xbb);
681 {
682 let mut bref2 = bref.reborrow().subslice_mut(0..100);
683 assert_eq!(bref2.len(), 100);
684 assert_eq!(bref2.range(), base + 1000..base + 1100);
685 bref2.as_mut_slice().fill(0xaa);
686 }
687 {
688 let mut bref2 = bref.reborrow().subslice_mut(900..1000);
689 assert_eq!(bref2.len(), 100);
690 assert_eq!(bref2.range(), base + 1900..base + 2000);
691 bref2.as_mut_slice().fill(0xcc);
692 }
693 assert_eq!(bref.as_slice()[..100], vec![0xaa; 100]);
694 assert_eq!(bref.as_slice()[100..900], vec![0xbb; 800]);
695
696 let bref = bref.subslice_mut(900..);
697 assert_eq!(bref.len(), 100);
698 assert_eq!(bref.as_slice(), vec![0xcc; 100]);
699 }
700 {
701 let bref = buf.as_ref();
702 assert_eq!(bref.len(), 4096);
703 assert_eq!(bref.range(), base..base + 4096);
704 assert_eq!(bref.as_slice()[0..1000], vec![0x00; 1000]);
705 {
706 let bref2 = bref.subslice(1000..2000);
707 assert_eq!(bref2.len(), 1000);
708 assert_eq!(bref2.range(), base + 1000..base + 2000);
709 assert_eq!(bref2.as_slice()[..100], vec![0xaa; 100]);
710 assert_eq!(bref2.as_slice()[100..900], vec![0xbb; 800]);
711 assert_eq!(bref2.as_slice()[900..1000], vec![0xcc; 100]);
712 }
713
714 let bref = bref.subslice(2048..);
715 assert_eq!(bref.len(), 2048);
716 assert_eq!(bref.as_slice(), vec![0x00; 2048]);
717 }
718 }
719
720 #[fuchsia::test]
721 async fn test_buffer_split() {
722 let source = BufferSource::new(1024 * 1024);
723 let allocator = BufferAllocator::new(512, source);
724
725 let _buf = allocator.allocate_buffer(512).await;
728 let mut buf = allocator.allocate_buffer(4096).await;
729 let base = buf.range().start;
730 {
731 let bref = buf.as_mut();
732 let (mut s1, mut s2) = bref.split_at_mut(2048);
733 assert_eq!(s1.len(), 2048);
734 assert_eq!(s1.range(), base..base + 2048);
735 s1.as_mut_slice().fill(0xaa);
736 assert_eq!(s2.len(), 2048);
737 assert_eq!(s2.range(), base + 2048..base + 4096);
738 s2.as_mut_slice().fill(0xbb);
739 }
740 {
741 let bref = buf.as_ref();
742 let (s1, s2) = bref.split_at(1);
743 let (s2, s3) = s2.split_at(2047);
744 let (s3, s4) = s3.split_at(0);
745 assert_eq!(s1.len(), 1);
746 assert_eq!(s1.range(), base..base + 1);
747 assert_eq!(s2.len(), 2047);
748 assert_eq!(s2.range(), base + 1..base + 2048);
749 assert_eq!(s3.len(), 0);
750 assert_eq!(s3.range(), base + 2048..base + 2048);
751 assert_eq!(s4.len(), 2048);
752 assert_eq!(s4.range(), base + 2048..base + 4096);
753 assert_eq!(s1.as_slice(), vec![0xaa; 1]);
754 assert_eq!(s2.as_slice(), vec![0xaa; 2047]);
755 assert_eq!(s3.as_slice(), &[] as &[u8]);
756 assert_eq!(s4.as_slice(), vec![0xbb; 2048]);
757 }
758 }
759
760 #[fuchsia::test]
761 async fn test_blocking_allocation() {
762 let source = BufferSource::new(1024 * 1024);
763 let allocator = Arc::new(BufferAllocator::new(512, source));
764
765 let buf1 = allocator.allocate_buffer(512 * 1024).await;
766 let buf2 = allocator.allocate_buffer(512 * 1024).await;
767 let bufs_dropped = Arc::new(AtomicBool::new(false));
768
769 let allocator_clone = allocator.clone();
771 let bufs_dropped_clone = bufs_dropped.clone();
772 let buf3_fut = async move {
773 allocator_clone.allocate_buffer(1024 * 1024).await;
774 assert!(bufs_dropped_clone.load(Ordering::Relaxed), "Allocation finished early");
775 };
776 pin_mut!(buf3_fut);
777
778 let mut buf_futs = vec![];
780 for _ in 0..16 {
781 let allocator_clone = allocator.clone();
782 let bufs_dropped_clone = bufs_dropped.clone();
783 let fut = async move {
784 allocator_clone.allocate_buffer(64 * 1024).await;
785 assert!(bufs_dropped_clone.load(Ordering::Relaxed), "Allocation finished early");
789 };
790 buf_futs.push(fut);
791 }
792
793 futures::join!(buf3_fut, join_all(buf_futs), async move {
794 std::mem::drop(buf1);
795 std::mem::drop(buf2);
796 bufs_dropped.store(true, Ordering::Relaxed);
797 });
798 }
799
800 #[fuchsia::test]
801 async fn test_clean_entire_transfer_buffer() {
802 const BUFFER_SIZE: usize = 4096;
803 let source = BufferSource::new(BUFFER_SIZE);
804 let allocator = Arc::new(BufferAllocator::new(512, source));
805
806 let mut buf = allocator.allocate_buffer(BUFFER_SIZE).await;
807 buf.as_mut_slice().fill(0xaa);
808 std::mem::drop(buf);
809
810 allocator.clean_transfer_buffer();
811 let buf = allocator.allocate_buffer(BUFFER_SIZE).await;
812 assert_eq!(buf.as_slice(), vec![0; BUFFER_SIZE]);
813 }
814
815 #[fuchsia::test]
816 async fn test_clean_transfer_buffer_around_allocation() {
817 let source = BufferSource::new(4096);
818 let allocator = Arc::new(BufferAllocator::new(512, source));
819
820 let mut buf1 = allocator.allocate_buffer(1024).await;
821 buf1.as_mut_slice().fill(0xaa);
822 let mut buf2 = allocator.allocate_buffer(1024).await;
823 buf2.as_mut_slice().fill(0xbb);
824 assert_eq!(buf2.range().start, 1024);
825 let mut buf3 = allocator.allocate_buffer(2048).await;
826 buf3.as_mut_slice().fill(0xcc);
827 std::mem::drop(buf1);
828 std::mem::drop(buf3);
829
830 allocator.clean_transfer_buffer();
831
832 let buf1 = allocator.allocate_buffer(1024).await;
833 assert_eq!(buf1.as_slice(), vec![0; 1024]);
834
835 assert_eq!(buf2.as_slice(), vec![0xbb; 1024]);
836
837 let buf3 = allocator.allocate_buffer(2048).await;
838 assert_eq!(buf3.as_slice(), vec![0; 2048]);
839 }
840
841 #[fuchsia::test]
842 async fn test_safe_buffer_apis() {
843 let source = BufferSource::new(4096);
844 let allocator = BufferAllocator::new(512, source);
845
846 let mut buf = allocator.allocate_buffer(4096).await;
847
848 let input_data = vec![0x33_u8; 4096];
850 buf.copy_from_slice(&input_data);
851 let mut output_data = vec![0_u8; 4096];
852 buf.copy_to_slice(&mut output_data);
853 assert_eq!(input_data, output_data);
854
855 buf.fill(0x55);
857 buf.copy_to_slice(&mut output_data);
858 assert_eq!(output_data, vec![0x55; 4096]);
859
860 {
862 let mut sub_mut = buf.as_mut().subslice_mut(1024..2048);
863 assert_eq!(sub_mut.len(), 1024);
864 sub_mut.fill(0xaa);
865 }
866
867 {
868 let bref = buf.as_ref();
869 let sub_ref = bref.subslice(1024..2048);
870 assert_eq!(sub_ref.len(), 1024);
871 let mut sub_output = vec![0_u8; 1024];
872 sub_ref.copy_to_slice(&mut sub_output);
873 assert_eq!(sub_output, vec![0xaa; 1024]);
874 }
875
876 {
878 let (mut left_mut, mut right_mut) = buf.as_mut().split_at_mut(2048);
879 assert_eq!(left_mut.len(), 2048);
880 assert_eq!(right_mut.len(), 2048);
881 left_mut.fill(0x11);
882 right_mut.fill(0x22);
883 }
884
885 {
886 let bref = buf.as_ref();
887 let (left_ref, right_ref) = bref.split_at(2048);
888 let mut left_out = vec![0_u8; 2048];
889 let mut right_out = vec![0_u8; 2048];
890 left_ref.copy_to_slice(&mut left_out);
891 right_ref.copy_to_slice(&mut right_out);
892 assert_eq!(left_out, vec![0x11; 2048]);
893 assert_eq!(right_out, vec![0x22; 2048]);
894 }
895 }
896
897 #[fuchsia::test]
898 async fn test_owned_buffer() {
899 let source = BufferSource::new(4096);
900 let allocator = Arc::new(BufferAllocator::new(512, source));
901
902 let mut owned_buf = allocator.allocate_buffer_sync_owned(2048);
903 assert_eq!(owned_buf.len(), 2048);
904 owned_buf.as_mut_slice().fill(0xcc);
905 assert_eq!(owned_buf.as_slice(), vec![0xcc; 2048]);
906
907 let owned_buf2 = allocator.try_allocate_buffer_owned(2048).expect("Must succeed");
909 assert_eq!(owned_buf2.len(), 2048);
910
911 assert!(allocator.try_allocate_buffer_owned(512).is_err());
913
914 std::mem::drop(owned_buf);
916
917 let mut owned_buf3 = allocator.try_allocate_buffer_owned(2048).expect("Must succeed");
919 owned_buf3.as_mut_slice().fill(0xdd);
920 assert_eq!(owned_buf3.as_slice(), vec![0xdd; 2048]);
921 }
922
923 #[fuchsia::test]
924 async fn test_allocate_buffer_sync() {
925 let source = BufferSource::new(4096);
926 let allocator = BufferAllocator::new(512, source);
927
928 let mut buf = allocator.allocate_buffer_sync(2048);
929 assert_eq!(buf.len(), 2048);
930 buf.as_mut_slice().fill(0xee);
931 assert_eq!(buf.as_slice(), vec![0xee; 2048]);
932
933 std::mem::drop(buf);
934
935 let mut buf2 = allocator.allocate_buffer_sync(4096);
936 assert_eq!(buf2.len(), 4096);
937 buf2.as_mut_slice().fill(0xff);
938 assert_eq!(buf2.as_slice(), vec![0xff; 4096]);
939 }
940}