From 50e4dd932864f2ea5007d00a787a349859d05fea Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 12 Apr 2010 20:30:49 +0000 Subject: [PATCH] axeld + bonefish: X86VMTranslationMap::Protect(): * Removed rounding up the end address to page alignment. It's not necessary and could cause an overflow. * Fixed possible infinite loop triggered by a rare race condition: When two threads of a team were accessing the same unmapped page at the same time each would trigger a page fault. One thread would map the page again, the second would wait until the first one was done and update the page protection (unnecessarily but harmlessly). If the first thread accessed the page again at an unfortunate time, it would implicitly change the accessed/dirty flags of the page's PTE, which was a situation the loop in Protect() didn't consider and thus run forever. Seen the problem twice today in form of an app server freeze. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36197 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/arch/x86/arch_vm_translation_map.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp index 44ef4266a3..bb3b84df89 100644 --- a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp @@ -976,7 +976,6 @@ X86VMTranslationMap::Protect(addr_t start, addr_t end, uint32 attributes) page_directory_entry *pd = fArchData->pgdir_virt; start = ROUNDDOWN(start, B_PAGE_SIZE); - end = ROUNDUP(end, B_PAGE_SIZE); TRACE("protect_tmap: pages 0x%lx to 0x%lx, attributes %lx\n", start, end, attributes); @@ -1022,12 +1021,15 @@ restart: // set the new protection flags -- we want to do that atomically, // without changing the accessed or dirty flag page_table_entry oldEntry; - do { + while (true) { oldEntry = test_and_set_page_table_entry(&pt[index], (entry & ~(X86_PTE_WRITABLE | X86_PTE_USER)) | newProtectionFlags, entry); - } while (oldEntry != entry); + if (oldEntry == entry) + break; + entry = oldEntry; + } if ((oldEntry & X86_PTE_ACCESSED) != 0) { // Note, that we only need to invalidate the address, if the