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(super) 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(super) 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(super) 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>;
245
246#[derive(Debug)]
247struct Inner {
248 free_lists: Vec<FreeList>,
250 allocation_map: BTreeMap<usize, usize>,
252}
253
254#[derive(Debug)]
258pub struct BufferAllocator {
259 block_size: usize,
260 source: BufferSource,
261 inner: Mutex<Inner>,
262 event: Event,
263}
264
265fn order(size: usize, block_size: usize) -> usize {
267 if size <= block_size {
268 return 0;
269 }
270 let nblocks = round_up(size, block_size) / block_size;
271 nblocks.next_power_of_two().trailing_zeros() as usize
272}
273
274fn order_fit(size: usize, block_size: usize) -> usize {
276 assert!(size >= block_size);
277 let nblocks = round_up(size, block_size) / block_size;
278 if nblocks.is_power_of_two() {
279 nblocks.trailing_zeros() as usize
280 } else {
281 nblocks.next_power_of_two().trailing_zeros() as usize - 1
282 }
283}
284
285fn size_for_order(order: usize, block_size: usize) -> usize {
286 block_size * (1 << (order as u32))
287}
288
289fn initial_free_lists(size: usize, block_size: usize) -> Vec<FreeList> {
290 let size = round_down(size, block_size);
291 assert!(block_size <= size);
292 assert!(block_size.is_power_of_two());
293 let max_order = order_fit(size, block_size);
294 let mut free_lists = Vec::with_capacity(max_order + 1);
295 for _ in 0..=max_order {
296 free_lists.push(FreeList::new())
297 }
298 let mut offset = 0;
299 while offset < size {
300 let order = order_fit(size - offset, block_size);
301 let size = size_for_order(order, block_size);
302 free_lists[order].push(offset);
303 offset += size;
304 }
305 free_lists
306}
307
308pub struct BufferFuture<'a> {
310 allocator: &'a BufferAllocator,
311 size: usize,
312 listener: Option<EventListener>,
313}
314
315impl<'a> Future for BufferFuture<'a> {
316 type Output = Buffer<'a>;
317
318 fn poll(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
319 if let Some(listener) = self.listener.as_mut() {
320 futures::ready!(listener.poll_unpin(context));
321 }
322 loop {
325 match self.allocator.try_allocate_buffer(self.size) {
326 Ok(buffer) => return Poll::Ready(buffer),
327 Err(mut listener) => {
328 if listener.poll_unpin(context).is_pending() {
329 self.listener = Some(listener);
330 return Poll::Pending;
331 }
332 }
333 }
334 }
335 }
336}
337
338impl BufferAllocator {
339 pub fn new(block_size: usize, source: BufferSource) -> Self {
340 let free_lists = initial_free_lists(source.size(), block_size);
341 Self {
342 block_size,
343 source,
344 inner: Mutex::new(Inner { free_lists, allocation_map: BTreeMap::new() }),
345 event: Event::new(),
346 }
347 }
348
349 pub fn is_trusted(&self) -> bool {
350 self.source.is_trusted()
351 }
352
353 pub fn block_size(&self) -> usize {
354 self.block_size
355 }
356
357 pub fn buffer_source(&self) -> &BufferSource {
358 &self.source
359 }
360
361 pub fn take_buffer_source(self) -> BufferSource {
363 self.source
364 }
365
366 pub fn identifier(&self) -> usize {
368 std::ptr::from_ref(self).addr()
369 }
370
371 pub fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
383 BufferFuture { allocator: self, size, listener: None }
384 }
385
386 pub fn allocate_buffer_sync(&self, size: usize) -> Buffer<'_> {
393 loop {
394 match self.try_allocate_buffer(size) {
395 Ok(buffer) => return buffer,
396 Err(listener) => listener.wait(),
397 }
398 }
399 }
400
401 pub fn allocate_buffer_sync_owned(self: &Arc<Self>, size: usize) -> OwnedBuffer {
408 loop {
409 match self.try_allocate_buffer_owned(size) {
410 Ok(buffer) => return buffer,
411 Err(listener) => listener.wait(),
412 }
413 }
414 }
415
416 pub fn try_allocate_buffer_owned(
423 self: &Arc<Self>,
424 size: usize,
425 ) -> Result<OwnedBuffer, EventListener> {
426 let buffer = self.try_allocate_buffer(size)?;
427 let range = buffer.range();
428 let slice = unsafe { self.source.subslice_ptr_unbounded(&range) };
433 std::mem::forget(buffer);
434 Ok(OwnedBuffer::new(slice, range, self.clone() as Arc<dyn BufferAllocatorTrait>))
435 }
436
437 pub fn try_allocate_buffer(&self, size: usize) -> Result<Buffer<'_>, EventListener> {
444 if size > self.source.size() {
445 panic!("Allocation of {} bytes would exceed limit {}", size, self.source.size());
446 }
447 let mut inner = self.inner.lock();
448 let requested_order = order(size, self.block_size());
449 assert!(requested_order < inner.free_lists.len());
450 let mut order = {
452 let mut idx = requested_order;
453 loop {
454 if idx >= inner.free_lists.len() {
455 return Err(self.event.listen());
456 }
457 if !inner.free_lists[idx].is_empty() {
458 break idx;
459 }
460 idx += 1;
461 }
462 };
463
464 let offset = inner.free_lists[order].pop().unwrap();
466 while order > requested_order {
467 order -= 1;
468 assert!(inner.free_lists[order].is_empty());
469 inner.free_lists[order].push(offset + self.size_for_order(order));
470 }
471
472 inner.allocation_map.insert(offset, self.size_for_order(order));
473 let range = offset..offset + size;
474 log::debug!(range:?, bytes_used = self.size_for_order(order); "Allocated");
475
476 Ok(Buffer::new(unsafe { self.source.subslice_ptr(&range) }, range, self))
479 }
480}
481
482impl BufferAllocatorTrait for BufferAllocator {
483 fn free_buffer(&self, range: Range<usize>) {
484 self.free_buffer(range);
485 }
486
487 fn is_trusted(&self) -> bool {
488 self.is_trusted()
489 }
490}
491
492impl BufferAllocator {
493 #[doc(hidden)]
495 pub(super) fn free_buffer(&self, range: Range<usize>) {
496 let mut inner = self.inner.lock();
497 let mut offset = range.start;
498 let size = inner
499 .allocation_map
500 .remove(&offset)
501 .unwrap_or_else(|| panic!("No allocation record found for {:?}", range));
502 assert!(range.end - range.start <= size);
503 log::debug!(range:?, bytes_used = size; "Freeing");
504
505 let mut order = order(size, self.block_size());
507 while order < inner.free_lists.len() - 1 {
508 let buddy = self.find_buddy(offset, order);
509 let idx = if let Ok(idx) = inner.free_lists[order].binary_search(&buddy) {
510 idx
511 } else {
512 break;
513 };
514 inner.free_lists[order].remove(idx);
515 offset = std::cmp::min(offset, buddy);
516 order += 1;
517 }
518
519 let idx = match inner.free_lists[order].binary_search(&offset) {
520 Ok(_) => panic!("Unexpectedly found {} in free list {}", offset, order),
521 Err(idx) => idx,
522 };
523 inner.free_lists[order].insert(idx, offset);
524
525 self.event.notify(usize::MAX);
527 }
528
529 fn size_for_order(&self, order: usize) -> usize {
530 size_for_order(order, self.block_size)
531 }
532
533 fn find_buddy(&self, offset: usize, order: usize) -> usize {
534 offset ^ self.size_for_order(order)
535 }
536
537 pub fn clean_transfer_buffer(&self) {
539 let inner = self.inner.lock();
540 for (n, free_list) in inner.free_lists.iter().enumerate() {
541 for offset in free_list {
542 unsafe {
544 self.source.clean_range(*offset..(*offset + size_for_order(n, self.block_size)))
545 };
546 }
547 }
548 }
549}
550
551#[cfg(test)]
552mod tests {
553 use crate::buffer_allocator::{BufferAllocator, BufferSource, order};
554 use fuchsia_async as fasync;
555 use futures::future::join_all;
556 use futures::pin_mut;
557 use rand::seq::IndexedRandom;
558 use rand::{Rng, rng};
559 use std::sync::Arc;
560 use std::sync::atomic::{AtomicBool, Ordering};
561
562 #[fuchsia::test]
563 async fn test_odd_sized_buffer_source() {
564 let source = BufferSource::new(123);
565 let allocator = BufferAllocator::new(2, source);
566
567 let sizes = vec![64, 32, 16, 8, 2];
569 let mut bufs = vec![];
570 for size in sizes.iter() {
571 bufs.push(allocator.allocate_buffer(*size).await);
572 }
573 for (expected_size, buf) in sizes.iter().zip(bufs.iter()) {
574 assert_eq!(*expected_size, buf.len());
575 }
576 assert!(allocator.try_allocate_buffer(2).is_err());
577 }
578
579 #[fuchsia::test]
580 async fn test_allocate_buffer_read_write() {
581 let source = BufferSource::new(1024 * 1024);
582 let allocator = BufferAllocator::new(8192, source);
583
584 let mut buf = allocator.allocate_buffer(8192).await;
585 buf.fill(0xaa);
586 let mut vec = vec![0 as u8; 8192];
587 buf.copy_to_slice(&mut vec);
588 assert_eq!(vec, vec![0xaa as u8; 8192]);
589 }
590
591 #[fuchsia::test]
592 async fn test_allocate_buffer_consecutive_calls_do_not_overlap() {
593 let source = BufferSource::new(1024 * 1024);
594 let allocator = BufferAllocator::new(8192, source);
595
596 let buf1 = allocator.allocate_buffer(8192).await;
597 let buf2 = allocator.allocate_buffer(8192).await;
598 assert!(buf1.range().end <= buf2.range().start || buf2.range().end <= buf1.range().start);
599 }
600
601 #[fuchsia::test]
602 async fn test_allocate_many_buffers() {
603 let source = BufferSource::new(1024 * 1024);
604 let allocator = BufferAllocator::new(8192, source);
605
606 for _ in 0..10 {
607 let _ = allocator.allocate_buffer(8192).await;
608 }
609 }
610
611 #[fuchsia::test]
612 async fn test_allocate_small_buffers_dont_overlap() {
613 let source = BufferSource::new(1024 * 1024);
614 let allocator = BufferAllocator::new(8192, source);
615
616 let buf1 = allocator.allocate_buffer(1).await;
617 let buf2 = allocator.allocate_buffer(1).await;
618 assert!(buf1.range().end <= buf2.range().start || buf2.range().end <= buf1.range().start);
619 }
620
621 #[fuchsia::test]
622 async fn test_allocate_large_buffer() {
623 let source = BufferSource::new(1024 * 1024);
624 let allocator = BufferAllocator::new(8192, source);
625
626 let mut buf = allocator.allocate_buffer(1024 * 1024).await;
627 assert_eq!(buf.len(), 1024 * 1024);
628 buf.fill(0xaa);
629 let mut vec = vec![0 as u8; 1024 * 1024];
630 buf.copy_to_slice(&mut vec);
631 assert_eq!(vec, vec![0xaa as u8; 1024 * 1024]);
632 }
633
634 #[fuchsia::test]
635 async fn test_allocate_large_buffer_after_smaller_buffers() {
636 let source = BufferSource::new(1024 * 1024);
637 let allocator = BufferAllocator::new(8192, source);
638
639 {
640 let mut buffers = vec![];
641 while let Ok(buffer) = allocator.try_allocate_buffer(8192) {
642 buffers.push(buffer);
643 }
644 }
645 let buf = allocator.allocate_buffer(1024 * 1024).await;
646 assert_eq!(buf.len(), 1024 * 1024);
647 }
648
649 #[fuchsia::test]
650 async fn test_allocate_at_limits() {
651 let source = BufferSource::new(1024 * 1024);
652 let allocator = BufferAllocator::new(8192, source);
653
654 let mut buffers = vec![];
655 while let Ok(buffer) = allocator.try_allocate_buffer(8192) {
656 buffers.push(buffer);
657 }
658 buffers.pop();
660 let buf = allocator.allocate_buffer(8192).await;
661 assert_eq!(buf.len(), 8192);
662 }
663
664 #[fuchsia::test(threads = 10)]
665 async fn test_random_allocs_deallocs() {
666 let source = BufferSource::new(16 * 1024 * 1024);
667 let bs = 512;
668 let allocator = Arc::new(BufferAllocator::new(bs, source));
669
670 join_all((0..10).map(|_| {
671 let allocator = allocator.clone();
672 fasync::Task::spawn(async move {
673 let mut rng = rng();
674 enum Op {
675 Alloc,
676 Dealloc,
677 }
678 let ops = vec![Op::Alloc, Op::Dealloc];
679 let mut buffers = vec![];
680 for _ in 0..1000 {
681 match ops.choose(&mut rng).unwrap() {
682 Op::Alloc => {
683 let order: usize = rng.random_range(order(1, bs)..order(65536 + 1, bs));
688 let size: usize = rng.random_range(
689 bs * 2_usize.pow(order as u32)..bs * 2_usize.pow(order as u32 + 1),
690 );
691 if let Ok(mut buf) = allocator.try_allocate_buffer(size) {
692 let val = rng.random::<u8>();
693 buf.fill(val);
694 let mut data = vec![0u8; size];
695 buf.copy_to_slice(&mut data);
696 for v in &data {
697 assert_eq!(v, &val);
698 }
699 buffers.push(buf);
700 }
701 }
702 Op::Dealloc if !buffers.is_empty() => {
703 let idx = rng.random_range(0..buffers.len());
704 buffers.remove(idx);
705 }
706 _ => {}
707 };
708 }
709 })
710 }))
711 .await;
712 }
713
714 #[fuchsia::test]
715 async fn test_buffer_refs() {
716 let source = BufferSource::new(1024 * 1024);
717 let allocator = BufferAllocator::new(512, source);
718
719 let _buf = allocator.allocate_buffer(512).await;
722 let mut buf = allocator.allocate_buffer(4096).await;
723 let base = buf.range().start;
724 {
725 let mut bref = buf.subslice_mut(1000..2000);
726 assert_eq!(bref.len(), 1000);
727 assert_eq!(bref.range(), base + 1000..base + 2000);
728 bref.fill(0xbb);
729 {
730 let mut bref2 = bref.reborrow().subslice_mut(0..100);
731 assert_eq!(bref2.len(), 100);
732 assert_eq!(bref2.range(), base + 1000..base + 1100);
733 bref2.fill(0xaa);
734 }
735 {
736 let mut bref2 = bref.reborrow().subslice_mut(900..1000);
737 assert_eq!(bref2.len(), 100);
738 assert_eq!(bref2.range(), base + 1900..base + 2000);
739 bref2.fill(0xcc);
740 }
741 let mut data = vec![0u8; 1000];
742 bref.copy_to_slice(&mut data);
743 assert_eq!(data[..100], vec![0xaa; 100]);
744 assert_eq!(data[100..900], vec![0xbb; 800]);
745
746 let bref = bref.subslice_mut(900..);
747 assert_eq!(bref.len(), 100);
748 let mut data = vec![0u8; 100];
749 bref.copy_to_slice(&mut data);
750 assert_eq!(data, vec![0xcc; 100]);
751 }
752 {
753 let bref = buf.as_ref();
754 assert_eq!(bref.len(), 4096);
755 assert_eq!(bref.range(), base..base + 4096);
756 let mut data = vec![0u8; 4096];
757 bref.copy_to_slice(&mut data);
758 assert_eq!(data[0..1000], vec![0x00; 1000]);
759 {
760 let bref2 = bref.subslice(1000..2000);
761 assert_eq!(bref2.len(), 1000);
762 assert_eq!(bref2.range(), base + 1000..base + 2000);
763 let mut data2 = vec![0u8; 1000];
764 bref2.copy_to_slice(&mut data2);
765 assert_eq!(data2[..100], vec![0xaa; 100]);
766 assert_eq!(data2[100..900], vec![0xbb; 800]);
767 assert_eq!(data2[900..1000], vec![0xcc; 100]);
768 }
769
770 let bref = bref.subslice(2048..);
771 assert_eq!(bref.len(), 2048);
772 let mut data = vec![0u8; 2048];
773 bref.copy_to_slice(&mut data);
774 assert_eq!(data, vec![0x00; 2048]);
775 }
776 }
777
778 #[fuchsia::test]
779 async fn test_buffer_split() {
780 let source = BufferSource::new(1024 * 1024);
781 let allocator = BufferAllocator::new(512, source);
782
783 let _buf = allocator.allocate_buffer(512).await;
786 let mut buf = allocator.allocate_buffer(4096).await;
787 let base = buf.range().start;
788 {
789 let bref = buf.as_mut();
790 let (mut s1, mut s2) = bref.split_at_mut(2048);
791 assert_eq!(s1.len(), 2048);
792 assert_eq!(s1.range(), base..base + 2048);
793 s1.fill(0xaa);
794 assert_eq!(s2.len(), 2048);
795 assert_eq!(s2.range(), base + 2048..base + 4096);
796 s2.fill(0xbb);
797 }
798 {
799 let bref = buf.as_ref();
800 let (s1, s2) = bref.split_at(1);
801 let (s2, s3) = s2.split_at(2047);
802 let (s3, s4) = s3.split_at(0);
803 assert_eq!(s1.len(), 1);
804 assert_eq!(s1.range(), base..base + 1);
805 assert_eq!(s2.len(), 2047);
806 assert_eq!(s2.range(), base + 1..base + 2048);
807 assert_eq!(s3.len(), 0);
808 assert_eq!(s3.range(), base + 2048..base + 2048);
809 assert_eq!(s4.len(), 2048);
810 assert_eq!(s4.range(), base + 2048..base + 4096);
811 let mut d1 = vec![0u8; 1];
812 s1.copy_to_slice(&mut d1);
813 assert_eq!(d1, vec![0xaa; 1]);
814 let mut d2 = vec![0u8; 2047];
815 s2.copy_to_slice(&mut d2);
816 assert_eq!(d2, vec![0xaa; 2047]);
817 let mut d3 = vec![0u8; 0];
818 s3.copy_to_slice(&mut d3);
819 assert_eq!(d3, &[] as &[u8]);
820 let mut d4 = vec![0u8; 2048];
821 s4.copy_to_slice(&mut d4);
822 assert_eq!(d4, vec![0xbb; 2048]);
823 }
824 }
825
826 #[fuchsia::test]
827 async fn test_blocking_allocation() {
828 let source = BufferSource::new(1024 * 1024);
829 let allocator = Arc::new(BufferAllocator::new(512, source));
830
831 let buf1 = allocator.allocate_buffer(512 * 1024).await;
832 let buf2 = allocator.allocate_buffer(512 * 1024).await;
833 let bufs_dropped = Arc::new(AtomicBool::new(false));
834
835 let allocator_clone = allocator.clone();
837 let bufs_dropped_clone = bufs_dropped.clone();
838 let buf3_fut = async move {
839 allocator_clone.allocate_buffer(1024 * 1024).await;
840 assert!(bufs_dropped_clone.load(Ordering::Relaxed), "Allocation finished early");
841 };
842 pin_mut!(buf3_fut);
843
844 let mut buf_futs = vec![];
846 for _ in 0..16 {
847 let allocator_clone = allocator.clone();
848 let bufs_dropped_clone = bufs_dropped.clone();
849 let fut = async move {
850 allocator_clone.allocate_buffer(64 * 1024).await;
851 assert!(bufs_dropped_clone.load(Ordering::Relaxed), "Allocation finished early");
855 };
856 buf_futs.push(fut);
857 }
858
859 futures::join!(buf3_fut, join_all(buf_futs), async move {
860 std::mem::drop(buf1);
861 std::mem::drop(buf2);
862 bufs_dropped.store(true, Ordering::Relaxed);
863 });
864 }
865
866 #[fuchsia::test]
867 async fn test_clean_entire_transfer_buffer() {
868 const BUFFER_SIZE: usize = 4096;
869 let source = BufferSource::new(BUFFER_SIZE);
870 let allocator = Arc::new(BufferAllocator::new(512, source));
871
872 let mut buf = allocator.allocate_buffer(BUFFER_SIZE).await;
873 buf.fill(0xaa);
874 std::mem::drop(buf);
875
876 allocator.clean_transfer_buffer();
877 let buf = allocator.allocate_buffer(BUFFER_SIZE).await;
878 let mut data = vec![0u8; BUFFER_SIZE];
879 buf.copy_to_slice(&mut data);
880 assert_eq!(data, vec![0; BUFFER_SIZE]);
881 }
882
883 #[fuchsia::test]
884 async fn test_clean_transfer_buffer_around_allocation() {
885 let source = BufferSource::new(4096);
886 let allocator = Arc::new(BufferAllocator::new(512, source));
887
888 let mut buf1 = allocator.allocate_buffer(1024).await;
889 buf1.fill(0xaa);
890 let mut buf2 = allocator.allocate_buffer(1024).await;
891 buf2.fill(0xbb);
892 assert_eq!(buf2.range().start, 1024);
893 let mut buf3 = allocator.allocate_buffer(2048).await;
894 buf3.fill(0xcc);
895 std::mem::drop(buf1);
896 std::mem::drop(buf3);
897
898 allocator.clean_transfer_buffer();
899
900 let buf1 = allocator.allocate_buffer(1024).await;
901 let mut data1 = vec![0u8; 1024];
902 buf1.copy_to_slice(&mut data1);
903 assert_eq!(data1, vec![0; 1024]);
904
905 let mut data2 = vec![0u8; 1024];
906 buf2.copy_to_slice(&mut data2);
907 assert_eq!(data2, vec![0xbb; 1024]);
908
909 let buf3 = allocator.allocate_buffer(2048).await;
910 let mut data3 = vec![0u8; 2048];
911 buf3.copy_to_slice(&mut data3);
912 assert_eq!(data3, vec![0; 2048]);
913 }
914
915 #[fuchsia::test]
916 async fn test_safe_buffer_apis() {
917 let source = BufferSource::new(4096);
918 let allocator = BufferAllocator::new(512, source);
919
920 let mut buf = allocator.allocate_buffer(4096).await;
921
922 let input_data = vec![0x33_u8; 4096];
924 buf.copy_from_slice(&input_data);
925 let mut output_data = vec![0_u8; 4096];
926 buf.copy_to_slice(&mut output_data);
927 assert_eq!(input_data, output_data);
928
929 buf.fill(0x55);
931 buf.copy_to_slice(&mut output_data);
932 assert_eq!(output_data, vec![0x55; 4096]);
933
934 {
936 let mut sub_mut = buf.as_mut().subslice_mut(1024..2048);
937 assert_eq!(sub_mut.len(), 1024);
938 sub_mut.fill(0xaa);
939 }
940
941 {
942 let bref = buf.as_ref();
943 let sub_ref = bref.subslice(1024..2048);
944 assert_eq!(sub_ref.len(), 1024);
945 let mut sub_output = vec![0_u8; 1024];
946 sub_ref.copy_to_slice(&mut sub_output);
947 assert_eq!(sub_output, vec![0xaa; 1024]);
948 }
949
950 {
952 let (mut left_mut, mut right_mut) = buf.as_mut().split_at_mut(2048);
953 assert_eq!(left_mut.len(), 2048);
954 assert_eq!(right_mut.len(), 2048);
955 left_mut.fill(0x11);
956 right_mut.fill(0x22);
957 }
958
959 {
960 let bref = buf.as_ref();
961 let (left_ref, right_ref) = bref.split_at(2048);
962 let mut left_out = vec![0_u8; 2048];
963 let mut right_out = vec![0_u8; 2048];
964 left_ref.copy_to_slice(&mut left_out);
965 right_ref.copy_to_slice(&mut right_out);
966 assert_eq!(left_out, vec![0x11; 2048]);
967 assert_eq!(right_out, vec![0x22; 2048]);
968 }
969 }
970
971 #[fuchsia::test]
972 async fn test_owned_buffer() {
973 let source = BufferSource::new(4096);
974 let allocator = Arc::new(BufferAllocator::new(512, source));
975
976 let mut owned_buf = allocator.allocate_buffer_sync_owned(2048);
977 assert_eq!(owned_buf.len(), 2048);
978 owned_buf.as_mut_ptr_slice().fill(0xcc);
979 assert_eq!(owned_buf.as_ptr_slice().to_vec(), vec![0xcc; 2048]);
980
981 let owned_buf2 = allocator.try_allocate_buffer_owned(2048).expect("Must succeed");
983 assert_eq!(owned_buf2.len(), 2048);
984
985 assert!(allocator.try_allocate_buffer_owned(512).is_err());
987
988 std::mem::drop(owned_buf);
990
991 let mut owned_buf3 = allocator.try_allocate_buffer_owned(2048).expect("Must succeed");
993 owned_buf3.as_mut_ptr_slice().fill(0xdd);
994 assert_eq!(owned_buf3.as_ptr_slice().to_vec(), vec![0xdd; 2048]);
995 }
996
997 #[fuchsia::test]
998 async fn test_allocate_buffer_sync() {
999 let source = BufferSource::new(4096);
1000 let allocator = BufferAllocator::new(512, source);
1001
1002 let mut buf = allocator.allocate_buffer_sync(2048);
1003 assert_eq!(buf.len(), 2048);
1004 buf.as_mut_ptr_slice().fill(0xee);
1005 assert_eq!(buf.as_ptr_slice().to_vec(), vec![0xee; 2048]);
1006
1007 std::mem::drop(buf);
1008
1009 let mut buf2 = allocator.allocate_buffer_sync(4096);
1010 assert_eq!(buf2.len(), 4096);
1011 buf2.as_mut_ptr_slice().fill(0xff);
1012 assert_eq!(buf2.as_ptr_slice().to_vec(), vec![0xff; 4096]);
1013 }
1014
1015 #[fuchsia::test]
1016 async fn test_trusted_buffer_apis() {
1017 #[cfg(target_os = "fuchsia")]
1019 {
1020 let source = BufferSource::new(4096);
1021 let allocator = BufferAllocator::new(512, source);
1022 let mut buf = allocator.allocate_buffer(4096).await;
1023 assert!(buf.try_as_slice().is_none());
1024 assert!(buf.as_mut().try_as_mut_slice().is_none());
1025 }
1026
1027 {
1029 let source = BufferSource::new_trusted(4096);
1030 let allocator = BufferAllocator::new(512, source);
1031 let mut buf = allocator.allocate_buffer(4096).await;
1032 assert!(buf.try_as_slice().is_some());
1033 assert!(buf.as_mut().try_as_mut_slice().is_some());
1034
1035 let slice = buf.try_as_slice().unwrap();
1037 assert_eq!(slice.len(), 4096);
1038 let mut expected = vec![0u8; 4096];
1039 assert_eq!(slice, expected.as_slice());
1040
1041 let mut bref = buf.as_mut();
1042 let slice_mut = bref.try_as_mut_slice().unwrap();
1043 slice_mut[0] = 0xff;
1044 expected[0] = 0xff;
1045 assert_eq!(buf.try_as_slice().unwrap(), expected.as_slice());
1046 }
1047 }
1048
1049 #[fuchsia::test]
1050 #[cfg(target_os = "fuchsia")]
1051 async fn test_trusted_buffer_rights() {
1052 use zx;
1053 let source = BufferSource::new_trusted(4096);
1054 let vmo = source.vmo();
1055 let info = vmo.basic_info().expect("failed to get basic info");
1056 assert!(!info.rights.contains(zx::Rights::TRANSFER));
1057 }
1058}