Index: uspace/lib/c/generic/malloc.c
===================================================================
--- uspace/lib/c/generic/malloc.c	(revision 21799398fb5b1afa28852a26b87fcf58caf15a28)
+++ uspace/lib/c/generic/malloc.c	(revision 2a5d1751090211ae7f388acdeff5287ff75e2b8f)
@@ -200,5 +200,5 @@
 	do { \
 		if (!(expr)) {\
-			futex_up(&malloc_futex); \
+			heap_unlock(); \
 			assert_abort(#expr, __FILE__, __LINE__); \
 		} \
@@ -210,4 +210,69 @@
 
 #endif /* NDEBUG */
+
+
+#ifdef FUTEX_UPGRADABLE
+/** True if the heap may be accessed from multiple threads. */
+static bool multithreaded = false;
+
+/** Makes accesses to the heap thread safe. */
+void malloc_enable_multithreaded(void)
+{
+	multithreaded = true;
+}
+
+/** Serializes access to the heap from multiple threads. */
+static inline void heap_lock(void)
+{
+	if (multithreaded) {
+		futex_down(&malloc_futex);
+	} else {
+		/*
+		 * Malloc never switches fibrils while the heap is locked.
+		 * Similarly, it never creates new threads from within the 
+		 * locked region. Therefore, if there are no other threads 
+		 * except this one, the whole operation will complete without 
+		 * any interruptions.
+		 */
+	}
+}
+
+/** Serializes access to the heap from multiple threads. */
+static inline void heap_unlock(void)
+{
+	if (multithreaded) {
+		futex_up(&malloc_futex);
+	} else {
+		/*
+		 * Malloc never switches fibrils while the heap is locked.
+		 * Similarly, it never creates new threads from within the 
+		 * locked region. Therefore, if there are no other threads 
+		 * except this one, the whole operation will complete without 
+		 * any interruptions.
+		 */
+	}
+}
+
+#else
+
+/** Makes accesses to the heap thread safe. */
+void malloc_enable_multithreaded(void)
+{
+	/* No-op. Already using thread-safe heap locking operations. */
+}
+
+/** Serializes access to the heap from multiple threads. */
+static inline void heap_lock(void)
+{
+	futex_down(&malloc_futex);
+}
+
+/** Serializes access to the heap from multiple threads. */
+static inline void heap_unlock(void)
+{
+	futex_up(&malloc_futex);
+}
+#endif
+
 
 /** Initialize a heap block
@@ -785,8 +850,8 @@
 void *malloc(const size_t size)
 {
-	futex_down(&malloc_futex);
+	heap_lock();
 	void *block = malloc_internal(size, BASE_ALIGN);
-	futex_up(&malloc_futex);
-	
+	heap_unlock();
+
 	return block;
 }
@@ -807,9 +872,9 @@
 	size_t palign =
 	    1 << (fnzb(max(sizeof(void *), align) - 1) + 1);
-	
-	futex_down(&malloc_futex);
+
+	heap_lock();
 	void *block = malloc_internal(size, palign);
-	futex_up(&malloc_futex);
-	
+	heap_unlock();
+
 	return block;
 }
@@ -828,5 +893,5 @@
 		return malloc(size);
 	
-	futex_down(&malloc_futex);
+	heap_lock();
 	
 	/* Calculate the position of the header. */
@@ -885,5 +950,5 @@
 	}
 	
-	futex_up(&malloc_futex);
+	heap_unlock();
 	
 	if (reloc) {
@@ -908,5 +973,5 @@
 		return;
 	
-	futex_down(&malloc_futex);
+	heap_lock();
 	
 	/* Calculate the position of the header. */
@@ -953,13 +1018,13 @@
 	heap_shrink(area);
 	
-	futex_up(&malloc_futex);
+	heap_unlock();
 }
 
 void *heap_check(void)
 {
-	futex_down(&malloc_futex);
+	heap_lock();
 	
 	if (first_heap_area == NULL) {
-		futex_up(&malloc_futex);
+		heap_unlock();
 		return (void *) -1;
 	}
@@ -975,5 +1040,5 @@
 		    (((uintptr_t) area->start % PAGE_SIZE) != 0) ||
 		    (((uintptr_t) area->end % PAGE_SIZE) != 0)) {
-			futex_up(&malloc_futex);
+			heap_unlock();
 			return (void *) area;
 		}
@@ -986,5 +1051,5 @@
 			/* Check heap block consistency */
 			if (head->magic != HEAP_BLOCK_HEAD_MAGIC) {
-				futex_up(&malloc_futex);
+				heap_unlock();
 				return (void *) head;
 			}
@@ -994,5 +1059,5 @@
 			if ((foot->magic != HEAP_BLOCK_FOOT_MAGIC) ||
 			    (head->size != foot->size)) {
-				futex_up(&malloc_futex);
+				heap_unlock();
 				return (void *) foot;
 			}
@@ -1000,5 +1065,5 @@
 	}
 	
-	futex_up(&malloc_futex);
+	heap_unlock();
 	
 	return NULL;
