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 trusted: bool,
31 }
32
33 unsafe impl Send for BufferSource {}
36 unsafe impl Sync for BufferSource {}
37
38 impl BufferSource {
39 pub fn new(size: usize) -> Self {
40 Self::new_internal(size, false)
41 }
42
43 pub fn new_trusted(size: usize) -> Self {
44 Self::new_internal(size, true)
45 }
46
47 fn new_internal(size: usize, trusted: bool) -> Self {
48 let mut vmo = zx::Vmo::create(size as u64).unwrap();
49 if trusted {
50 let rights = zx::Rights::VMO_DEFAULT & !zx::Rights::TRANSFER;
58 vmo = vmo.replace_handle(rights).unwrap();
59 }
60 let vmo = Arc::new(vmo);
61 let name = zx::Name::new("transfer-buf").unwrap();
62 vmo.set_name(&name).unwrap();
63 let flags = zx::VmarFlags::PERM_READ
64 | zx::VmarFlags::PERM_WRITE
65 | zx::VmarFlags::MAP_RANGE
66 | zx::VmarFlags::REQUIRE_NON_RESIZABLE;
67 let base = vmar_root_self().map(0, &vmo, 0, size, flags).unwrap() as *mut u8;
68 Self { base, size, vmo, trusted }
69 }
70
71 pub fn is_trusted(&self) -> bool {
72 self.trusted
73 }
74
75 pub fn slice(&self) -> *mut [u8] {
76 std::ptr::slice_from_raw_parts_mut(self.base, self.size)
77 }
78
79 pub fn size(&self) -> usize {
80 self.size
81 }
82
83 pub fn vmo(&self) -> &Arc<zx::Vmo> {
84 &self.vmo
85 }
86
87 pub(crate) unsafe fn subslice_ptr(&self, range: &Range<usize>) -> MutPtrByteSlice<'_> {
94 assert!(range.start < self.size && range.end <= self.size);
95 unsafe {
98 MutPtrByteSlice::new(std::ptr::slice_from_raw_parts_mut(
99 self.base.add(range.start),
100 range.len(),
101 ))
102 }
103 }
104
105 pub(crate) unsafe fn subslice_ptr_unbounded<'a>(
113 &self,
114 range: &Range<usize>,
115 ) -> MutPtrByteSlice<'a> {
116 assert!(range.start < self.size && range.end <= self.size);
117 unsafe {
120 MutPtrByteSlice::new(std::ptr::slice_from_raw_parts_mut(
121 self.base.add(range.start),
122 range.len(),
123 ))
124 }
125 }
126
127 pub fn commit_range(&self, range: Range<usize>) -> Result<(), zx::Status> {
129 self.vmo.op_range(zx::VmoOp::COMMIT, range.start as u64, range.len() as u64)
130 }
131
132 pub(crate) unsafe fn clean_range(&self, range: Range<usize>) {
138 let _ = self.vmo.op_range(zx::VmoOp::ZERO, range.start as u64, range.len() as u64);
139 }
140 }
141
142 impl Drop for BufferSource {
143 fn drop(&mut self) {
144 unsafe {
146 let _ = vmar_root_self().unmap(self.base as usize, self.size);
147 }
148 }
149 }
150}
151
152#[cfg(not(target_os = "fuchsia"))]
153mod buffer_source {
154 use std::cell::UnsafeCell;
155 use std::ops::Range;
156 use std::pin::Pin;
157 use storage_ptr_slice::MutPtrByteSlice;
158
159 #[derive(Debug)]
161 pub struct BufferSource {
162 data: UnsafeCell<Pin<Vec<u8>>>,
167 }
168
169 unsafe impl Sync for BufferSource {}
172
173 impl BufferSource {
174 pub fn new(size: usize) -> Self {
175 Self { data: UnsafeCell::new(Pin::new(vec![0 as u8; size])) }
176 }
177
178 pub fn new_trusted(size: usize) -> Self {
179 Self::new(size)
180 }
181
182 pub fn is_trusted(&self) -> bool {
183 true
184 }
185
186 pub fn size(&self) -> usize {
187 unsafe { (&*self.data.get()).len() }
189 }
190
191 pub(super) unsafe fn subslice_ptr(&self, range: &Range<usize>) -> MutPtrByteSlice<'_> {
198 assert!(range.start < self.size() && range.end <= self.size());
199 unsafe {
202 let ptr = (&mut *self.data.get()).as_mut_ptr().add(range.start);
203 MutPtrByteSlice::new(std::ptr::slice_from_raw_parts_mut(ptr, range.len()))
204 }
205 }
206
207 pub(super) unsafe fn subslice_ptr_unbounded<'a>(
215 &self,
216 range: &Range<usize>,
217 ) -> MutPtrByteSlice<'a> {
218 assert!(range.start < self.size() && range.end <= self.size());
219 unsafe {
222 let ptr = (&mut *self.data.get()).as_mut_ptr().add(range.start);
223 MutPtrByteSlice::new(std::ptr::slice_from_raw_parts_mut(ptr, range.len()))
224 }
225 }
226
227 pub(super) unsafe fn clean_range(&self, range: Range<usize>) {
233 unsafe { self.subslice_ptr(&range) }.fill(0);
235 }
236 }
237}
238
239pub use buffer_source::BufferSource;
240
241type FreeList = Vec<usize>;
252
253#[derive(Debug)]
254struct Inner {
255 free_lists: Vec<FreeList>,
257 allocation_map: BTreeMap<usize, usize>,
259}
260
261#[derive(Debug)]
267pub struct BufferAllocator {
268 block_size: usize,
269 source: BufferSource,
270 inner: Mutex<Inner>,
271 event: Event,
272}
273
274fn order(size: usize, block_size: usize) -> usize {
276 if size <= block_size {
277 return 0;
278 }
279 let nblocks = round_up(size, block_size) / block_size;
280 nblocks.next_power_of_two().trailing_zeros() as usize
281}
282
283fn order_fit(size: usize, block_size: usize) -> usize {
285 assert!(size >= block_size);
286 let nblocks = round_up(size, block_size) / block_size;
287 if nblocks.is_power_of_two() {
288 nblocks.trailing_zeros() as usize
289 } else {
290 nblocks.next_power_of_two().trailing_zeros() as usize - 1
291 }
292}
293
294fn size_for_order(order: usize, block_size: usize) -> usize {
295 block_size * (1 << (order as u32))
296}
297
298fn initial_free_lists(size: usize, block_size: usize) -> Vec<FreeList> {
299 let size = round_down(size, block_size);
300 assert!(block_size <= size);
301 assert!(block_size.is_power_of_two());
302 let max_order = order_fit(size, block_size);
303 let mut free_lists = Vec::with_capacity(max_order + 1);
304 for _ in 0..=max_order {
305 free_lists.push(FreeList::new())
306 }
307 let mut offset = 0;
308 while offset < size {
309 let order = order_fit(size - offset, block_size);
310 let size = size_for_order(order, block_size);
311 free_lists[order].push(offset);
312 offset += size;
313 }
314 free_lists
315}
316
317pub trait TryAllocateBuffer<'a> {
319 type Buffer;
320
321 fn try_allocate_buffer(&'a self, size: usize) -> Result<Self::Buffer, EventListener>;
324
325 fn allocate_buffer_sync(&'a self, size: usize) -> Self::Buffer {
327 loop {
328 match self.try_allocate_buffer(size) {
329 Ok(buffer) => return buffer,
330 Err(listener) => listener.wait(),
331 }
332 }
333 }
334}
335
336pub struct BufferFuture<'a, A: TryAllocateBuffer<'a> + ?Sized = BufferAllocator> {
338 allocator: &'a A,
339 size: usize,
340 listener: Option<EventListener>,
341}
342
343impl<'a, A: TryAllocateBuffer<'a> + ?Sized> BufferFuture<'a, A> {
344 pub fn new(allocator: &'a A, size: usize) -> Self {
345 Self { allocator, size, listener: None }
346 }
347}
348
349impl<'a, A: TryAllocateBuffer<'a> + ?Sized> Future for BufferFuture<'a, A> {
350 type Output = A::Buffer;
351
352 fn poll(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
353 if let Some(listener) = self.listener.as_mut() {
354 futures::ready!(listener.poll_unpin(context));
355 }
356 loop {
359 match self.allocator.try_allocate_buffer(self.size) {
360 Ok(buffer) => return Poll::Ready(buffer),
361 Err(mut listener) => {
362 if listener.poll_unpin(context).is_pending() {
363 self.listener = Some(listener);
364 return Poll::Pending;
365 }
366 }
367 }
368 }
369 }
370}
371
372impl BufferAllocator {
373 pub fn new(block_size: usize, source: BufferSource) -> Self {
374 let free_lists = initial_free_lists(source.size(), block_size);
375 Self {
376 block_size,
377 source,
378 inner: Mutex::new(Inner { free_lists, allocation_map: BTreeMap::new() }),
379 event: Event::new(),
380 }
381 }
382
383 #[cfg(target_os = "fuchsia")]
388 pub fn vmo(&self) -> Option<Arc<zx::Vmo>> {
389 if self.is_trusted() { None } else { Some(self.source.vmo().clone()) }
390 }
391
392 pub fn is_trusted(&self) -> bool {
393 self.source.is_trusted()
394 }
395
396 pub fn block_size(&self) -> usize {
397 self.block_size
398 }
399
400 pub fn buffer_source(&self) -> &BufferSource {
401 &self.source
402 }
403
404 pub fn take_buffer_source(self) -> BufferSource {
406 self.source
407 }
408
409 pub fn identifier(&self) -> usize {
411 std::ptr::from_ref(self).addr()
412 }
413
414 pub fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
426 BufferFuture::new(self, size)
427 }
428
429 pub fn allocate_buffer_sync(&self, size: usize) -> Buffer<'_> {
436 <Self as TryAllocateBuffer>::allocate_buffer_sync(self, size)
437 }
438
439 pub fn allocate_buffer_sync_owned(self: &Arc<Self>, size: usize) -> OwnedBuffer {
446 loop {
447 match self.try_allocate_buffer_owned(size) {
448 Ok(buffer) => return buffer,
449 Err(listener) => listener.wait(),
450 }
451 }
452 }
453
454 pub fn try_allocate_buffer_owned(
461 self: &Arc<Self>,
462 size: usize,
463 ) -> Result<OwnedBuffer, EventListener> {
464 let buffer = self.try_allocate_buffer(size)?;
465 let range = buffer.range();
466 let slice = unsafe { self.source.subslice_ptr_unbounded(&range) };
471 std::mem::forget(buffer);
472 Ok(OwnedBuffer::new(slice, range, self.clone() as Arc<dyn BufferAllocatorTrait>))
473 }
474
475 pub fn try_allocate_buffer(&self, size: usize) -> Result<Buffer<'_>, EventListener> {
482 if size > self.source.size() {
483 panic!("Allocation of {} bytes would exceed limit {}", size, self.source.size());
484 }
485 let mut inner = self.inner.lock();
486 let requested_order = order(size, self.block_size());
487 assert!(requested_order < inner.free_lists.len());
488 let mut order = {
490 let mut idx = requested_order;
491 loop {
492 if idx >= inner.free_lists.len() {
493 return Err(self.event.listen());
494 }
495 if !inner.free_lists[idx].is_empty() {
496 break idx;
497 }
498 idx += 1;
499 }
500 };
501
502 let offset = inner.free_lists[order].pop().unwrap();
504 while order > requested_order {
505 order -= 1;
506 assert!(inner.free_lists[order].is_empty());
507 inner.free_lists[order].push(offset + self.size_for_order(order));
508 }
509
510 inner.allocation_map.insert(offset, self.size_for_order(order));
511 let range = offset..offset + size;
512 log::debug!(range:?, bytes_used = self.size_for_order(order); "Allocated");
513
514 Ok(Buffer::new(unsafe { self.source.subslice_ptr(&range) }, range, self))
517 }
518}
519
520impl BufferAllocatorTrait for BufferAllocator {
521 fn free_buffer(&self, range: Range<usize>) {
522 self.free_buffer(range);
523 }
524
525 fn is_trusted(&self) -> bool {
526 self.is_trusted()
527 }
528
529 #[cfg(target_os = "fuchsia")]
530 fn vmo(&self) -> Option<Arc<zx::Vmo>> {
531 self.vmo()
532 }
533}
534
535impl<'a> TryAllocateBuffer<'a> for BufferAllocator {
536 type Buffer = Buffer<'a>;
537
538 fn try_allocate_buffer(&'a self, size: usize) -> Result<Buffer<'a>, EventListener> {
539 self.try_allocate_buffer(size)
540 }
541}
542
543impl BufferAllocator {
544 #[doc(hidden)]
546 pub(crate) fn free_buffer(&self, range: Range<usize>) {
547 let mut inner = self.inner.lock();
548 let mut offset = range.start;
549 let size = inner
550 .allocation_map
551 .remove(&offset)
552 .unwrap_or_else(|| panic!("No allocation record found for {:?}", range));
553 assert!(range.end - range.start <= size);
554 log::debug!(range:?, bytes_used = size; "Freeing");
555
556 let mut order = order(size, self.block_size());
558 while order < inner.free_lists.len() - 1 {
559 let buddy = self.find_buddy(offset, order);
560 let idx = if let Ok(idx) =
561 inner.free_lists[order].binary_search_by(|probe| buddy.cmp(probe))
562 {
563 idx
564 } else {
565 break;
566 };
567 inner.free_lists[order].remove(idx);
568 offset = std::cmp::min(offset, buddy);
569 order += 1;
570 }
571
572 let idx = match inner.free_lists[order].binary_search_by(|probe| offset.cmp(probe)) {
573 Ok(_) => panic!("Unexpectedly found {} in free list {}", offset, order),
574 Err(idx) => idx,
575 };
576 inner.free_lists[order].insert(idx, offset);
577
578 self.event.notify(usize::MAX);
580 }
581
582 fn size_for_order(&self, order: usize) -> usize {
583 size_for_order(order, self.block_size)
584 }
585
586 fn find_buddy(&self, offset: usize, order: usize) -> usize {
587 offset ^ self.size_for_order(order)
588 }
589
590 pub fn clean_transfer_buffer(&self) {
592 let inner = self.inner.lock();
593 for (n, free_list) in inner.free_lists.iter().enumerate() {
594 for offset in free_list {
595 unsafe {
597 self.source.clean_range(*offset..(*offset + size_for_order(n, self.block_size)))
598 };
599 }
600 }
601 }
602}
603
604#[cfg(target_os = "fuchsia")]
605pub use crate::pinned_buffer_allocator::{
606 DEFAULT_PIN_CHUNK_SIZE, PinnedBuffer, PinnedBufferAllocator, PinnedBufferFuture,
607};
608
609#[cfg(test)]
610mod tests {
611 use crate::buffer::BufferAllocator as BufferAllocatorTrait;
612 use crate::buffer_allocator::{BufferAllocator, BufferSource, order};
613 use fuchsia_async as fasync;
614 use futures::future::join_all;
615 use futures::pin_mut;
616 use rand::seq::IndexedRandom as _;
617 use rand::{RngExt as _, rng};
618 use std::sync::Arc;
619 use std::sync::atomic::{AtomicBool, Ordering};
620
621 #[fuchsia::test]
622 async fn test_odd_sized_buffer_source() {
623 let source = BufferSource::new(123);
624 let allocator = BufferAllocator::new(2, source);
625
626 let sizes = vec![64, 32, 16, 8, 2];
628 let mut bufs = vec![];
629 for size in sizes.iter() {
630 bufs.push(allocator.allocate_buffer(*size).await);
631 }
632 for (expected_size, buf) in sizes.iter().zip(bufs.iter()) {
633 assert_eq!(*expected_size, buf.len());
634 }
635 assert!(allocator.try_allocate_buffer(2).is_err());
636 }
637
638 #[fuchsia::test]
639 async fn test_allocate_buffer_read_write() {
640 let source = BufferSource::new(1024 * 1024);
641 let allocator = BufferAllocator::new(8192, source);
642
643 let mut buf = allocator.allocate_buffer(8192).await;
644 buf.fill(0xaa);
645 let mut vec = vec![0 as u8; 8192];
646 buf.copy_to_slice(&mut vec);
647 assert_eq!(vec, vec![0xaa as u8; 8192]);
648 }
649
650 #[fuchsia::test]
651 async fn test_allocate_buffer_consecutive_calls_do_not_overlap() {
652 let source = BufferSource::new(1024 * 1024);
653 let allocator = BufferAllocator::new(8192, source);
654
655 let buf1 = allocator.allocate_buffer(8192).await;
656 let buf2 = allocator.allocate_buffer(8192).await;
657 assert!(buf1.range().end <= buf2.range().start || buf2.range().end <= buf1.range().start);
658 }
659
660 #[fuchsia::test]
661 async fn test_allocate_many_buffers() {
662 let source = BufferSource::new(1024 * 1024);
663 let allocator = BufferAllocator::new(8192, source);
664
665 for _ in 0..10 {
666 let _ = allocator.allocate_buffer(8192).await;
667 }
668 }
669
670 #[fuchsia::test]
671 async fn test_allocate_small_buffers_dont_overlap() {
672 let source = BufferSource::new(1024 * 1024);
673 let allocator = BufferAllocator::new(8192, source);
674
675 let buf1 = allocator.allocate_buffer(1).await;
676 let buf2 = allocator.allocate_buffer(1).await;
677 assert!(buf1.range().end <= buf2.range().start || buf2.range().end <= buf1.range().start);
678 }
679
680 #[fuchsia::test]
681 async fn test_allocate_large_buffer() {
682 let source = BufferSource::new(1024 * 1024);
683 let allocator = BufferAllocator::new(8192, source);
684
685 let mut buf = allocator.allocate_buffer(1024 * 1024).await;
686 assert_eq!(buf.len(), 1024 * 1024);
687 buf.fill(0xaa);
688 let mut vec = vec![0 as u8; 1024 * 1024];
689 buf.copy_to_slice(&mut vec);
690 assert_eq!(vec, vec![0xaa as u8; 1024 * 1024]);
691 }
692
693 #[fuchsia::test]
694 async fn test_allocate_large_buffer_after_smaller_buffers() {
695 let source = BufferSource::new(1024 * 1024);
696 let allocator = BufferAllocator::new(8192, source);
697
698 {
699 let mut buffers = vec![];
700 while let Ok(buffer) = allocator.try_allocate_buffer(8192) {
701 buffers.push(buffer);
702 }
703 }
704 let buf = allocator.allocate_buffer(1024 * 1024).await;
705 assert_eq!(buf.len(), 1024 * 1024);
706 }
707
708 #[fuchsia::test]
709 async fn test_allocate_at_limits() {
710 let source = BufferSource::new(1024 * 1024);
711 let allocator = BufferAllocator::new(8192, source);
712
713 let mut buffers = vec![];
714 while let Ok(buffer) = allocator.try_allocate_buffer(8192) {
715 buffers.push(buffer);
716 }
717 buffers.pop();
719 let buf = allocator.allocate_buffer(8192).await;
720 assert_eq!(buf.len(), 8192);
721 }
722
723 #[fuchsia::test(threads = 10)]
724 async fn test_random_allocs_deallocs() {
725 let source = BufferSource::new(16 * 1024 * 1024);
726 let bs = 512;
727 let allocator = Arc::new(BufferAllocator::new(bs, source));
728
729 join_all((0..10).map(|_| {
730 let allocator = allocator.clone();
731 fasync::Task::spawn(async move {
732 let mut rng = rng();
733 enum Op {
734 Alloc,
735 Dealloc,
736 }
737 let ops = vec![Op::Alloc, Op::Dealloc];
738 let mut buffers = vec![];
739 for _ in 0..1000 {
740 match ops.choose(&mut rng).unwrap() {
741 Op::Alloc => {
742 let order: usize = rng.random_range(order(1, bs)..order(65536 + 1, bs));
747 let size: usize = rng.random_range(
748 bs * 2_usize.pow(order as u32)..bs * 2_usize.pow(order as u32 + 1),
749 );
750 if let Ok(mut buf) = allocator.try_allocate_buffer(size) {
751 let val = rng.random::<u8>();
752 buf.fill(val);
753 let mut data = vec![0u8; size];
754 buf.copy_to_slice(&mut data);
755 for v in &data {
756 assert_eq!(v, &val);
757 }
758 buffers.push(buf);
759 }
760 }
761 Op::Dealloc if !buffers.is_empty() => {
762 let idx = rng.random_range(0..buffers.len());
763 buffers.remove(idx);
764 }
765 _ => {}
766 };
767 }
768 })
769 }))
770 .await;
771 }
772
773 #[fuchsia::test]
774 async fn test_buffer_refs() {
775 let source = BufferSource::new(1024 * 1024);
776 let allocator = BufferAllocator::new(512, source);
777
778 let _buf = allocator.allocate_buffer(512).await;
781 let mut buf = allocator.allocate_buffer(4096).await;
782 let base = buf.range().start;
783 {
784 let mut bref = buf.subslice_mut(1000..2000);
785 assert_eq!(bref.len(), 1000);
786 assert_eq!(bref.range(), base + 1000..base + 2000);
787 bref.fill(0xbb);
788 {
789 let mut bref2 = bref.reborrow().subslice_mut(0..100);
790 assert_eq!(bref2.len(), 100);
791 assert_eq!(bref2.range(), base + 1000..base + 1100);
792 bref2.fill(0xaa);
793 }
794 {
795 let mut bref2 = bref.reborrow().subslice_mut(900..1000);
796 assert_eq!(bref2.len(), 100);
797 assert_eq!(bref2.range(), base + 1900..base + 2000);
798 bref2.fill(0xcc);
799 }
800 let mut data = vec![0u8; 1000];
801 bref.copy_to_slice(&mut data);
802 assert_eq!(data[..100], vec![0xaa; 100]);
803 assert_eq!(data[100..900], vec![0xbb; 800]);
804
805 let bref = bref.subslice_mut(900..);
806 assert_eq!(bref.len(), 100);
807 let mut data = vec![0u8; 100];
808 bref.copy_to_slice(&mut data);
809 assert_eq!(data, vec![0xcc; 100]);
810 }
811 {
812 let bref = buf.as_ref();
813 assert_eq!(bref.len(), 4096);
814 assert_eq!(bref.range(), base..base + 4096);
815 let mut data = vec![0u8; 4096];
816 bref.copy_to_slice(&mut data);
817 assert_eq!(data[0..1000], vec![0x00; 1000]);
818 {
819 let bref2 = bref.subslice(1000..2000);
820 assert_eq!(bref2.len(), 1000);
821 assert_eq!(bref2.range(), base + 1000..base + 2000);
822 let mut data2 = vec![0u8; 1000];
823 bref2.copy_to_slice(&mut data2);
824 assert_eq!(data2[..100], vec![0xaa; 100]);
825 assert_eq!(data2[100..900], vec![0xbb; 800]);
826 assert_eq!(data2[900..1000], vec![0xcc; 100]);
827 }
828
829 let bref = bref.subslice(2048..);
830 assert_eq!(bref.len(), 2048);
831 let mut data = vec![0u8; 2048];
832 bref.copy_to_slice(&mut data);
833 assert_eq!(data, vec![0x00; 2048]);
834 }
835 }
836
837 #[fuchsia::test]
838 async fn test_buffer_split() {
839 let source = BufferSource::new(1024 * 1024);
840 let allocator = BufferAllocator::new(512, source);
841
842 let _buf = allocator.allocate_buffer(512).await;
845 let mut buf = allocator.allocate_buffer(4096).await;
846 let base = buf.range().start;
847 {
848 let bref = buf.as_mut();
849 let (mut s1, mut s2) = bref.split_at_mut(2048);
850 assert_eq!(s1.len(), 2048);
851 assert_eq!(s1.range(), base..base + 2048);
852 s1.fill(0xaa);
853 assert_eq!(s2.len(), 2048);
854 assert_eq!(s2.range(), base + 2048..base + 4096);
855 s2.fill(0xbb);
856 }
857 {
858 let bref = buf.as_ref();
859 let (s1, s2) = bref.split_at(1);
860 let (s2, s3) = s2.split_at(2047);
861 let (s3, s4) = s3.split_at(0);
862 assert_eq!(s1.len(), 1);
863 assert_eq!(s1.range(), base..base + 1);
864 assert_eq!(s2.len(), 2047);
865 assert_eq!(s2.range(), base + 1..base + 2048);
866 assert_eq!(s3.len(), 0);
867 assert_eq!(s3.range(), base + 2048..base + 2048);
868 assert_eq!(s4.len(), 2048);
869 assert_eq!(s4.range(), base + 2048..base + 4096);
870 let mut d1 = vec![0u8; 1];
871 s1.copy_to_slice(&mut d1);
872 assert_eq!(d1, vec![0xaa; 1]);
873 let mut d2 = vec![0u8; 2047];
874 s2.copy_to_slice(&mut d2);
875 assert_eq!(d2, vec![0xaa; 2047]);
876 let mut d3 = vec![0u8; 0];
877 s3.copy_to_slice(&mut d3);
878 assert_eq!(d3, &[] as &[u8]);
879 let mut d4 = vec![0u8; 2048];
880 s4.copy_to_slice(&mut d4);
881 assert_eq!(d4, vec![0xbb; 2048]);
882 }
883 }
884
885 #[fuchsia::test]
886 async fn test_blocking_allocation() {
887 let source = BufferSource::new(1024 * 1024);
888 let allocator = Arc::new(BufferAllocator::new(512, source));
889
890 let buf1 = allocator.allocate_buffer(512 * 1024).await;
891 let buf2 = allocator.allocate_buffer(512 * 1024).await;
892 let bufs_dropped = Arc::new(AtomicBool::new(false));
893
894 let allocator_clone = allocator.clone();
896 let bufs_dropped_clone = bufs_dropped.clone();
897 let buf3_fut = async move {
898 allocator_clone.allocate_buffer(1024 * 1024).await;
899 assert!(bufs_dropped_clone.load(Ordering::Relaxed), "Allocation finished early");
900 };
901 pin_mut!(buf3_fut);
902
903 let mut buf_futs = vec![];
905 for _ in 0..16 {
906 let allocator_clone = allocator.clone();
907 let bufs_dropped_clone = bufs_dropped.clone();
908 let fut = async move {
909 allocator_clone.allocate_buffer(64 * 1024).await;
910 assert!(bufs_dropped_clone.load(Ordering::Relaxed), "Allocation finished early");
914 };
915 buf_futs.push(fut);
916 }
917
918 futures::join!(buf3_fut, join_all(buf_futs), async move {
919 std::mem::drop(buf1);
920 std::mem::drop(buf2);
921 bufs_dropped.store(true, Ordering::Relaxed);
922 });
923 }
924
925 #[fuchsia::test]
926 async fn test_clean_entire_transfer_buffer() {
927 const BUFFER_SIZE: usize = 4096;
928 let source = BufferSource::new(BUFFER_SIZE);
929 let allocator = Arc::new(BufferAllocator::new(512, source));
930
931 let mut buf = allocator.allocate_buffer(BUFFER_SIZE).await;
932 buf.fill(0xaa);
933 std::mem::drop(buf);
934
935 allocator.clean_transfer_buffer();
936 let buf = allocator.allocate_buffer(BUFFER_SIZE).await;
937 let mut data = vec![0u8; BUFFER_SIZE];
938 buf.copy_to_slice(&mut data);
939 assert_eq!(data, vec![0; BUFFER_SIZE]);
940 }
941
942 #[fuchsia::test]
943 async fn test_clean_transfer_buffer_around_allocation() {
944 let source = BufferSource::new(4096);
945 let allocator = Arc::new(BufferAllocator::new(512, source));
946
947 let mut buf1 = allocator.allocate_buffer(1024).await;
948 buf1.fill(0xaa);
949 let mut buf2 = allocator.allocate_buffer(1024).await;
950 buf2.fill(0xbb);
951 assert_eq!(buf2.range().start, 1024);
952 let mut buf3 = allocator.allocate_buffer(2048).await;
953 buf3.fill(0xcc);
954 std::mem::drop(buf1);
955 std::mem::drop(buf3);
956
957 allocator.clean_transfer_buffer();
958
959 let buf1 = allocator.allocate_buffer(1024).await;
960 let mut data1 = vec![0u8; 1024];
961 buf1.copy_to_slice(&mut data1);
962 assert_eq!(data1, vec![0; 1024]);
963
964 let mut data2 = vec![0u8; 1024];
965 buf2.copy_to_slice(&mut data2);
966 assert_eq!(data2, vec![0xbb; 1024]);
967
968 let buf3 = allocator.allocate_buffer(2048).await;
969 let mut data3 = vec![0u8; 2048];
970 buf3.copy_to_slice(&mut data3);
971 assert_eq!(data3, vec![0; 2048]);
972 }
973
974 #[fuchsia::test]
975 async fn test_safe_buffer_apis() {
976 let source = BufferSource::new(4096);
977 let allocator = BufferAllocator::new(512, source);
978
979 let mut buf = allocator.allocate_buffer(4096).await;
980
981 let input_data = vec![0x33_u8; 4096];
983 buf.copy_from_slice(&input_data);
984 let mut output_data = vec![0_u8; 4096];
985 buf.copy_to_slice(&mut output_data);
986 assert_eq!(input_data, output_data);
987
988 buf.fill(0x55);
990 buf.copy_to_slice(&mut output_data);
991 assert_eq!(output_data, vec![0x55; 4096]);
992
993 {
995 let mut sub_mut = buf.as_mut().subslice_mut(1024..2048);
996 assert_eq!(sub_mut.len(), 1024);
997 sub_mut.fill(0xaa);
998 }
999
1000 {
1001 let bref = buf.as_ref();
1002 let sub_ref = bref.subslice(1024..2048);
1003 assert_eq!(sub_ref.len(), 1024);
1004 let mut sub_output = vec![0_u8; 1024];
1005 sub_ref.copy_to_slice(&mut sub_output);
1006 assert_eq!(sub_output, vec![0xaa; 1024]);
1007 }
1008
1009 {
1011 let (mut left_mut, mut right_mut) = buf.as_mut().split_at_mut(2048);
1012 assert_eq!(left_mut.len(), 2048);
1013 assert_eq!(right_mut.len(), 2048);
1014 left_mut.fill(0x11);
1015 right_mut.fill(0x22);
1016 }
1017
1018 {
1019 let bref = buf.as_ref();
1020 let (left_ref, right_ref) = bref.split_at(2048);
1021 let mut left_out = vec![0_u8; 2048];
1022 let mut right_out = vec![0_u8; 2048];
1023 left_ref.copy_to_slice(&mut left_out);
1024 right_ref.copy_to_slice(&mut right_out);
1025 assert_eq!(left_out, vec![0x11; 2048]);
1026 assert_eq!(right_out, vec![0x22; 2048]);
1027 }
1028 }
1029
1030 #[fuchsia::test]
1031 async fn test_owned_buffer() {
1032 let source = BufferSource::new(4096);
1033 let allocator = Arc::new(BufferAllocator::new(512, source));
1034
1035 let mut owned_buf = allocator.allocate_buffer_sync_owned(2048);
1036 assert_eq!(owned_buf.len(), 2048);
1037 owned_buf.as_mut_ptr_slice().fill(0xcc);
1038 assert_eq!(owned_buf.as_ptr_slice().to_vec(), vec![0xcc; 2048]);
1039
1040 let owned_buf2 = allocator.try_allocate_buffer_owned(2048).expect("Must succeed");
1042 assert_eq!(owned_buf2.len(), 2048);
1043
1044 assert!(allocator.try_allocate_buffer_owned(512).is_err());
1046
1047 std::mem::drop(owned_buf);
1049
1050 let mut owned_buf3 = allocator.try_allocate_buffer_owned(2048).expect("Must succeed");
1052 owned_buf3.as_mut_ptr_slice().fill(0xdd);
1053 assert_eq!(owned_buf3.as_ptr_slice().to_vec(), vec![0xdd; 2048]);
1054 }
1055
1056 #[fuchsia::test]
1057 async fn test_allocate_buffer_sync() {
1058 let source = BufferSource::new(4096);
1059 let allocator = BufferAllocator::new(512, source);
1060
1061 let mut buf = allocator.allocate_buffer_sync(2048);
1062 assert_eq!(buf.len(), 2048);
1063 buf.as_mut_ptr_slice().fill(0xee);
1064 assert_eq!(buf.as_ptr_slice().to_vec(), vec![0xee; 2048]);
1065
1066 std::mem::drop(buf);
1067
1068 let mut buf2 = allocator.allocate_buffer_sync(4096);
1069 assert_eq!(buf2.len(), 4096);
1070 buf2.as_mut_ptr_slice().fill(0xff);
1071 assert_eq!(buf2.as_ptr_slice().to_vec(), vec![0xff; 4096]);
1072 }
1073
1074 #[fuchsia::test]
1075 async fn test_trusted_buffer_apis() {
1076 #[cfg(target_os = "fuchsia")]
1078 {
1079 let source = BufferSource::new(4096);
1080 let allocator = BufferAllocator::new(512, source);
1081 let mut buf = allocator.allocate_buffer(4096).await;
1082 assert!(buf.try_as_slice().is_none());
1083 assert!(buf.as_mut().try_as_mut_slice().is_none());
1084 }
1085
1086 {
1088 let source = BufferSource::new_trusted(4096);
1089 let allocator = BufferAllocator::new(512, source);
1090 let mut buf = allocator.allocate_buffer(4096).await;
1091 assert!(buf.try_as_slice().is_some());
1092 assert!(buf.as_mut().try_as_mut_slice().is_some());
1093
1094 let slice = buf.try_as_slice().unwrap();
1096 assert_eq!(slice.len(), 4096);
1097 let mut expected = vec![0u8; 4096];
1098 assert_eq!(slice, expected.as_slice());
1099
1100 let mut bref = buf.as_mut();
1101 let slice_mut = bref.try_as_mut_slice().unwrap();
1102 slice_mut[0] = 0xff;
1103 expected[0] = 0xff;
1104 assert_eq!(buf.try_as_slice().unwrap(), expected.as_slice());
1105 }
1106 }
1107
1108 #[fuchsia::test]
1109 #[cfg(target_os = "fuchsia")]
1110 async fn test_trusted_buffer_rights() {
1111 use zx;
1112 let source = BufferSource::new_trusted(4096);
1113 let vmo = source.vmo();
1114 let info = vmo.basic_info().expect("failed to get basic info");
1115 assert!(!info.rights.contains(zx::Rights::TRANSFER));
1116 }
1117
1118 #[fuchsia::test]
1119 async fn test_allocator_lowest_offset_first() {
1120 let source = BufferSource::new(8192);
1121 let allocator = BufferAllocator::new(512, source);
1122
1123 let buf0 = allocator.allocate_buffer(1024).await;
1125 let buf1 = allocator.allocate_buffer(1024).await;
1126 assert_eq!(buf0.range(), 0..1024);
1127 assert_eq!(buf1.range(), 1024..2048);
1128
1129 std::mem::drop(buf0);
1131
1132 let buf0_again = allocator.allocate_buffer(1024).await;
1134 assert_eq!(buf0_again.range(), 0..1024);
1135 }
1136
1137 #[fuchsia::test]
1138 #[cfg(target_os = "fuchsia")]
1139 async fn test_unpinned_buffer() {
1140 let source = BufferSource::new(4096);
1141 let standard_allocator = BufferAllocator::new(512, source);
1142 let unpinned = standard_allocator.allocate_buffer(512).await;
1143 assert_eq!(unpinned.paddrs(), None);
1144 assert_eq!(unpinned.contiguity(), None);
1145 }
1146
1147 #[fuchsia::test]
1148 #[cfg(target_os = "fuchsia")]
1149 async fn test_vmo_trusted_vs_untrusted() {
1150 let untrusted_source = BufferSource::new(4096);
1151 let untrusted_alloc = BufferAllocator::new(512, untrusted_source);
1152 assert!(!untrusted_alloc.is_trusted());
1153 assert!(untrusted_alloc.vmo().is_some());
1154 assert!(BufferAllocatorTrait::vmo(&untrusted_alloc).is_some());
1155 let untrusted_buf = untrusted_alloc.allocate_buffer(512).await;
1156 assert!(untrusted_buf.vmo().is_some());
1157
1158 let trusted_source = BufferSource::new_trusted(4096);
1159 let trusted_alloc = BufferAllocator::new(512, trusted_source);
1160 assert!(trusted_alloc.is_trusted());
1161 assert!(trusted_alloc.vmo().is_none());
1162 assert!(BufferAllocatorTrait::vmo(&trusted_alloc).is_none());
1163 let trusted_buf = trusted_alloc.allocate_buffer(512).await;
1164 assert!(trusted_buf.vmo().is_none());
1165 }
1166}