@@ -649,6 +649,16 @@ fn adjust_chosen_chunk(
649
649
}
650
650
651
651
652
+ /// Possible options when requested pages from the page allocator.
653
+ pub enum AllocationRequest < ' r > {
654
+ /// The allocated pages can be located at any virtual address.
655
+ Any ,
656
+ /// The allocated pages must start exactly at the given `VirtualAddress`.
657
+ AtVirtualAddress ( VirtualAddress ) ,
658
+ /// The allocated pages can be located anywhere within the given range.
659
+ WithinRange ( & ' r PageRange ) ,
660
+ }
661
+
652
662
/// The core page allocation routine that allocates the given number of virtual pages,
653
663
/// optionally at the requested starting `VirtualAddress`.
654
664
///
@@ -660,9 +670,8 @@ fn adjust_chosen_chunk(
660
670
/// Fragmentation isn't cleaned up until we're out of address space, but that's not really a big deal.
661
671
///
662
672
/// # Arguments
663
- /// * `requested_vaddr`: if `Some`, the returned `AllocatedPages` will start at the `Page`
664
- /// containing this `VirtualAddress`.
665
- /// If `None`, the first available `Page` range will be used, starting at any random virtual address.
673
+ /// * `request`: whether to allocate `num_pages` pages at any address,
674
+ /// at a specific virtual address, or withing a specified range.
666
675
/// * `num_pages`: the number of `Page`s to be allocated.
667
676
///
668
677
/// # Return
@@ -672,9 +681,8 @@ fn adjust_chosen_chunk(
672
681
/// Those actions are deferred until this returned `DeferredAllocAction` struct object is dropped,
673
682
/// allowing the caller (such as the heap implementation itself) to control when heap allocation may occur.
674
683
pub fn allocate_pages_deferred (
675
- requested_vaddr : Option < VirtualAddress > ,
684
+ request : AllocationRequest ,
676
685
num_pages : usize ,
677
- within_range : Option < & PageRange > ,
678
686
) -> Result < ( AllocatedPages , DeferredAllocAction < ' static > ) , & ' static str > {
679
687
if num_pages == 0 {
680
688
warn ! ( "PageAllocator: requested an allocation of 0 pages... stupid!" ) ;
@@ -688,12 +696,18 @@ pub fn allocate_pages_deferred(
688
696
// - Can fit the requested size (starting at the requested address) within the chunk.
689
697
// - The chunk can only be within in a designated region if a specific address was requested,
690
698
// or all other non-designated chunks are already in use.
691
- if let Some ( vaddr) = requested_vaddr {
692
- find_specific_chunk ( & mut locked_list, Page :: containing_address ( vaddr) , num_pages)
693
- } else {
694
- find_any_chunk ( & mut locked_list, num_pages, within_range)
695
- }
696
- . map_err ( From :: from) // convert from AllocationError to &str
699
+ let res = match request {
700
+ AllocationRequest :: AtVirtualAddress ( vaddr) => {
701
+ find_specific_chunk ( & mut locked_list, Page :: containing_address ( vaddr) , num_pages)
702
+ }
703
+ AllocationRequest :: Any => {
704
+ find_any_chunk ( & mut locked_list, num_pages, None )
705
+ }
706
+ AllocationRequest :: WithinRange ( range) => {
707
+ find_any_chunk ( & mut locked_list, num_pages, Some ( range) )
708
+ }
709
+ } ;
710
+ res. map_err ( From :: from) // convert from AllocationError to &str
697
711
}
698
712
699
713
@@ -702,24 +716,24 @@ pub fn allocate_pages_deferred(
702
716
///
703
717
/// This function still allocates whole pages by rounding up the number of bytes.
704
718
pub fn allocate_pages_by_bytes_deferred (
705
- requested_vaddr : Option < VirtualAddress > ,
719
+ request : AllocationRequest ,
706
720
num_bytes : usize ,
707
721
) -> Result < ( AllocatedPages , DeferredAllocAction < ' static > ) , & ' static str > {
708
- let actual_num_bytes = if let Some ( vaddr) = requested_vaddr {
722
+ let actual_num_bytes = if let AllocationRequest :: AtVirtualAddress ( vaddr) = request {
709
723
num_bytes + ( vaddr. value ( ) % PAGE_SIZE )
710
724
} else {
711
725
num_bytes
712
726
} ;
713
727
let num_pages = ( actual_num_bytes + PAGE_SIZE - 1 ) / PAGE_SIZE ; // round up
714
- allocate_pages_deferred ( requested_vaddr , num_pages, None )
728
+ allocate_pages_deferred ( request , num_pages)
715
729
}
716
730
717
731
718
732
/// Allocates the given number of pages with no constraints on the starting virtual address.
719
733
///
720
734
/// See [`allocate_pages_deferred()`](fn.allocate_pages_deferred.html) for more details.
721
735
pub fn allocate_pages ( num_pages : usize ) -> Option < AllocatedPages > {
722
- allocate_pages_deferred ( None , num_pages, None )
736
+ allocate_pages_deferred ( AllocationRequest :: Any , num_pages)
723
737
. map ( |( ap, _action) | ap)
724
738
. ok ( )
725
739
}
@@ -731,7 +745,7 @@ pub fn allocate_pages(num_pages: usize) -> Option<AllocatedPages> {
731
745
/// This function still allocates whole pages by rounding up the number of bytes.
732
746
/// See [`allocate_pages_deferred()`](fn.allocate_pages_deferred.html) for more details.
733
747
pub fn allocate_pages_by_bytes ( num_bytes : usize ) -> Option < AllocatedPages > {
734
- allocate_pages_by_bytes_deferred ( None , num_bytes)
748
+ allocate_pages_by_bytes_deferred ( AllocationRequest :: Any , num_bytes)
735
749
. map ( |( ap, _action) | ap)
736
750
. ok ( )
737
751
}
@@ -742,7 +756,7 @@ pub fn allocate_pages_by_bytes(num_bytes: usize) -> Option<AllocatedPages> {
742
756
/// This function still allocates whole pages by rounding up the number of bytes.
743
757
/// See [`allocate_pages_deferred()`](fn.allocate_pages_deferred.html) for more details.
744
758
pub fn allocate_pages_by_bytes_at ( vaddr : VirtualAddress , num_bytes : usize ) -> Result < AllocatedPages , & ' static str > {
745
- allocate_pages_by_bytes_deferred ( Some ( vaddr) , num_bytes)
759
+ allocate_pages_by_bytes_deferred ( AllocationRequest :: AtVirtualAddress ( vaddr) , num_bytes)
746
760
. map ( |( ap, _action) | ap)
747
761
}
748
762
@@ -751,7 +765,7 @@ pub fn allocate_pages_by_bytes_at(vaddr: VirtualAddress, num_bytes: usize) -> Re
751
765
///
752
766
/// See [`allocate_pages_deferred()`](fn.allocate_pages_deferred.html) for more details.
753
767
pub fn allocate_pages_at ( vaddr : VirtualAddress , num_pages : usize ) -> Result < AllocatedPages , & ' static str > {
754
- allocate_pages_deferred ( Some ( vaddr) , num_pages, None )
768
+ allocate_pages_deferred ( AllocationRequest :: AtVirtualAddress ( vaddr) , num_pages)
755
769
. map ( |( ap, _action) | ap)
756
770
}
757
771
@@ -762,7 +776,7 @@ pub fn allocate_pages_in_range(
762
776
num_pages : usize ,
763
777
range : & PageRange ,
764
778
) -> Result < AllocatedPages , & ' static str > {
765
- allocate_pages_deferred ( None , num_pages , Some ( range) )
779
+ allocate_pages_deferred ( AllocationRequest :: WithinRange ( range) , num_pages )
766
780
. map ( |( ap, _action) | ap)
767
781
}
768
782
@@ -773,8 +787,7 @@ pub fn allocate_pages_by_bytes_in_range(
773
787
num_bytes : usize ,
774
788
range : & PageRange ,
775
789
) -> Result < AllocatedPages , & ' static str > {
776
- let num_pages = ( num_bytes + PAGE_SIZE - 1 ) / PAGE_SIZE ; // round up
777
- allocate_pages_deferred ( None , num_pages, Some ( range) )
790
+ allocate_pages_by_bytes_deferred ( AllocationRequest :: WithinRange ( range) , num_bytes)
778
791
. map ( |( ap, _action) | ap)
779
792
}
780
793
0 commit comments