summaryrefslogtreecommitdiff
path: root/vm
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2016-07-23 00:52:47 +0200
committerRichard Braun <rbraun@sceen.net>2016-08-07 21:16:58 +0200
commit5dd4f67522ad0d49a2cecdb9b109251f546d4dd1 (patch)
treea307863494bfe7b0c4a3e44b524b7f0b8a181526 /vm
parentbc23dda642a299fb1380294f4e5940511bc512ef (diff)
VM: fix pageout-related deadlock
* vm/vm_map.c (_vm_map_entry_create): Temporarily set the current thread as VM privileged.
Diffstat (limited to 'vm')
-rw-r--r--vm/vm_map.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/vm/vm_map.c b/vm/vm_map.c
index ccbe8f1a..acac66e4 100644
--- a/vm/vm_map.c
+++ b/vm/vm_map.c
@@ -241,8 +241,26 @@ vm_map_entry_t _vm_map_entry_create(map_header)
const struct vm_map_header *map_header;
{
vm_map_entry_t entry;
+ boolean_t vm_privilege;
+ /*
+ * XXX Map entry creation may occur while a map is locked,
+ * for example when clipping entries. If the system is running
+ * low on memory, allocating an entry may block until pages
+ * are available. But if a map used by the default pager is
+ * kept locked, a deadlock occurs.
+ *
+ * This workaround temporarily elevates the current thread
+ * VM privileges to avoid that particular deadlock, and does
+ * so regardless of the map for convenience, and because it's
+ * currently impossible to predict which map the default pager
+ * may depend on.
+ */
+ vm_privilege = current_thread()->vm_privilege;
+ current_thread()->vm_privilege = TRUE;
entry = (vm_map_entry_t) kmem_cache_alloc(&vm_map_entry_cache);
+ current_thread()->vm_privilege = vm_privilege;
+
if (entry == VM_MAP_ENTRY_NULL)
panic("vm_map_entry_create");