forked from Bananymous/banan-os
				
			Kernel: Implement MemoryRegion pinning
This allows process to pin a MemoryRegion into users memory space for syscall duration without allowing user to munmap the region.
This commit is contained in:
		
							parent
							
								
									808c97020a
								
							
						
					
					
						commit
						d54489bbcb
					
				|  | @ -3,8 +3,7 @@ | ||||||
| #include <BAN/UniqPtr.h> | #include <BAN/UniqPtr.h> | ||||||
| #include <kernel/Memory/PageTable.h> | #include <kernel/Memory/PageTable.h> | ||||||
| #include <kernel/Memory/Types.h> | #include <kernel/Memory/Types.h> | ||||||
| 
 | #include <kernel/ThreadBlocker.h> | ||||||
| #include <stddef.h> |  | ||||||
| 
 | 
 | ||||||
| namespace Kernel | namespace Kernel | ||||||
| { | { | ||||||
|  | @ -42,6 +41,10 @@ namespace Kernel | ||||||
| 		size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); } | 		size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); } | ||||||
| 		size_t physical_page_count() const { return m_physical_page_count; } | 		size_t physical_page_count() const { return m_physical_page_count; } | ||||||
| 
 | 
 | ||||||
|  | 		void pin() { m_pinned_count++; } | ||||||
|  | 		void unpin() { if (--m_pinned_count == 0) m_pinned_blocker.unblock(); } | ||||||
|  | 		void wait_not_pinned() { while (m_pinned_count) m_pinned_blocker.block_with_timeout_ms(100); } | ||||||
|  | 
 | ||||||
| 		virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0; | 		virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0; | ||||||
| 
 | 
 | ||||||
| 		// Returns error if no memory was available
 | 		// Returns error if no memory was available
 | ||||||
|  | @ -64,6 +67,9 @@ namespace Kernel | ||||||
| 		const PageTable::flags_t m_flags; | 		const PageTable::flags_t m_flags; | ||||||
| 		vaddr_t m_vaddr { 0 }; | 		vaddr_t m_vaddr { 0 }; | ||||||
| 		size_t m_physical_page_count { 0 }; | 		size_t m_physical_page_count { 0 }; | ||||||
|  | 
 | ||||||
|  | 		BAN::Atomic<size_t> m_pinned_count { 0 }; | ||||||
|  | 		ThreadBlocker m_pinned_blocker; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 	MemoryRegion::~MemoryRegion() | 	MemoryRegion::~MemoryRegion() | ||||||
| 	{ | 	{ | ||||||
|  | 		ASSERT(m_pinned_count == 0); | ||||||
| 		if (m_vaddr) | 		if (m_vaddr) | ||||||
| 			m_page_table.unmap_range(m_vaddr, m_size); | 			m_page_table.unmap_range(m_vaddr, m_size); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -1806,7 +1806,10 @@ namespace Kernel | ||||||
| 			const vaddr_t region_s = region->vaddr(); | 			const vaddr_t region_s = region->vaddr(); | ||||||
| 			const vaddr_t region_e = region->vaddr() + region->size(); | 			const vaddr_t region_e = region->vaddr() + region->size(); | ||||||
| 			if (vaddr <= region_s && region_e <= vaddr + len) | 			if (vaddr <= region_s && region_e <= vaddr + len) | ||||||
|  | 			{ | ||||||
|  | 				region->wait_not_pinned(); | ||||||
| 				m_mapped_regions.remove(i--); | 				m_mapped_regions.remove(i--); | ||||||
|  | 			} | ||||||
| 			else if (region->overlaps(vaddr, len)) | 			else if (region->overlaps(vaddr, len)) | ||||||
| 				dwarnln("TODO: partial region munmap"); | 				dwarnln("TODO: partial region munmap"); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue