Index: generic/src/mm/as.c
===================================================================
--- generic/src/mm/as.c	(revision e18cf3d2c00cddd79eafdc91fef81dc3df0667d5)
+++ generic/src/mm/as.c	(revision 1068f6a33444f5917a7f47f13b57ebe76e675eb3)
@@ -55,4 +55,5 @@
 #include <arch/mm/asid.h>
 #include <synch/spinlock.h>
+#include <synch/mutex.h>
 #include <adt/list.h>
 #include <adt/btree.h>
@@ -75,5 +76,5 @@
 as_operations_t *as_operations = NULL;
 
-/** Address space lock. It protects inactive_as_with_asid_head. */
+/** Address space lock. It protects inactive_as_with_asid_head. Must be acquired before as_t mutex. */
 SPINLOCK_INITIALIZE(as_lock);
 
@@ -111,5 +112,5 @@
 	as = (as_t *) malloc(sizeof(as_t), 0);
 	link_initialize(&as->inactive_as_with_asid_link);
-	spinlock_initialize(&as->lock, "as_lock");
+	mutex_initialize(&as->lock);
 	btree_create(&as->as_area_btree);
 	
@@ -163,8 +164,8 @@
 	
 	ipl = interrupts_disable();
-	spinlock_lock(&as->lock);
+	mutex_lock(&as->lock);
 	
 	if (!check_area_conflicts(as, base, size, NULL)) {
-		spinlock_unlock(&as->lock);
+		mutex_unlock(&as->lock);
 		interrupts_restore(ipl);
 		return NULL;
@@ -173,5 +174,5 @@
 	a = (as_area_t *) malloc(sizeof(as_area_t), 0);
 
-	spinlock_initialize(&a->lock, "as_area_lock");
+	mutex_initialize(&a->lock);
 	
 	a->flags = flags;
@@ -182,5 +183,5 @@
 	btree_insert(&as->as_area_btree, base, (void *) a, NULL);
 
-	spinlock_unlock(&as->lock);
+	mutex_unlock(&as->lock);
 	interrupts_restore(ipl);
 
@@ -204,5 +205,5 @@
 	
 	ipl = interrupts_disable();
-	spinlock_lock(&as->lock);
+	mutex_lock(&as->lock);
 	
 	/*
@@ -211,5 +212,5 @@
 	area = find_area_and_lock(as, address);
 	if (!area) {
-		spinlock_unlock(&as->lock);
+		mutex_unlock(&as->lock);
 		interrupts_restore(ipl);
 		return ENOENT;
@@ -221,6 +222,6 @@
 		 * with memory mapped devices is not supported.
 		 */
-		spinlock_unlock(&area->lock);
-		spinlock_unlock(&as->lock);
+		mutex_unlock(&area->lock);
+		mutex_unlock(&as->lock);
 		interrupts_restore(ipl);
 		return ENOTSUP;
@@ -232,6 +233,6 @@
 		 * Zero size address space areas are not allowed.
 		 */
-		spinlock_unlock(&area->lock);
-		spinlock_unlock(&as->lock);
+		mutex_unlock(&area->lock);
+		mutex_unlock(&as->lock);
 		interrupts_restore(ipl);
 		return EPERM;
@@ -279,6 +280,6 @@
 		 */
 		if (!check_area_conflicts(as, address, pages * PAGE_SIZE, area)) {
-			spinlock_unlock(&area->lock);
-			spinlock_unlock(&as->lock);		
+			mutex_unlock(&area->lock);
+			mutex_unlock(&as->lock);		
 			interrupts_restore(ipl);
 			return EADDRNOTAVAIL;
@@ -288,6 +289,6 @@
 	area->pages = pages;
 	
-	spinlock_unlock(&area->lock);
-	spinlock_unlock(&as->lock);
+	mutex_unlock(&area->lock);
+	mutex_unlock(&as->lock);
 	interrupts_restore(ipl);
 
@@ -310,9 +311,9 @@
 
 	ipl = interrupts_disable();
-	spinlock_lock(&as->lock);
+	mutex_lock(&as->lock);
 
 	area = find_area_and_lock(as, address);
 	if (!area) {
-		spinlock_unlock(&as->lock);
+		mutex_unlock(&as->lock);
 		interrupts_restore(ipl);
 		return ENOENT;
@@ -351,5 +352,5 @@
 
 	area->attributes |= AS_AREA_ATTR_PARTIAL;
-	spinlock_unlock(&area->lock);
+	mutex_unlock(&area->lock);
 
 	/*
@@ -360,5 +361,5 @@
 	free(area);
 	
-	spinlock_unlock(&AS->lock);
+	mutex_unlock(&AS->lock);
 	interrupts_restore(ipl);
 	return 0;
@@ -398,5 +399,5 @@
 	src_as = src_task->as;
 	
-	spinlock_lock(&src_as->lock);
+	mutex_lock(&src_as->lock);
 	src_area = find_area_and_lock(src_as, src_base);
 	if (!src_area) {
@@ -405,5 +406,5 @@
 		 */
 		spinlock_unlock(&src_task->lock);
-		spinlock_unlock(&src_as->lock);
+		mutex_unlock(&src_as->lock);
 		interrupts_restore(ipl);
 		return ENOENT;
@@ -411,6 +412,6 @@
 	src_size = src_area->pages * PAGE_SIZE;
 	src_flags = src_area->flags;
-	spinlock_unlock(&src_area->lock);
-	spinlock_unlock(&src_as->lock);
+	mutex_unlock(&src_area->lock);
+	mutex_unlock(&src_as->lock);
 
 
@@ -442,9 +443,9 @@
 	 */
 	if (AS < src_as) {
-		spinlock_lock(&AS->lock);
-		spinlock_lock(&src_as->lock);
+		mutex_lock(&AS->lock);
+		mutex_lock(&src_as->lock);
 	} else {
-		spinlock_lock(&AS->lock);
-		spinlock_lock(&src_as->lock);
+		mutex_lock(&AS->lock);
+		mutex_lock(&src_as->lock);
 	}
 	
@@ -476,10 +477,10 @@
 	 * attribute.
 	 */	
-	spinlock_lock(&dst_area->lock);
+	mutex_lock(&dst_area->lock);
 	dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL;
-	spinlock_unlock(&dst_area->lock);
-	
-	spinlock_unlock(&AS->lock);
-	spinlock_unlock(&src_as->lock);
+	mutex_unlock(&dst_area->lock);
+	
+	mutex_unlock(&AS->lock);
+	mutex_unlock(&src_as->lock);
 	interrupts_restore(ipl);
 	
@@ -512,5 +513,5 @@
 	page_mapping_insert(as, page, frame, get_area_flags(area));
 	
-	spinlock_unlock(&area->lock);
+	mutex_unlock(&area->lock);
 	page_table_unlock(as, true);
 	interrupts_restore(ipl);
@@ -533,7 +534,10 @@
 	__address frame;
 	
+	if (!THREAD)
+		return 0;
+		
 	ASSERT(AS);
 
-	spinlock_lock(&AS->lock);
+	mutex_lock(&AS->lock);
 	area = find_area_and_lock(AS, page);	
 	if (!area) {
@@ -542,5 +546,5 @@
 		 * Signal page fault to low-level handler.
 		 */
-		spinlock_unlock(&AS->lock);
+		mutex_unlock(&AS->lock);
 		goto page_fault;
 	}
@@ -551,6 +555,6 @@
 		 * Avoid possible race by returning error.
 		 */
-		spinlock_unlock(&area->lock);
-		spinlock_unlock(&AS->lock);
+		mutex_unlock(&area->lock);
+		mutex_unlock(&AS->lock);
 		goto page_fault;		
 	}
@@ -568,6 +572,6 @@
 		if (PTE_PRESENT(pte)) {
 			page_table_unlock(AS, false);
-			spinlock_unlock(&area->lock);
-			spinlock_unlock(&AS->lock);
+			mutex_unlock(&area->lock);
+			mutex_unlock(&AS->lock);
 			return 1;
 		}
@@ -599,6 +603,6 @@
 	page_table_unlock(AS, false);
 	
-	spinlock_unlock(&area->lock);
-	spinlock_unlock(&AS->lock);
+	mutex_unlock(&area->lock);
+	mutex_unlock(&AS->lock);
 	return AS_PF_OK;
 
@@ -622,4 +626,7 @@
 /** Switch address spaces.
  *
+ * Note that this function cannot sleep as it is essentially a part of
+ * the scheduling. Sleeping here would lead to deadlock on wakeup.
+ *
  * @param old Old address space or NULL.
  * @param new New address space.
@@ -637,5 +644,5 @@
 	 */	
 	if (old) {
-		spinlock_lock(&old->lock);
+		mutex_lock_active(&old->lock);
 		ASSERT(old->refcount);
 		if((--old->refcount == 0) && (old != AS_KERNEL)) {
@@ -649,5 +656,5 @@
 			 list_append(&old->inactive_as_with_asid_link, &inactive_as_with_asid_head);
 		}
-		spinlock_unlock(&old->lock);
+		mutex_unlock(&old->lock);
 	}
 
@@ -655,5 +662,5 @@
 	 * Second, prepare the new address space.
 	 */
-	spinlock_lock(&new->lock);
+	mutex_lock_active(&new->lock);
 	if ((new->refcount++ == 0) && (new != AS_KERNEL)) {
 		if (new->asid != ASID_INVALID)
@@ -663,5 +670,5 @@
 	}
 	SET_PTL0_ADDRESS(new->page_table);
-	spinlock_unlock(&new->lock);
+	mutex_unlock(&new->lock);
 
 	if (needs_asid) {
@@ -673,7 +680,7 @@
 		
 		asid = asid_get();
-		spinlock_lock(&new->lock);
+		mutex_lock_active(&new->lock);
 		new->asid = asid;
-		spinlock_unlock(&new->lock);
+		mutex_unlock(&new->lock);
 	}
 	spinlock_unlock(&as_lock);
@@ -799,5 +806,5 @@
 	if (a) {
 		/* va is the base address of an address space area */
-		spinlock_lock(&a->lock);
+		mutex_lock(&a->lock);
 		return a;
 	}
@@ -812,9 +819,9 @@
 	for (i = 0; i < leaf->keys; i++) {
 		a = (as_area_t *) leaf->value[i];
-		spinlock_lock(&a->lock);
+		mutex_lock(&a->lock);
 		if ((a->base <= va) && (va < a->base + a->pages * PAGE_SIZE)) {
 			return a;
 		}
-		spinlock_unlock(&a->lock);
+		mutex_unlock(&a->lock);
 	}
 
@@ -825,9 +832,9 @@
 	if ((lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf))) {
 		a = (as_area_t *) lnode->value[lnode->keys - 1];
-		spinlock_lock(&a->lock);
+		mutex_lock(&a->lock);
 		if (va < a->base + a->pages * PAGE_SIZE) {
 			return a;
 		}
-		spinlock_unlock(&a->lock);
+		mutex_unlock(&a->lock);
 	}
 
@@ -874,19 +881,19 @@
 	if ((node = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf))) {
 		a = (as_area_t *) node->value[node->keys - 1];
-		spinlock_lock(&a->lock);
+		mutex_lock(&a->lock);
 		if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
-			spinlock_unlock(&a->lock);
+			mutex_unlock(&a->lock);
 			return false;
 		}
-		spinlock_unlock(&a->lock);
+		mutex_unlock(&a->lock);
 	}
 	if ((node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf))) {
 		a = (as_area_t *) node->value[0];
-		spinlock_lock(&a->lock);
+		mutex_lock(&a->lock);
 		if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
-			spinlock_unlock(&a->lock);
+			mutex_unlock(&a->lock);
 			return false;
 		}
-		spinlock_unlock(&a->lock);
+		mutex_unlock(&a->lock);
 	}
 	
@@ -898,10 +905,10 @@
 			continue;
 	
-		spinlock_lock(&a->lock);
+		mutex_lock(&a->lock);
 		if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
-			spinlock_unlock(&a->lock);
+			mutex_unlock(&a->lock);
 			return false;
 		}
-		spinlock_unlock(&a->lock);
+		mutex_unlock(&a->lock);
 	}
 
@@ -918,5 +925,5 @@
 }
 
-/** Return size of address space of current task pointed to by base */
+/** Return size of the address space area with given base.  */
 size_t as_get_size(__address base)
 {
@@ -929,5 +936,5 @@
 	if (src_area){
 		size = src_area->pages * PAGE_SIZE;
-		spinlock_unlock(&src_area->lock);
+		mutex_unlock(&src_area->lock);
 	} else {
 		size = 0;
