Index: kernel/arch/mips32/src/mm/tlb.c
===================================================================
--- kernel/arch/mips32/src/mm/tlb.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ kernel/arch/mips32/src/mm/tlb.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -557,6 +557,7 @@
 	entry_hi_t hi, hi_save;
 	tlb_index_t index;
-
-	ASSERT(asid != ASID_INVALID);
+	
+	if (asid == ASID_INVALID)
+		return;
 
 	hi_save.value = cp0_entry_hi_read();
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ kernel/generic/include/mm/as.h	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -115,17 +115,19 @@
 	
 	/**
-	 * Number of processors on wich is this address space active.
-	 * Protected by asidlock.
+	 * Number of processors on which this
+	 * address space is active. Protected by
+	 * asidlock.
 	 */
 	size_t cpu_refcount;
 	
-	/**
-	 * Address space identifier.
-	 * Constant on architectures that do not support ASIDs.
-	 * Protected by asidlock.
+	/** Address space identifier.
+	 *
+	 * Constant on architectures that do not
+	 * support ASIDs. Protected by asidlock.
+	 *
 	 */
 	asid_t asid;
 	
-	/** Number of references (i.e tasks that reference this as). */
+	/** Number of references (i.e. tasks that reference this as). */
 	atomic_t refcount;
 	
@@ -199,24 +201,29 @@
 typedef struct {
 	mutex_t lock;
+	
 	/** Containing address space. */
 	as_t *as;
 	
-	/**
-	 * Flags related to the memory represented by the address space area.
-	 */
+	/** Memory flags. */
 	unsigned int flags;
 	
-	/** Attributes related to the address space area itself. */
+	/** Address space area attributes. */
 	unsigned int attributes;
-	/** Size of this area in multiples of PAGE_SIZE. */
+	
+	/** Number of pages in the area. */
 	size_t pages;
+	
+	/** Number of resident pages in the area. */
+	size_t resident;
+	
 	/** Base address of this area. */
 	uintptr_t base;
+	
 	/** Map of used space. */
 	btree_t used_space;
 	
 	/**
-	 * If the address space area has been shared, this pointer will
-	 * reference the share info structure.
+	 * If the address space area is shared. this is
+	 * a reference to the share info structure.
 	 */
 	share_info_t *sh_info;
@@ -261,7 +268,6 @@
 extern bool as_area_check_access(as_area_t *, pf_access_t);
 extern size_t as_area_get_size(uintptr_t);
-extern int used_space_insert(as_area_t *, uintptr_t, size_t);
-extern int used_space_remove(as_area_t *, uintptr_t, size_t);
-
+extern bool used_space_insert(as_area_t *, uintptr_t, size_t);
+extern bool used_space_remove(as_area_t *, uintptr_t, size_t);
 
 /* Interface to be implemented by architectures. */
@@ -307,4 +313,5 @@
 extern sysarg_t sys_as_area_change_flags(uintptr_t, unsigned int);
 extern sysarg_t sys_as_area_destroy(uintptr_t);
+extern sysarg_t sys_as_get_unmapped_area(uintptr_t, size_t);
 
 /* Introspection functions. */
Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ kernel/generic/include/syscall/syscall.h	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -59,4 +59,5 @@
 	SYS_AS_AREA_CHANGE_FLAGS,
 	SYS_AS_AREA_DESTROY,
+	SYS_AS_GET_UNMAPPED_AREA,
 	
 	SYS_IPC_CALL_SYNC_FAST,
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ kernel/generic/src/mm/as.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -71,4 +71,5 @@
 #include <memstr.h>
 #include <macros.h>
+#include <bitops.h>
 #include <arch.h>
 #include <errno.h>
@@ -86,17 +87,15 @@
  * Each architecture decides what functions will be used to carry out
  * address space operations such as creating or locking page tables.
- *
  */
 as_operations_t *as_operations = NULL;
 
-/**
- * Slab for as_t objects.
+/** Slab for as_t objects.
  *
  */
 static slab_cache_t *as_slab;
 
-/**
- * This lock serializes access to the ASID subsystem.
- * It protects:
+/** ASID subsystem lock.
+ *
+ * This lock protects:
  * - inactive_as_with_asid_head list
  * - as->asid for each as of the as_t type
@@ -107,7 +106,6 @@
 
 /**
- * This list contains address spaces that are not active on any
- * processor and that have valid ASID.
- *
+ * Inactive address spaces (on all processors)
+ * that have valid ASID.
  */
 LIST_INITIALIZE(inactive_as_with_asid_head);
@@ -123,13 +121,10 @@
 	mutex_initialize(&as->lock, MUTEX_PASSIVE);
 	
-	int rc = as_constructor_arch(as, flags);
-	
-	return rc;
+	return as_constructor_arch(as, flags);
 }
 
 NO_TRACE static size_t as_destructor(void *obj)
 {
-	as_t *as = (as_t *) obj;
-	return as_destructor_arch(as);
+	return as_destructor_arch((as_t *) obj);
 }
 
@@ -146,5 +141,6 @@
 		panic("Cannot create kernel address space.");
 	
-	/* Make sure the kernel address space
+	/*
+	 * Make sure the kernel address space
 	 * reference count never drops to zero.
 	 */
@@ -195,5 +191,5 @@
 {
 	DEADLOCK_PROBE_INIT(p_asidlock);
-
+	
 	ASSERT(as != AS);
 	ASSERT(atomic_get(&as->refcount) == 0);
@@ -203,5 +199,5 @@
 	 * lock its mutex.
 	 */
-
+	
 	/*
 	 * We need to avoid deadlock between TLB shootdown and asidlock.
@@ -210,5 +206,4 @@
 	 * disabled to prevent nested context switches. We also depend on the
 	 * fact that so far no spinlocks are held.
-	 *
 	 */
 	preemption_disable();
@@ -235,5 +230,5 @@
 	spinlock_unlock(&asidlock);
 	interrupts_restore(ipl);
-
+	
 	
 	/*
@@ -241,5 +236,4 @@
 	 * The B+tree must be walked carefully because it is
 	 * also being destroyed.
-	 *
 	 */
 	bool cond = true;
@@ -268,6 +262,6 @@
 /** Hold a reference to an address space.
  *
- * Holding a reference to an address space prevents destruction of that address
- * space.
+ * Holding a reference to an address space prevents destruction
+ * of that address space.
  *
  * @param as Address space to be held.
@@ -281,6 +275,6 @@
 /** Release a reference to an address space.
  *
- * The last one to release a reference to an address space destroys the address
- * space.
+ * The last one to release a reference to an address space
+ * destroys the address space.
  *
  * @param asAddress space to be released.
@@ -295,22 +289,22 @@
 /** Check area conflicts with other areas.
  *
- * @param as         Address space.
- * @param va         Starting virtual address of the area being tested.
- * @param size       Size of the area being tested.
- * @param avoid_area Do not touch this area.
+ * @param as    Address space.
+ * @param addr  Starting virtual address of the area being tested.
+ * @param count Number of pages in the area being tested.
+ * @param avoid Do not touch this area.
  *
  * @return True if there is no conflict, false otherwise.
  *
  */
-NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
-    as_area_t *avoid_area)
-{
+NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr,
+    size_t count, as_area_t *avoid)
+{
+	ASSERT((addr % PAGE_SIZE) == 0);
 	ASSERT(mutex_locked(&as->lock));
 	
 	/*
 	 * We don't want any area to have conflicts with NULL page.
-	 *
-	 */
-	if (overlaps(va, size, (uintptr_t) NULL, PAGE_SIZE))
+	 */
+	if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
 		return false;
 	
@@ -321,11 +315,10 @@
 	 * record in the left neighbour, the leftmost record in the right
 	 * neighbour and all records in the leaf node itself.
-	 *
 	 */
 	btree_node_t *leaf;
 	as_area_t *area =
-	    (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
+	    (as_area_t *) btree_search(&as->as_area_btree, addr, &leaf);
 	if (area) {
-		if (area != avoid_area)
+		if (area != avoid)
 			return false;
 	}
@@ -337,12 +330,15 @@
 		area = (as_area_t *) node->value[node->keys - 1];
 		
-		mutex_lock(&area->lock);
-		
-		if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
+		if (area != avoid) {
+			mutex_lock(&area->lock);
+			
+			if (overlaps(addr, count << PAGE_WIDTH,
+			    area->base, area->pages << PAGE_WIDTH)) {
+				mutex_unlock(&area->lock);
+				return false;
+			}
+			
 			mutex_unlock(&area->lock);
-			return false;
-		}
-		
-		mutex_unlock(&area->lock);
+		}
 	}
 	
@@ -351,12 +347,15 @@
 		area = (as_area_t *) node->value[0];
 		
-		mutex_lock(&area->lock);
-		
-		if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
+		if (area != avoid) {
+			mutex_lock(&area->lock);
+			
+			if (overlaps(addr, count << PAGE_WIDTH,
+			    area->base, area->pages << PAGE_WIDTH)) {
+				mutex_unlock(&area->lock);
+				return false;
+			}
+			
 			mutex_unlock(&area->lock);
-			return false;
-		}
-		
-		mutex_unlock(&area->lock);
+		}
 	}
 	
@@ -366,10 +365,11 @@
 		area = (as_area_t *) leaf->value[i];
 		
-		if (area == avoid_area)
+		if (area == avoid)
 			continue;
 		
 		mutex_lock(&area->lock);
 		
-		if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
+		if (overlaps(addr, count << PAGE_WIDTH,
+		    area->base, area->pages << PAGE_WIDTH)) {
 			mutex_unlock(&area->lock);
 			return false;
@@ -382,8 +382,7 @@
 	 * So far, the area does not conflict with other areas.
 	 * Check if it doesn't conflict with kernel address space.
-	 *
 	 */
 	if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
-		return !overlaps(va, size,
+		return !overlaps(addr, count << PAGE_WIDTH,
 		    KERNEL_ADDRESS_SPACE_START,
 		    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
@@ -412,9 +411,11 @@
     mem_backend_data_t *backend_data)
 {
-	if (base % PAGE_SIZE)
+	if ((base % PAGE_SIZE) != 0)
 		return NULL;
 	
-	if (!size)
+	if (size == 0)
 		return NULL;
+	
+	size_t pages = SIZE2FRAMES(size);
 	
 	/* Writeable executable areas are not supported. */
@@ -424,5 +425,5 @@
 	mutex_lock(&as->lock);
 	
-	if (!check_area_conflicts(as, base, size, NULL)) {
+	if (!check_area_conflicts(as, base, pages, NULL)) {
 		mutex_unlock(&as->lock);
 		return NULL;
@@ -436,5 +437,6 @@
 	area->flags = flags;
 	area->attributes = attrs;
-	area->pages = SIZE2FRAMES(size);
+	area->pages = pages;
+	area->resident = 0;
 	area->base = base;
 	area->sh_info = NULL;
@@ -479,5 +481,4 @@
 	 * to find out whether this is a miss or va belongs to an address
 	 * space area found there.
-	 *
 	 */
 	
@@ -490,5 +491,6 @@
 		mutex_lock(&area->lock);
 		
-		if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
+		if ((area->base <= va) &&
+		    (va < area->base + (area->pages << PAGE_WIDTH)))
 			return area;
 		
@@ -499,5 +501,4 @@
 	 * Second, locate the left neighbour and test its last record.
 	 * Because of its position in the B+tree, it must have base < va.
-	 *
 	 */
 	btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
@@ -507,5 +508,5 @@
 		mutex_lock(&area->lock);
 		
-		if (va < area->base + area->pages * PAGE_SIZE)
+		if (va < area->base + (area->pages << PAGE_WIDTH))
 			return area;
 		
@@ -534,5 +535,4 @@
 	/*
 	 * Locate the area.
-	 *
 	 */
 	as_area_t *area = find_area_and_lock(as, address);
@@ -546,5 +546,4 @@
 		 * Remapping of address space areas associated
 		 * with memory mapped devices is not supported.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -557,5 +556,4 @@
 		 * Remapping of shared address space areas
 		 * is not supported.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -568,5 +566,4 @@
 		/*
 		 * Zero size address space areas are not allowed.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -576,10 +573,9 @@
 	
 	if (pages < area->pages) {
-		uintptr_t start_free = area->base + pages * PAGE_SIZE;
+		uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
 		
 		/*
 		 * Shrinking the area.
 		 * No need to check for overlaps.
-		 *
 		 */
 		
@@ -588,8 +584,7 @@
 		/*
 		 * Start TLB shootdown sequence.
-		 *
 		 */
 		ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
-		    area->base + pages * PAGE_SIZE, area->pages - pages);
+		    area->base + (pages << PAGE_WIDTH), area->pages - pages);
 		
 		/*
@@ -599,5 +594,4 @@
 		 * is also the right way to remove part of the used_space
 		 * B+tree leaf list.
-		 *
 		 */
 		bool cond = true;
@@ -615,13 +609,12 @@
 				size_t i = 0;
 				
-				if (overlaps(ptr, size * PAGE_SIZE, area->base,
-				    pages * PAGE_SIZE)) {
+				if (overlaps(ptr, size << PAGE_WIDTH, area->base,
+				    pages << PAGE_WIDTH)) {
 					
-					if (ptr + size * PAGE_SIZE <= start_free) {
+					if (ptr + (size << PAGE_WIDTH) <= start_free) {
 						/*
 						 * The whole interval fits
 						 * completely in the resized
 						 * address space area.
-						 *
 						 */
 						break;
@@ -632,5 +625,4 @@
 					 * to b and c overlaps with the resized
 					 * address space area.
-					 *
 					 */
 					
@@ -652,5 +644,5 @@
 				for (; i < size; i++) {
 					pte_t *pte = page_mapping_find(as, ptr +
-					    i * PAGE_SIZE);
+					    (i << PAGE_WIDTH));
 					
 					ASSERT(pte);
@@ -661,10 +653,10 @@
 					    (area->backend->frame_free)) {
 						area->backend->frame_free(area,
-						    ptr + i * PAGE_SIZE,
+						    ptr + (i << PAGE_WIDTH),
 						    PTE_GET_FRAME(pte));
 					}
 					
 					page_mapping_remove(as, ptr +
-					    i * PAGE_SIZE);
+					    (i << PAGE_WIDTH));
 				}
 			}
@@ -673,16 +665,14 @@
 		/*
 		 * Finish TLB shootdown sequence.
-		 *
-		 */
-		
-		tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
+		 */
+		
+		tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
 		    area->pages - pages);
 		
 		/*
 		 * Invalidate software translation caches (e.g. TSB on sparc64).
-		 *
 		 */
 		as_invalidate_translation_cache(as, area->base +
-		    pages * PAGE_SIZE, area->pages - pages);
+		    (pages << PAGE_WIDTH), area->pages - pages);
 		tlb_shootdown_finalize(ipl);
 		
@@ -692,8 +682,6 @@
 		 * Growing the area.
 		 * Check for overlaps with other address space areas.
-		 *
-		 */
-		if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
-		    area)) {
+		 */
+		if (!check_area_conflicts(as, address, pages, area)) {
 			mutex_unlock(&area->lock);
 			mutex_unlock(&as->lock);
@@ -794,5 +782,6 @@
 			
 			for (size = 0; size < (size_t) node->value[i]; size++) {
-				pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
+				pte_t *pte =
+				    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
 				
 				ASSERT(pte);
@@ -803,8 +792,8 @@
 				    (area->backend->frame_free)) {
 					area->backend->frame_free(area,
-					    ptr + size * PAGE_SIZE, PTE_GET_FRAME(pte));
+					    ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
 				}
 				
-				page_mapping_remove(as, ptr + size * PAGE_SIZE);
+				page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
 			}
 		}
@@ -813,5 +802,4 @@
 	/*
 	 * Finish TLB shootdown sequence.
-	 *
 	 */
 	
@@ -821,5 +809,4 @@
 	 * Invalidate potential software translation caches (e.g. TSB on
 	 * sparc64).
-	 *
 	 */
 	as_invalidate_translation_cache(as, area->base, area->pages);
@@ -839,5 +826,4 @@
 	/*
 	 * Remove the empty area from address space.
-	 *
 	 */
 	btree_remove(&as->as_area_btree, base, NULL);
@@ -881,5 +867,4 @@
 		/*
 		 * Could not find the source address space area.
-		 *
 		 */
 		mutex_unlock(&src_as->lock);
@@ -891,5 +876,4 @@
 		 * There is no backend or the backend does not
 		 * know how to share the area.
-		 *
 		 */
 		mutex_unlock(&src_area->lock);
@@ -898,5 +882,5 @@
 	}
 	
-	size_t src_size = src_area->pages * PAGE_SIZE;
+	size_t src_size = src_area->pages << PAGE_WIDTH;
 	unsigned int src_flags = src_area->flags;
 	mem_backend_t *src_backend = src_area->backend;
@@ -918,5 +902,4 @@
 	 * First, prepare the area for sharing.
 	 * Then it will be safe to unlock it.
-	 *
 	 */
 	share_info_t *sh_info = src_area->sh_info;
@@ -930,5 +913,4 @@
 		/*
 		 * Call the backend to setup sharing.
-		 *
 		 */
 		src_area->backend->share(src_area);
@@ -949,5 +931,4 @@
 	 * The flags of the source area are masked against dst_flags_mask
 	 * to support sharing in less privileged mode.
-	 *
 	 */
 	as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask, src_size,
@@ -966,5 +947,4 @@
 	 * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
 	 * attribute and set the sh_info.
-	 *
 	 */
 	mutex_lock(&dst_as->lock);
@@ -989,4 +969,6 @@
 NO_TRACE bool as_area_check_access(as_area_t *area, pf_access_t access)
 {
+	ASSERT(mutex_locked(&area->lock));
+	
 	int flagmap[] = {
 		[PF_ACCESS_READ] = AS_AREA_READ,
@@ -994,6 +976,4 @@
 		[PF_ACCESS_EXEC] = AS_AREA_EXEC
 	};
-
-	ASSERT(mutex_locked(&area->lock));
 	
 	if (!(area->flags & flagmap[access]))
@@ -1066,5 +1046,4 @@
 	/*
 	 * Compute total number of used pages in the used_space B+tree
-	 *
 	 */
 	size_t used_pages = 0;
@@ -1088,5 +1067,4 @@
 	/*
 	 * Start TLB shootdown sequence.
-	 *
 	 */
 	ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
@@ -1096,5 +1074,4 @@
 	 * Remove used pages from page tables and remember their frame
 	 * numbers.
-	 *
 	 */
 	size_t frame_idx = 0;
@@ -1111,5 +1088,6 @@
 			
 			for (size = 0; size < (size_t) node->value[i]; size++) {
-				pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
+				pte_t *pte =
+				    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
 				
 				ASSERT(pte);
@@ -1120,5 +1098,5 @@
 				
 				/* Remove old mapping */
-				page_mapping_remove(as, ptr + size * PAGE_SIZE);
+				page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
 			}
 		}
@@ -1127,5 +1105,4 @@
 	/*
 	 * Finish TLB shootdown sequence.
-	 *
 	 */
 	
@@ -1135,5 +1112,4 @@
 	 * Invalidate potential software translation caches (e.g. TSB on
 	 * sparc64).
-	 *
 	 */
 	as_invalidate_translation_cache(as, area->base, area->pages);
@@ -1168,5 +1144,5 @@
 				
 				/* Insert the new mapping */
-				page_mapping_insert(as, ptr + size * PAGE_SIZE,
+				page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
 				    old_frame[frame_idx++], page_flags);
 				
@@ -1217,5 +1193,4 @@
 		 * No area contained mapping for 'page'.
 		 * Signal page fault to low-level handler.
-		 *
 		 */
 		mutex_unlock(&AS->lock);
@@ -1237,5 +1212,4 @@
 		 * The address space area is not backed by any backend
 		 * or the backend cannot handle page faults.
-		 *
 		 */
 		mutex_unlock(&area->lock);
@@ -1249,5 +1223,4 @@
 	 * To avoid race condition between two page faults on the same address,
 	 * we need to make sure the mapping has not been already inserted.
-	 *
 	 */
 	pte_t *pte;
@@ -1267,5 +1240,4 @@
 	/*
 	 * Resort to the backend page fault handler.
-	 *
 	 */
 	if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
@@ -1322,5 +1294,4 @@
 		 * preemption is disabled. We should not be
 		 * holding any other lock.
-		 *
 		 */
 		(void) interrupts_enable();
@@ -1342,5 +1313,4 @@
 			 * list of inactive address spaces with assigned
 			 * ASID.
-			 *
 			 */
 			ASSERT(old_as->asid != ASID_INVALID);
@@ -1353,5 +1323,4 @@
 		 * Perform architecture-specific tasks when the address space
 		 * is being removed from the CPU.
-		 *
 		 */
 		as_deinstall_arch(old_as);
@@ -1360,5 +1329,4 @@
 	/*
 	 * Second, prepare the new address space.
-	 *
 	 */
 	if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
@@ -1376,5 +1344,4 @@
 	 * Perform architecture-specific steps.
 	 * (e.g. write ASID to hardware register etc.)
-	 *
 	 */
 	as_install_arch(new_as);
@@ -1395,5 +1362,5 @@
 {
 	ASSERT(mutex_locked(&area->lock));
-
+	
 	return area_flags_to_page_flags(area->flags);
 }
@@ -1499,5 +1466,5 @@
 	
 	if (src_area) {
-		size = src_area->pages * PAGE_SIZE;
+		size = src_area->pages << PAGE_WIDTH;
 		mutex_unlock(&src_area->lock);
 	} else
@@ -1516,8 +1483,8 @@
  * @param count Number of page to be marked.
  *
- * @return Zero on failure and non-zero on success.
- *
- */
-int used_space_insert(as_area_t *area, uintptr_t page, size_t count)
+ * @return False on failure or true on success.
+ *
+ */
+bool used_space_insert(as_area_t *area, uintptr_t page, size_t count)
 {
 	ASSERT(mutex_locked(&area->lock));
@@ -1530,12 +1497,11 @@
 		/*
 		 * We hit the beginning of some used space.
-		 *
-		 */
-		return 0;
+		 */
+		return false;
 	}
 	
 	if (!leaf->keys) {
 		btree_insert(&area->used_space, page, (void *) count, leaf);
-		return 1;
+		goto success;
 	}
 	
@@ -1551,54 +1517,49 @@
 		 * somewhere between the rightmost interval of
 		 * the left neigbour and the first interval of the leaf.
-		 *
 		 */
 		
 		if (page >= right_pg) {
 			/* Do nothing. */
-		} else if (overlaps(page, count * PAGE_SIZE, left_pg,
-		    left_cnt * PAGE_SIZE)) {
+		} else if (overlaps(page, count << PAGE_WIDTH, left_pg,
+		    left_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the left interval. */
-			return 0;
-		} else if (overlaps(page, count * PAGE_SIZE, right_pg,
-		    right_cnt * PAGE_SIZE)) {
+			return false;
+		} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
+		    right_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the right interval. */
-			return 0;
-		} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
-		    (page + count * PAGE_SIZE == right_pg)) {
+			return false;
+		} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
+		    (page + (count << PAGE_WIDTH) == right_pg)) {
 			/*
 			 * The interval can be added by merging the two already
 			 * present intervals.
-			 *
 			 */
 			node->value[node->keys - 1] += count + right_cnt;
 			btree_remove(&area->used_space, right_pg, leaf);
-			return 1;
-		} else if (page == left_pg + left_cnt * PAGE_SIZE) {
+			goto success;
+		} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
 			/*
 			 * The interval can be added by simply growing the left
 			 * interval.
-			 *
 			 */
 			node->value[node->keys - 1] += count;
-			return 1;
-		} else if (page + count * PAGE_SIZE == right_pg) {
+			goto success;
+		} else if (page + (count << PAGE_WIDTH) == right_pg) {
 			/*
 			 * The interval can be addded by simply moving base of
 			 * the right interval down and increasing its size
 			 * accordingly.
-			 *
 			 */
 			leaf->value[0] += count;
 			leaf->key[0] = page;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval is between both neigbouring intervals,
 			 * but cannot be merged with any of them.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	} else if (page < leaf->key[0]) {
@@ -1609,30 +1570,27 @@
 		 * Investigate the border case in which the left neighbour does
 		 * not exist but the interval fits from the left.
-		 *
-		 */
-		
-		if (overlaps(page, count * PAGE_SIZE, right_pg,
-		    right_cnt * PAGE_SIZE)) {
+		 */
+		
+		if (overlaps(page, count << PAGE_WIDTH, right_pg,
+		    right_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the right interval. */
-			return 0;
-		} else if (page + count * PAGE_SIZE == right_pg) {
+			return false;
+		} else if (page + (count << PAGE_WIDTH) == right_pg) {
 			/*
 			 * The interval can be added by moving the base of the
 			 * right interval down and increasing its size
 			 * accordingly.
-			 *
 			 */
 			leaf->key[0] = page;
 			leaf->value[0] += count;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval doesn't adjoin with the right interval.
 			 * It must be added individually.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	}
@@ -1649,54 +1607,49 @@
 		 * somewhere between the leftmost interval of
 		 * the right neigbour and the last interval of the leaf.
-		 *
 		 */
 		
 		if (page < left_pg) {
 			/* Do nothing. */
-		} else if (overlaps(page, count * PAGE_SIZE, left_pg,
-		    left_cnt * PAGE_SIZE)) {
+		} else if (overlaps(page, count << PAGE_WIDTH, left_pg,
+		    left_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the left interval. */
-			return 0;
-		} else if (overlaps(page, count * PAGE_SIZE, right_pg,
-		    right_cnt * PAGE_SIZE)) {
+			return false;
+		} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
+		    right_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the right interval. */
-			return 0;
-		} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
-		    (page + count * PAGE_SIZE == right_pg)) {
+			return false;
+		} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
+		    (page + (count << PAGE_WIDTH) == right_pg)) {
 			/*
 			 * The interval can be added by merging the two already
 			 * present intervals.
-			 *
 			 */
 			leaf->value[leaf->keys - 1] += count + right_cnt;
 			btree_remove(&area->used_space, right_pg, node);
-			return 1;
-		} else if (page == left_pg + left_cnt * PAGE_SIZE) {
+			goto success;
+		} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
 			/*
 			 * The interval can be added by simply growing the left
 			 * interval.
-			 *
 			 */
-			leaf->value[leaf->keys - 1] +=  count;
-			return 1;
-		} else if (page + count * PAGE_SIZE == right_pg) {
+			leaf->value[leaf->keys - 1] += count;
+			goto success;
+		} else if (page + (count << PAGE_WIDTH) == right_pg) {
 			/*
 			 * The interval can be addded by simply moving base of
 			 * the right interval down and increasing its size
 			 * accordingly.
-			 *
 			 */
 			node->value[0] += count;
 			node->key[0] = page;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval is between both neigbouring intervals,
 			 * but cannot be merged with any of them.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	} else if (page >= leaf->key[leaf->keys - 1]) {
@@ -1707,28 +1660,25 @@
 		 * Investigate the border case in which the right neighbour
 		 * does not exist but the interval fits from the right.
-		 *
-		 */
-		
-		if (overlaps(page, count * PAGE_SIZE, left_pg,
-		    left_cnt * PAGE_SIZE)) {
+		 */
+		
+		if (overlaps(page, count << PAGE_WIDTH, left_pg,
+		    left_cnt << PAGE_WIDTH)) {
 			/* The interval intersects with the left interval. */
-			return 0;
-		} else if (left_pg + left_cnt * PAGE_SIZE == page) {
+			return false;
+		} else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
 			/*
 			 * The interval can be added by growing the left
 			 * interval.
-			 *
 			 */
 			leaf->value[leaf->keys - 1] += count;
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * The interval doesn't adjoin with the left interval.
 			 * It must be added individually.
-			 *
 			 */
 			btree_insert(&area->used_space, page, (void *) count,
 			    leaf);
-			return 1;
+			goto success;
 		}
 	}
@@ -1738,5 +1688,4 @@
 	 * only between two other intervals of the leaf. The two border cases
 	 * were already resolved.
-	 *
 	 */
 	btree_key_t i;
@@ -1750,51 +1699,45 @@
 			/*
 			 * The interval fits between left_pg and right_pg.
-			 *
 			 */
 			
-			if (overlaps(page, count * PAGE_SIZE, left_pg,
-			    left_cnt * PAGE_SIZE)) {
+			if (overlaps(page, count << PAGE_WIDTH, left_pg,
+			    left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval intersects with the left
 				 * interval.
-				 *
 				 */
-				return 0;
-			} else if (overlaps(page, count * PAGE_SIZE, right_pg,
-			    right_cnt * PAGE_SIZE)) {
+				return false;
+			} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
+			    right_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval intersects with the right
 				 * interval.
-				 *
 				 */
-				return 0;
-			} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
-			    (page + count * PAGE_SIZE == right_pg)) {
+				return false;
+			} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
+			    (page + (count << PAGE_WIDTH) == right_pg)) {
 				/*
 				 * The interval can be added by merging the two
 				 * already present intervals.
-				 *
 				 */
 				leaf->value[i - 1] += count + right_cnt;
 				btree_remove(&area->used_space, right_pg, leaf);
-				return 1;
-			} else if (page == left_pg + left_cnt * PAGE_SIZE) {
+				goto success;
+			} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval can be added by simply growing
 				 * the left interval.
-				 *
 				 */
 				leaf->value[i - 1] += count;
-				return 1;
-			} else if (page + count * PAGE_SIZE == right_pg) {
+				goto success;
+			} else if (page + (count << PAGE_WIDTH) == right_pg) {
 				/*
 				 * The interval can be addded by simply moving
 				 * base of the right interval down and
 				 * increasing its size accordingly.
-				 *
 				 */
 				leaf->value[i] += count;
 				leaf->key[i] = page;
-				return 1;
+				goto success;
 			} else {
 				/*
@@ -1802,9 +1745,8 @@
 				 * intervals, but cannot be merged with any of
 				 * them.
-				 *
 				 */
 				btree_insert(&area->used_space, page,
 				    (void *) count, leaf);
-				return 1;
+				goto success;
 			}
 		}
@@ -1813,4 +1755,8 @@
 	panic("Inconsistency detected while adding %zu pages of used "
 	    "space at %p.", count, (void *) page);
+	
+success:
+	area->resident += count;
+	return true;
 }
 
@@ -1823,8 +1769,8 @@
  * @param count Number of page to be marked.
  *
- * @return Zero on failure and non-zero on success.
- *
- */
-int used_space_remove(as_area_t *area, uintptr_t page, size_t count)
+ * @return False on failure or true on success.
+ *
+ */
+bool used_space_remove(as_area_t *area, uintptr_t page, size_t count)
 {
 	ASSERT(mutex_locked(&area->lock));
@@ -1837,25 +1783,24 @@
 		/*
 		 * We are lucky, page is the beginning of some interval.
-		 *
 		 */
 		if (count > pages) {
-			return 0;
+			return false;
 		} else if (count == pages) {
 			btree_remove(&area->used_space, page, leaf);
-			return 1;
+			goto success;
 		} else {
 			/*
 			 * Find the respective interval.
 			 * Decrease its size and relocate its start address.
-			 *
 			 */
 			btree_key_t i;
 			for (i = 0; i < leaf->keys; i++) {
 				if (leaf->key[i] == page) {
-					leaf->key[i] += count * PAGE_SIZE;
+					leaf->key[i] += count << PAGE_WIDTH;
 					leaf->value[i] -= count;
-					return 1;
+					goto success;
 				}
 			}
+			
 			goto error;
 		}
@@ -1867,8 +1812,8 @@
 		size_t left_cnt = (size_t) node->value[node->keys - 1];
 		
-		if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
-		    count * PAGE_SIZE)) {
-			if (page + count * PAGE_SIZE ==
-			    left_pg + left_cnt * PAGE_SIZE) {
+		if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
+		    count << PAGE_WIDTH)) {
+			if (page + (count << PAGE_WIDTH) ==
+			    left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1876,10 +1821,9 @@
 				 * removed by updating the size of the bigger
 				 * interval.
-				 *
 				 */
 				node->value[node->keys - 1] -= count;
-				return 1;
-			} else if (page + count * PAGE_SIZE <
-			    left_pg + left_cnt*PAGE_SIZE) {
+				goto success;
+			} else if (page + (count << PAGE_WIDTH) <
+			    left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1888,17 +1832,17 @@
 				 * the original interval and also inserting a
 				 * new interval.
-				 *
 				 */
-				size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
-				    (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
+				size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
+				    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
 				node->value[node->keys - 1] -= count + new_cnt;
 				btree_insert(&area->used_space, page +
-				    count * PAGE_SIZE, (void *) new_cnt, leaf);
-				return 1;
+				    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
+				goto success;
 			}
 		}
-		return 0;
+		
+		return false;
 	} else if (page < leaf->key[0])
-		return 0;
+		return false;
 	
 	if (page > leaf->key[leaf->keys - 1]) {
@@ -1906,18 +1850,17 @@
 		size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
 		
-		if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
-		    count * PAGE_SIZE)) {
-			if (page + count * PAGE_SIZE ==
-			    left_pg + left_cnt * PAGE_SIZE) {
+		if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
+		    count << PAGE_WIDTH)) {
+			if (page + (count << PAGE_WIDTH) ==
+			    left_pg + (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
 				 * interval of the leaf and can be removed by
 				 * updating the size of the bigger interval.
-				 *
 				 */
 				leaf->value[leaf->keys - 1] -= count;
-				return 1;
-			} else if (page + count * PAGE_SIZE < left_pg +
-			    left_cnt * PAGE_SIZE) {
+				goto success;
+			} else if (page + (count << PAGE_WIDTH) < left_pg +
+			    (left_cnt << PAGE_WIDTH)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1926,20 +1869,20 @@
 				 * original interval and also inserting a new
 				 * interval.
-				 *
 				 */
-				size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
-				    (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
+				size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
+				    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
 				leaf->value[leaf->keys - 1] -= count + new_cnt;
 				btree_insert(&area->used_space, page +
-				    count * PAGE_SIZE, (void *) new_cnt, leaf);
-				return 1;
+				    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
+				goto success;
 			}
 		}
-		return 0;
+		
+		return false;
 	}
 	
 	/*
 	 * The border cases have been already resolved.
-	 * Now the interval can be only between intervals of the leaf. 
+	 * Now the interval can be only between intervals of the leaf.
 	 */
 	btree_key_t i;
@@ -1953,8 +1896,8 @@
 			 * to (i - 1) and i.
 			 */
-			if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
-			    count * PAGE_SIZE)) {
-				if (page + count * PAGE_SIZE ==
-				    left_pg + left_cnt*PAGE_SIZE) {
+			if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
+			    count << PAGE_WIDTH)) {
+				if (page + (count << PAGE_WIDTH) ==
+				    left_pg + (left_cnt << PAGE_WIDTH)) {
 					/*
 					 * The interval is contained in the
@@ -1962,10 +1905,9 @@
 					 * be removed by updating the size of
 					 * the bigger interval.
-					 *
 					 */
 					leaf->value[i - 1] -= count;
-					return 1;
-				} else if (page + count * PAGE_SIZE <
-				    left_pg + left_cnt * PAGE_SIZE) {
+					goto success;
+				} else if (page + (count << PAGE_WIDTH) <
+				    left_pg + (left_cnt << PAGE_WIDTH)) {
 					/*
 					 * The interval is contained in the
@@ -1976,15 +1918,16 @@
 					 */
 					size_t new_cnt = ((left_pg +
-					    left_cnt * PAGE_SIZE) -
-					    (page + count * PAGE_SIZE)) >>
+					    (left_cnt << PAGE_WIDTH)) -
+					    (page + (count << PAGE_WIDTH))) >>
 					    PAGE_WIDTH;
 					leaf->value[i - 1] -= count + new_cnt;
 					btree_insert(&area->used_space, page +
-					    count * PAGE_SIZE, (void *) new_cnt,
+					    (count << PAGE_WIDTH), (void *) new_cnt,
 					    leaf);
-					return 1;
+					goto success;
 				}
 			}
-			return 0;
+			
+			return false;
 		}
 	}
@@ -1993,4 +1936,8 @@
 	panic("Inconsistency detected while removing %zu pages of used "
 	    "space from %p.", count, (void *) page);
+	
+success:
+	area->resident -= count;
+	return true;
 }
 
@@ -2027,4 +1974,70 @@
 }
 
+/** Return pointer to unmapped address space area
+ *
+ * @param base Lowest address bound.
+ * @param size Requested size of the allocation.
+ *
+ * @return Pointer to the beginning of unmapped address space area.
+ *
+ */
+sysarg_t sys_as_get_unmapped_area(uintptr_t base, size_t size)
+{
+	if (size == 0)
+		return 0;
+	
+	/*
+	 * Make sure we allocate from page-aligned
+	 * address. Check for possible overflow in
+	 * each step.
+	 */
+	
+	size_t pages = SIZE2FRAMES(size);
+	uintptr_t ret = 0;
+	
+	/*
+	 * Find the lowest unmapped address aligned on the sz
+	 * boundary, not smaller than base and of the required size.
+	 */
+	
+	mutex_lock(&AS->lock);
+	
+	/* First check the base address itself */
+	uintptr_t addr = ALIGN_UP(base, PAGE_SIZE);
+	if ((addr >= base) &&
+	    (check_area_conflicts(AS, addr, pages, NULL)))
+		ret = addr;
+	
+	/* Eventually check the addresses behind each area */
+	link_t *cur;
+	for (cur = AS->as_area_btree.leaf_head.next;
+	    (ret == 0) && (cur != &AS->as_area_btree.leaf_head);
+	    cur = cur->next) {
+		btree_node_t *node =
+		    list_get_instance(cur, btree_node_t, leaf_link);
+		
+		btree_key_t i;
+		for (i = 0; (ret == 0) && (i < node->keys); i++) {
+			as_area_t *area = (as_area_t *) node->value[i];
+			
+			mutex_lock(&area->lock);
+			
+			uintptr_t addr =
+			    ALIGN_UP(area->base + (area->pages << PAGE_WIDTH),
+			    PAGE_SIZE);
+			
+			if ((addr >= base) && (addr >= area->base) &&
+			    (check_area_conflicts(AS, addr, pages, area)))
+				ret = addr;
+			
+			mutex_unlock(&area->lock);
+		}
+	}
+	
+	mutex_unlock(&AS->lock);
+	
+	return (sysarg_t) ret;
+}
+
 /** Get list of adress space areas.
  *
@@ -2093,5 +2106,5 @@
 	mutex_lock(&as->lock);
 	
-	/* print out info about address space areas */
+	/* Print out info about address space areas */
 	link_t *cur;
 	for (cur = as->as_area_btree.leaf_head.next;
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ kernel/generic/src/proc/program.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -171,4 +171,5 @@
 	void *loader = program_loader;
 	if (!loader) {
+		as_destroy(as);
 		printf("Cannot spawn loader as none was registered\n");
 		return ENOENT;
@@ -179,4 +180,5 @@
 	if (rc != EE_OK) {
 		as_destroy(as);
+		printf("Cannot spawn loader (%s)\n", elf_error(rc));
 		return ENOENT;
 	}
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ kernel/generic/src/syscall/syscall.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -143,4 +143,5 @@
 	(syshandler_t) sys_as_area_change_flags,
 	(syshandler_t) sys_as_area_destroy,
+	(syshandler_t) sys_as_get_unmapped_area,
 	
 	/* IPC related syscalls. */
Index: kernel/generic/src/sysinfo/stats.c
===================================================================
--- kernel/generic/src/sysinfo/stats.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ kernel/generic/src/sysinfo/stats.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -160,69 +160,17 @@
 static size_t get_task_virtmem(as_t *as)
 {
-	size_t result = 0;
-
 	/*
-	 * We are holding some spinlocks here and therefore are not allowed to
-	 * block. Only attempt to lock the address space and address space area
-	 * mutexes conditionally. If it is not possible to lock either object,
-	 * allow the statistics to be inexact by skipping the respective object.
-	 *
-	 * Note that it may be infinitely better to let the address space
-	 * management code compute these statistics as it proceeds instead of
-	 * having them calculated over and over again here.
+	 * We are holding spinlocks here and therefore are not allowed to
+	 * block. Only attempt to lock the address space and address space
+	 * area mutexes conditionally. If it is not possible to lock either
+	 * object, return inexact statistics by skipping the respective object.
 	 */
-
+	
 	if (SYNCH_FAILED(mutex_trylock(&as->lock)))
-		return result * PAGE_SIZE;
+		return 0;
+	
+	size_t pages = 0;
 	
 	/* Walk the B+ tree and count pages */
-	link_t *cur;
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
-		btree_node_t *node =
-		    list_get_instance(cur, btree_node_t, leaf_link);
-		
-		unsigned int i;
-		for (i = 0; i < node->keys; i++) {
-			as_area_t *area = node->value[i];
-			
-			if (SYNCH_FAILED(mutex_trylock(&area->lock)))
-				continue;
-			result += area->pages;
-			mutex_unlock(&area->lock);
-		}
-	}
-	
-	mutex_unlock(&as->lock);
-	
-	return result * PAGE_SIZE;
-}
-
-/** Get the resident (used) size of a virtual address space
- *
- * @param as Address space.
- *
- * @return Size of the resident (used) virtual address space (bytes).
- *
- */
-static size_t get_task_resmem(as_t *as)
-{
-	size_t result = 0;
-	
-	/*
-	 * We are holding some spinlocks here and therefore are not allowed to
-	 * block. Only attempt to lock the address space and address space area
-	 * mutexes conditionally. If it is not possible to lock either object,
-	 * allow the statistics to be inexact by skipping the respective object.
-	 *
-	 * Note that it may be infinitely better to let the address space
-	 * management code compute these statistics as it proceeds instead of
-	 * having them calculated over and over again here.
-	 */
-	
-	if (SYNCH_FAILED(mutex_trylock(&as->lock)))
-		return result * PAGE_SIZE;
-	
-	/* Walk the B+ tree of AS areas */
 	link_t *cur;
 	for (cur = as->as_area_btree.leaf_head.next;
@@ -238,16 +186,5 @@
 				continue;
 			
-			/* Walk the B+ tree of resident pages */
-			link_t *rcur;
-			for (rcur = area->used_space.leaf_head.next;
-			    rcur != &area->used_space.leaf_head; rcur = rcur->next) {
-				btree_node_t *rnode =
-				    list_get_instance(rcur, btree_node_t, leaf_link);
-				
-				unsigned int j;
-				for (j = 0; j < rnode->keys; j++)
-					result += (size_t) rnode->value[i];
-			}
-			
+			pages += area->pages;
 			mutex_unlock(&area->lock);
 		}
@@ -256,5 +193,50 @@
 	mutex_unlock(&as->lock);
 	
-	return result * PAGE_SIZE;
+	return (pages << PAGE_WIDTH);
+}
+
+/** Get the resident (used) size of a virtual address space
+ *
+ * @param as Address space.
+ *
+ * @return Size of the resident (used) virtual address space (bytes).
+ *
+ */
+static size_t get_task_resmem(as_t *as)
+{
+	/*
+	 * We are holding spinlocks here and therefore are not allowed to
+	 * block. Only attempt to lock the address space and address space
+	 * area mutexes conditionally. If it is not possible to lock either
+	 * object, return inexact statistics by skipping the respective object.
+	 */
+	
+	if (SYNCH_FAILED(mutex_trylock(&as->lock)))
+		return 0;
+	
+	size_t pages = 0;
+	
+	/* Walk the B+ tree and count pages */
+	link_t *cur;
+	for (cur = as->as_area_btree.leaf_head.next;
+	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+		btree_node_t *node =
+		    list_get_instance(cur, btree_node_t, leaf_link);
+		
+		unsigned int i;
+		for (i = 0; i < node->keys; i++) {
+			as_area_t *area = node->value[i];
+			
+			if (SYNCH_FAILED(mutex_trylock(&area->lock)))
+				continue;
+			
+			pages += area->resident;
+			mutex_unlock(&area->lock);
+		}
+	}
+	
+	mutex_unlock(&as->lock);
+	
+	return (pages << PAGE_WIDTH);
 }
 
Index: uspace/app/taskdump/taskdump.c
===================================================================
--- uspace/app/taskdump/taskdump.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/app/taskdump/taskdump.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -406,4 +406,17 @@
 	}
 
+	rc = asprintf(&file_name, "/drv/%s/%s", app_name, app_name);
+	if (rc < 0) {
+		printf("Memory allocation failure.\n");
+		exit(1);
+	}
+
+	rc = symtab_load(file_name, &app_symtab);
+	if (rc == EOK) {
+		printf("Loaded symbol table from %s\n", file_name);
+		free(file_name);
+		return;
+	}
+
 	free(file_name);
 	printf("Failed autoloading symbol table.\n");
Index: uspace/lib/block/libblock.c
===================================================================
--- uspace/lib/block/libblock.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/block/libblock.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -294,6 +294,8 @@
 
 	/* Allow 1:1 or small-to-large block size translation */
-	if (cache->lblock_size % devcon->pblock_size != 0)
+	if (cache->lblock_size % devcon->pblock_size != 0) {
+		free(cache);
 		return ENOTSUP;
+	}
 
 	cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
@@ -436,4 +438,5 @@
 			if (!b->data) {
 				free(b);
+				b = NULL;
 				goto recycle;
 			}
@@ -563,4 +566,5 @@
 	assert(devcon);
 	assert(devcon->cache);
+	assert(block->refcnt >= 1);
 
 	cache = devcon->cache;
@@ -622,6 +626,6 @@
 			unsigned long key = block->lba;
 			hash_table_remove(&cache->block_hash, &key, 1);
+			free(block->data);
 			free(block);
-			free(block->data);
 			cache->blocks_cached--;
 			fibril_mutex_unlock(&cache->lock);
Index: uspace/lib/c/arch/abs32le/_link.ld.in
===================================================================
--- uspace/lib/c/arch/abs32le/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/arch/abs32le/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -44,8 +44,4 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	
-	_heap = .;
-	
 	/DISCARD/ : {
 		*(*);
Index: uspace/lib/c/arch/amd64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/amd64/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/arch/amd64/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -42,7 +42,4 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	_heap = .;
-	
 #ifdef CONFIG_LINE_DEBUG
 	.comment 0 : { *(.comment); } :debug
@@ -61,4 +58,3 @@
 		*(*);
 	}
-
 }
Index: uspace/lib/c/arch/arm32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/arm32/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/arch/arm32/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -9,15 +9,16 @@
 SECTIONS {
 	. = 0x1000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
-        *(.rodata*);
+		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x1000;
-
+	
 	.data : {
 		*(.opd);
@@ -25,4 +26,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -33,18 +35,16 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
 		*(.scommon);
-        *(COMMON);
-        *(.bss);
+		*(COMMON);
+		*(.bss);
 	} :data
-	
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/lib/c/arch/ia32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia32/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/arch/ia32/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -43,7 +43,4 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	_heap = .;
-	
 #ifdef CONFIG_LINE_DEBUG
 	.comment 0 : { *(.comment); } :debug
Index: uspace/lib/c/arch/ia64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia64/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/arch/ia64/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -9,19 +9,21 @@
 SECTIONS {
 	. = 0x4000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		_gp = .;
 		*(.got*);
-	} :data	
+	} :data
+	
 	.data : {
 		*(.opd);
@@ -29,4 +31,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -37,5 +40,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
@@ -44,10 +49,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
- 
+	
 	/DISCARD/ : {
 		*(*);
-        }
+	}
 }
Index: uspace/lib/c/arch/mips32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/mips32/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/arch/mips32/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -13,43 +13,46 @@
 		*(.init);
 	} :text
+	
 	.text : {
-	        *(.text);
+		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.data : {
 		*(.data);
 		*(.data.rel*);
 	} :data
-
+	
 	.got : {
 		_gp = .;
 		*(.got);
 	} :data
-
+	
 	.tdata : {
 		_tdata_start = .;
 		*(.tdata);
 		_tdata_end = .;
+	} :data
+	
+	.tbss : {
 		_tbss_start = .;
 		*(.tbss);
 		_tbss_end = .;
 	} :data
-	_tls_alignment = ALIGNOF(.tdata);
-
+	
+	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.sbss : {
 		*(.scommon);
 		*(.sbss);
-	}	
+	}
+	
 	.bss : {
 		*(.bss);
 		*(COMMON);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
-
+	
 	/DISCARD/ : {
 		*(*);
Index: uspace/lib/c/arch/mips32/src/entry.s
===================================================================
--- uspace/lib/c/arch/mips32/src/entry.s	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/arch/mips32/src/entry.s	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -29,6 +29,7 @@
 .text
 .section .init, "ax"
+
 .global __entry
-.global __entry_driver
+
 .set noreorder
 .option pic2
@@ -57,6 +58,2 @@
 	nop
 .end
-
-# Alignment of output section data to 0x4000
-.section .data
-.align 14
Index: uspace/lib/c/arch/ppc32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ppc32/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/arch/ppc32/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -9,19 +9,21 @@
 SECTIONS {
 	. = 0x1000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x1000;
-
+	
 	.data : {
 		*(.data);
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -32,5 +34,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
@@ -38,11 +42,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/lib/c/arch/sparc64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/sparc64/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/arch/sparc64/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -9,23 +9,26 @@
 SECTIONS {
 	. = 0x4000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		 _gp = .;
 		 *(.got*);
 	} :data
+	
 	.data : {
 		*(.data);
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -36,5 +39,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = ALIGNOF(.tdata);
+	
 	.bss : {
 		*(.sbss);
@@ -42,11 +47,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/lib/c/generic/as.c
===================================================================
--- uspace/lib/c/generic/as.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/generic/as.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -40,7 +40,5 @@
 #include <bitops.h>
 #include <malloc.h>
-
-/** Last position allocated by as_get_mappable_page */
-static uintptr_t last_allocated = 0;
+#include "private/libc.h"
 
 /** Create address space area.
@@ -103,27 +101,15 @@
 }
 
-/** Return pointer to some unmapped area, where fits new as_area
+/** Return pointer to unmapped address space area
  *
  * @param size Requested size of the allocation.
  *
- * @return pointer to the beginning
+ * @return Pointer to the beginning of unmapped address space area.
  *
  */
 void *as_get_mappable_page(size_t size)
 {
-	if (size == 0)
-		return NULL;
-	
-	size_t sz = 1 << (fnzb(size - 1) + 1);
-	if (last_allocated == 0)
-		last_allocated = get_max_heap_addr();
-	
-	/*
-	 * Make sure we allocate from naturally aligned address.
-	 */
-	uintptr_t res = ALIGN_UP(last_allocated, sz);
-	last_allocated = res + ALIGN_UP(size, PAGE_SIZE);
-	
-	return ((void *) res);
+	return (void *) __SYSCALL2(SYS_AS_GET_UNMAPPED_AREA,
+	    (sysarg_t) __entry, (sysarg_t) size);
 }
 
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/generic/async.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -294,15 +294,6 @@
 }
 
-/** Connection hash table removal callback function.
- *
- * This function is called whenever a connection is removed from the connection
- * hash table.
- *
- * @param item Connection hash table item being removed.
- *
- */
 static void conn_remove(link_t *item)
 {
-	free(hash_table_get_instance(item, connection_t, link));
 }
 
@@ -647,4 +638,5 @@
 		ipc_answer_0(FIBRIL_connection->close_callid, EOK);
 	
+	free(FIBRIL_connection);
 	return 0;
 }
Index: uspace/lib/c/generic/malloc.c
===================================================================
--- uspace/lib/c/generic/malloc.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/generic/malloc.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -47,33 +47,77 @@
 #include "private/malloc.h"
 
-/* Magic used in heap headers. */
-#define HEAP_BLOCK_HEAD_MAGIC  0xBEEF0101
-
-/* Magic used in heap footers. */
-#define HEAP_BLOCK_FOOT_MAGIC  0xBEEF0202
-
-/** Allocation alignment (this also covers the alignment of fields
-    in the heap header and footer) */
+/** Magic used in heap headers. */
+#define HEAP_BLOCK_HEAD_MAGIC  UINT32_C(0xBEEF0101)
+
+/** Magic used in heap footers. */
+#define HEAP_BLOCK_FOOT_MAGIC  UINT32_C(0xBEEF0202)
+
+/** Magic used in heap descriptor. */
+#define HEAP_AREA_MAGIC  UINT32_C(0xBEEFCAFE)
+
+/** Allocation alignment.
+ *
+ * This also covers the alignment of fields
+ * in the heap header and footer.
+ *
+ */
 #define BASE_ALIGN  16
 
-/**
- * Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures
- */
-#define MAX_HEAP_SIZE  (sizeof(uintptr_t) << 28)
-
-/**
- *
- */
-#define STRUCT_OVERHEAD  (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
-
-/**
- * Calculate real size of a heap block (with header and footer)
+/** Overhead of each heap block. */
+#define STRUCT_OVERHEAD \
+	(sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
+
+/** Calculate real size of a heap block.
+ *
+ * Add header and footer size.
+ *
  */
 #define GROSS_SIZE(size)  ((size) + STRUCT_OVERHEAD)
 
-/**
- * Calculate net size of a heap block (without header and footer)
+/** Calculate net size of a heap block.
+ *
+ * Subtract header and footer size.
+ *
  */
 #define NET_SIZE(size)  ((size) - STRUCT_OVERHEAD)
+
+/** Get first block in heap area.
+ *
+ */
+#define AREA_FIRST_BLOCK(area) \
+	(ALIGN_UP(((uintptr_t) (area)) + sizeof(heap_area_t), BASE_ALIGN))
+
+/** Get footer in heap block.
+ *
+ */
+#define BLOCK_FOOT(head) \
+	((heap_block_foot_t *) \
+	    (((uintptr_t) head) + head->size - sizeof(heap_block_foot_t)))
+
+/** Heap area.
+ *
+ * The memory managed by the heap allocator is divided into
+ * multiple discontinuous heaps. Each heap is represented
+ * by a separate address space area which has this structure
+ * at its very beginning.
+ *
+ */
+typedef struct heap_area {
+	/** Start of the heap area (including this structure)
+	 *
+	 * Aligned on page boundary.
+	 *
+	 */
+	void *start;
+	
+	/** End of the heap area (aligned on page boundary) */
+	void *end;
+	
+	/** Next heap area */
+	struct heap_area *next;
+	
+	/** A magic value */
+	uint32_t magic;
+} heap_area_t;
 
 /** Header of a heap block
@@ -87,4 +131,7 @@
 	bool free;
 	
+	/** Heap area this block belongs to */
+	heap_area_t *area;
+	
 	/* A magic value to detect overwrite of heap header */
 	uint32_t magic;
@@ -102,25 +149,19 @@
 } heap_block_foot_t;
 
-/** Linker heap symbol */
-extern char _heap;
+/** First heap area */
+static heap_area_t *first_heap_area = NULL;
+
+/** Last heap area */
+static heap_area_t *last_heap_area = NULL;
+
+/** Next heap block to examine (next fit algorithm) */
+static heap_block_head_t *next = NULL;
 
 /** Futex for thread-safe heap manipulation */
 static futex_t malloc_futex = FUTEX_INITIALIZER;
 
-/** Address of heap start */
-static void *heap_start = 0;
-
-/** Address of heap end */
-static void *heap_end = 0;
-
-/** Maximum heap size */
-static size_t max_heap_size = (size_t) -1;
-
-/** Current number of pages of heap area */
-static size_t heap_pages = 0;
-
 /** Initialize a heap block
  *
- * Fills in the structures related to a heap block.
+ * Fill in the structures related to a heap block.
  * Should be called only inside the critical section.
  *
@@ -128,16 +169,18 @@
  * @param size Size of the block including the header and the footer.
  * @param free Indication of a free block.
- *
- */
-static void block_init(void *addr, size_t size, bool free)
+ * @param area Heap area the block belongs to.
+ *
+ */
+static void block_init(void *addr, size_t size, bool free, heap_area_t *area)
 {
 	/* Calculate the position of the header and the footer */
 	heap_block_head_t *head = (heap_block_head_t *) addr;
-	heap_block_foot_t *foot =
-	    (heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t));
 	
 	head->size = size;
 	head->free = free;
+	head->area = area;
 	head->magic = HEAP_BLOCK_HEAD_MAGIC;
+	
+	heap_block_foot_t *foot = BLOCK_FOOT(head);
 	
 	foot->size = size;
@@ -160,6 +203,5 @@
 	assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
 	
-	heap_block_foot_t *foot =
-	    (heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t));
+	heap_block_foot_t *foot = BLOCK_FOOT(head);
 	
 	assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
@@ -167,49 +209,130 @@
 }
 
-/** Increase the heap area size
- *
- * Should be called only inside the critical section.
- *
- * @param size Number of bytes to grow the heap by.
- *
- */
-static bool grow_heap(size_t size)
+/** Check a heap area structure
+ *
+ * @param addr Address of the heap area.
+ *
+ */
+static void area_check(void *addr)
+{
+	heap_area_t *area = (heap_area_t *) addr;
+	
+	assert(area->magic == HEAP_AREA_MAGIC);
+	assert(area->start < area->end);
+	assert(((uintptr_t) area->start % PAGE_SIZE) == 0);
+	assert(((uintptr_t) area->end % PAGE_SIZE) == 0);
+}
+
+/** Create new heap area
+ *
+ * @param start Preffered starting address of the new area.
+ * @param size  Size of the area.
+ *
+ */
+static bool area_create(size_t size)
+{
+	void *start = as_get_mappable_page(size);
+	if (start == NULL)
+		return false;
+	
+	/* Align the heap area on page boundary */
+	void *astart = (void *) ALIGN_UP((uintptr_t) start, PAGE_SIZE);
+	size_t asize = ALIGN_UP(size, PAGE_SIZE);
+	
+	astart = as_area_create(astart, asize, AS_AREA_WRITE | AS_AREA_READ);
+	if (astart == (void *) -1)
+		return false;
+	
+	heap_area_t *area = (heap_area_t *) astart;
+	
+	area->start = astart;
+	area->end = (void *)
+	    ALIGN_DOWN((uintptr_t) astart + asize, BASE_ALIGN);
+	area->next = NULL;
+	area->magic = HEAP_AREA_MAGIC;
+	
+	void *block = (void *) AREA_FIRST_BLOCK(area);
+	size_t bsize = (size_t) (area->end - block);
+	
+	block_init(block, bsize, true, area);
+	
+	if (last_heap_area == NULL) {
+		first_heap_area = area;
+		last_heap_area = area;
+	} else {
+		last_heap_area->next = area;
+		last_heap_area = area;
+	}
+	
+	return true;
+}
+
+/** Try to enlarge a heap area
+ *
+ * @param area Heap area to grow.
+ * @param size Gross size of item to allocate (bytes).
+ *
+ */
+static bool area_grow(heap_area_t *area, size_t size)
 {
 	if (size == 0)
+		return true;
+	
+	area_check(area);
+	
+	size_t asize = ALIGN_UP((size_t) (area->end - area->start) + size,
+	    PAGE_SIZE);
+	
+	/* New heap area size */
+	void *end = (void *)
+	    ALIGN_DOWN((uintptr_t) area->start + asize, BASE_ALIGN);
+	
+	/* Check for overflow */
+	if (end < area->start)
 		return false;
-
-	if ((heap_start + size < heap_start) || (heap_end + size < heap_end))
+	
+	/* Resize the address space area */
+	int ret = as_area_resize(area->start, asize, 0);
+	if (ret != EOK)
 		return false;
 	
-	size_t heap_size = (size_t) (heap_end - heap_start);
-	
-	if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size))
-		return false;
-	
-	size_t pages = (size - 1) / PAGE_SIZE + 1;
-	
-	if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0)
-	    == EOK) {
-		void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) +
-		    (heap_pages + pages) * PAGE_SIZE, BASE_ALIGN);
-		block_init(heap_end, end - heap_end, true);
-		heap_pages += pages;
-		heap_end = end;
+	/* Add new free block */
+	block_init(area->end, (size_t) (end - area->end), true, area);
+	
+	/* Update heap area parameters */
+	area->end = end;
+	
+	return true;
+}
+
+/** Try to enlarge any of the heap areas
+ *
+ * @param size Gross size of item to allocate (bytes).
+ *
+ */
+static bool heap_grow(size_t size)
+{
+	if (size == 0)
 		return true;
-	}
-	
-	return false;
-}
-
-/** Decrease the heap area
- *
- * Should be called only inside the critical section.
- *
- * @param size Number of bytes to shrink the heap by.
- *
- */
-static void shrink_heap(void)
-{
-	// TODO
+	
+	/* First try to enlarge some existing area */
+	heap_area_t *area;
+	for (area = first_heap_area; area != NULL; area = area->next) {
+		if (area_grow(area, size))
+			return true;
+	}
+	
+	/* Eventually try to create a new area */
+	return area_create(AREA_FIRST_BLOCK(size));
+}
+
+/** Try to shrink heap space
+ *
+ * In all cases the next pointer is reset.
+ *
+ */
+static void heap_shrink(void)
+{
+	next = NULL;
 }
 
@@ -223,33 +346,6 @@
 void __malloc_init(void)
 {
-	if (!as_area_create((void *) &_heap, PAGE_SIZE,
-	    AS_AREA_WRITE | AS_AREA_READ))
+	if (!area_create(PAGE_SIZE))
 		abort();
-	
-	heap_pages = 1;
-	heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN);
-	heap_end =
-	    (void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN);
-	
-	/* Make the entire area one large block. */
-	block_init(heap_start, heap_end - heap_start, true);
-}
-
-/** Get maximum heap address
- *
- */
-uintptr_t get_max_heap_addr(void)
-{
-	futex_down(&malloc_futex);
-	
-	if (max_heap_size == (size_t) -1)
-		max_heap_size =
-		    max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE);
-	
-	uintptr_t max_heap_addr = (uintptr_t) heap_start + max_heap_size;
-	
-	futex_up(&malloc_futex);
-	
-	return max_heap_addr;
 }
 
@@ -273,6 +369,6 @@
 		/* Block big enough -> split. */
 		void *next = ((void *) cur) + size;
-		block_init(next, cur->size - size, true);
-		block_init(cur, size, false);
+		block_init(next, cur->size - size, true, cur->area);
+		block_init(cur, size, false, cur->area);
 	} else {
 		/* Block too small -> use as is. */
@@ -281,43 +377,53 @@
 }
 
-/** Allocate a memory block
+/** Allocate memory from heap area starting from given block
  *
  * Should be called only inside the critical section.
- *
- * @param size  The size of the block to allocate.
- * @param align Memory address alignment.
- *
- * @return the address of the block or NULL when not enough memory.
- *
- */
-static void *malloc_internal(const size_t size, const size_t align)
-{
-	if (align == 0)
-		return NULL;
-	
-	size_t falign = lcm(align, BASE_ALIGN);
-	size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
-	
-	bool grown = false;
-	void *result;
-	
-loop:
-	result = NULL;
-	heap_block_head_t *cur = (heap_block_head_t *) heap_start;
-	
-	while ((result == NULL) && ((void *) cur < heap_end)) {
+ * As a side effect this function also sets the current
+ * pointer on successful allocation.
+ *
+ * @param area        Heap area where to allocate from.
+ * @param first_block Starting heap block.
+ * @param final_block Heap block where to finish the search
+ *                    (may be NULL).
+ * @param real_size   Gross number of bytes to allocate.
+ * @param falign      Physical alignment of the block.
+ *
+ * @return Address of the allocated block or NULL on not enough memory.
+ *
+ */
+static void *malloc_area(heap_area_t *area, heap_block_head_t *first_block,
+    heap_block_head_t *final_block, size_t real_size, size_t falign)
+{
+	area_check((void *) area);
+	assert((void *) first_block >= (void *) AREA_FIRST_BLOCK(area));
+	assert((void *) first_block < area->end);
+	
+	heap_block_head_t *cur;
+	for (cur = first_block; (void *) cur < area->end;
+	    cur = (heap_block_head_t *) (((void *) cur) + cur->size)) {
 		block_check(cur);
+		
+		/* Finish searching on the final block */
+		if ((final_block != NULL) && (cur == final_block))
+			break;
 		
 		/* Try to find a block that is free and large enough. */
 		if ((cur->free) && (cur->size >= real_size)) {
-			/* We have found a suitable block.
-			   Check for alignment properties. */
-			void *addr = ((void *) cur) + sizeof(heap_block_head_t);
-			void *aligned = (void *) ALIGN_UP(addr, falign);
+			/*
+			 * We have found a suitable block.
+			 * Check for alignment properties.
+			 */
+			void *addr = (void *)
+			    ((uintptr_t) cur + sizeof(heap_block_head_t));
+			void *aligned = (void *)
+			    ALIGN_UP((uintptr_t) addr, falign);
 			
 			if (addr == aligned) {
 				/* Exact block start including alignment. */
 				split_mark(cur, real_size);
-				result = addr;
+				
+				next = cur;
+				return addr;
 			} else {
 				/* Block start has to be aligned */
@@ -325,15 +431,19 @@
 				
 				if (cur->size >= real_size + excess) {
-					/* The current block is large enough to fit
-					   data in including alignment */
-					if ((void *) cur > heap_start) {
-						/* There is a block before the current block.
-						   This previous block can be enlarged to compensate
-						   for the alignment excess */
-						heap_block_foot_t *prev_foot =
-						    ((void *) cur) - sizeof(heap_block_foot_t);
+					/*
+					 * The current block is large enough to fit
+					 * data in (including alignment).
+					 */
+					if ((void *) cur > (void *) AREA_FIRST_BLOCK(area)) {
+						/*
+						 * There is a block before the current block.
+						 * This previous block can be enlarged to
+						 * compensate for the alignment excess.
+						 */
+						heap_block_foot_t *prev_foot = (heap_block_foot_t *)
+						    ((void *) cur - sizeof(heap_block_foot_t));
 						
-						heap_block_head_t *prev_head =
-						    (heap_block_head_t *) (((void *) cur) - prev_foot->size);
+						heap_block_head_t *prev_head = (heap_block_head_t *)
+						    ((void *) cur - prev_foot->size);
 						
 						block_check(prev_head);
@@ -342,25 +452,38 @@
 						heap_block_head_t *next_head = ((void *) cur) + excess;
 						
-						if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) {
-							/* The previous block is not free and there is enough
-							   space to fill in a new free block between the previous
-							   and current block */
-							block_init(cur, excess, true);
+						if ((!prev_head->free) &&
+						    (excess >= STRUCT_OVERHEAD)) {
+							/*
+							 * The previous block is not free and there
+							 * is enough free space left to fill in
+							 * a new free block between the previous
+							 * and current block.
+							 */
+							block_init(cur, excess, true, area);
 						} else {
-							/* The previous block is free (thus there is no need to
-							   induce additional fragmentation to the heap) or the
-							   excess is small, thus just enlarge the previous block */
-							block_init(prev_head, prev_head->size + excess, prev_head->free);
+							/*
+							 * The previous block is free (thus there
+							 * is no need to induce additional
+							 * fragmentation to the heap) or the
+							 * excess is small. Therefore just enlarge
+							 * the previous block.
+							 */
+							block_init(prev_head, prev_head->size + excess,
+							    prev_head->free, area);
 						}
 						
-						block_init(next_head, reduced_size, true);
+						block_init(next_head, reduced_size, true, area);
 						split_mark(next_head, real_size);
-						result = aligned;
-						cur = next_head;
+						
+						next = next_head;
+						return aligned;
 					} else {
-						/* The current block is the first block on the heap.
-						   We have to make sure that the alignment excess
-						   is large enough to fit a new free block just
-						   before the current block */
+						/*
+						 * The current block is the first block
+						 * in the heap area. We have to make sure
+						 * that the alignment excess is large enough
+						 * to fit a new free block just before the
+						 * current block.
+						 */
 						while (excess < STRUCT_OVERHEAD) {
 							aligned += falign;
@@ -371,10 +494,14 @@
 						if (cur->size >= real_size + excess) {
 							size_t reduced_size = cur->size - excess;
-							cur = (heap_block_head_t *) (heap_start + excess);
+							cur = (heap_block_head_t *)
+							    (AREA_FIRST_BLOCK(area) + excess);
 							
-							block_init(heap_start, excess, true);
-							block_init(cur, reduced_size, true);
+							block_init((void *) AREA_FIRST_BLOCK(area), excess,
+							    true, area);
+							block_init(cur, reduced_size, true, area);
 							split_mark(cur, real_size);
-							result = aligned;
+							
+							next = cur;
+							return aligned;
 						}
 					}
@@ -382,17 +509,67 @@
 			}
 		}
-		
-		/* Advance to the next block. */
-		cur = (heap_block_head_t *) (((void *) cur) + cur->size);
-	}
-	
-	if ((result == NULL) && (!grown)) {
-		if (grow_heap(real_size)) {
-			grown = true;
+	}
+	
+	return NULL;
+}
+
+/** Allocate a memory block
+ *
+ * Should be called only inside the critical section.
+ *
+ * @param size  The size of the block to allocate.
+ * @param align Memory address alignment.
+ *
+ * @return Address of the allocated block or NULL on not enough memory.
+ *
+ */
+static void *malloc_internal(const size_t size, const size_t align)
+{
+	assert(first_heap_area != NULL);
+	
+	if (align == 0)
+		return NULL;
+	
+	size_t falign = lcm(align, BASE_ALIGN);
+	size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
+	
+	bool retry = false;
+	heap_block_head_t *split;
+	
+loop:
+	
+	/* Try the next fit approach */
+	split = next;
+	
+	if (split != NULL) {
+		void *addr = malloc_area(split->area, split, NULL, real_size,
+		    falign);
+		
+		if (addr != NULL)
+			return addr;
+	}
+	
+	/* Search the entire heap */
+	heap_area_t *area;
+	for (area = first_heap_area; area != NULL; area = area->next) {
+		heap_block_head_t *first = (heap_block_head_t *)
+		    AREA_FIRST_BLOCK(area);
+		
+		void *addr = malloc_area(area, first, split, real_size,
+		    falign);
+		
+		if (addr != NULL)
+			return addr;
+	}
+	
+	if (!retry) {
+		/* Try to grow the heap space */
+		if (heap_grow(real_size)) {
+			retry = true;
 			goto loop;
 		}
 	}
 	
-	return result;
+	return NULL;
 }
 
@@ -473,9 +650,12 @@
 	    (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
 	
-	assert((void *) head >= heap_start);
-	assert((void *) head < heap_end);
-	
 	block_check(head);
 	assert(!head->free);
+	
+	heap_area_t *area = head->area;
+	
+	area_check(area);
+	assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
+	assert((void *) head < area->end);
 	
 	void *ptr = NULL;
@@ -487,29 +667,34 @@
 		/* Shrink */
 		if (orig_size - real_size >= STRUCT_OVERHEAD) {
-			/* Split the original block to a full block
-			   and a trailing free block */
-			block_init((void *) head, real_size, false);
+			/*
+			 * Split the original block to a full block
+			 * and a trailing free block.
+			 */
+			block_init((void *) head, real_size, false, area);
 			block_init((void *) head + real_size,
-			    orig_size - real_size, true);
-			shrink_heap();
+			    orig_size - real_size, true, area);
+			heap_shrink();
 		}
 		
 		ptr = ((void *) head) + sizeof(heap_block_head_t);
 	} else {
-		/* Look at the next block. If it is free and the size is
-		   sufficient then merge the two. Otherwise just allocate
-		   a new block, copy the original data into it and
-		   free the original block. */
+		/*
+		 * Look at the next block. If it is free and the size is
+		 * sufficient then merge the two. Otherwise just allocate
+		 * a new block, copy the original data into it and
+		 * free the original block.
+		 */
 		heap_block_head_t *next_head =
 		    (heap_block_head_t *) (((void *) head) + head->size);
 		
-		if (((void *) next_head < heap_end) &&
+		if (((void *) next_head < area->end) &&
 		    (head->size + next_head->size >= real_size) &&
 		    (next_head->free)) {
 			block_check(next_head);
-			block_init(head, head->size + next_head->size, false);
+			block_init(head, head->size + next_head->size, false, area);
 			split_mark(head, real_size);
 			
 			ptr = ((void *) head) + sizeof(heap_block_head_t);
+			next = NULL;
 		} else
 			reloc = true;
@@ -542,9 +727,12 @@
 	    = (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
 	
-	assert((void *) head >= heap_start);
-	assert((void *) head < heap_end);
-	
 	block_check(head);
 	assert(!head->free);
+	
+	heap_area_t *area = head->area;
+	
+	area_check(area);
+	assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
+	assert((void *) head < area->end);
 	
 	/* Mark the block itself as free. */
@@ -555,12 +743,12 @@
 	    = (heap_block_head_t *) (((void *) head) + head->size);
 	
-	if ((void *) next_head < heap_end) {
+	if ((void *) next_head < area->end) {
 		block_check(next_head);
 		if (next_head->free)
-			block_init(head, head->size + next_head->size, true);
+			block_init(head, head->size + next_head->size, true, area);
 	}
 	
 	/* Look at the previous block. If it is free, merge the two. */
-	if ((void *) head > heap_start) {
+	if ((void *) head > (void *) AREA_FIRST_BLOCK(area)) {
 		heap_block_foot_t *prev_foot =
 		    (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
@@ -572,8 +760,9 @@
 		
 		if (prev_head->free)
-			block_init(prev_head, prev_head->size + head->size, true);
-	}
-	
-	shrink_heap();
+			block_init(prev_head, prev_head->size + head->size, true,
+			    area);
+	}
+	
+	heap_shrink();
 	
 	futex_up(&malloc_futex);
Index: uspace/lib/c/generic/private/libc.h
===================================================================
--- uspace/lib/c/generic/private/libc.h	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/generic/private/libc.h	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -36,6 +36,7 @@
 #define LIBC_PRIVATE_LIBC_H_
 
+extern void __entry(void);
+extern void __main(void *) __attribute__((noreturn));
 extern int main(int, char *[]);
-extern void __main(void *) __attribute__((noreturn));
 
 #endif
Index: uspace/lib/c/include/as.h
===================================================================
--- uspace/lib/c/include/as.h	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/include/as.h	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -41,4 +41,17 @@
 #include <libarch/config.h>
 
+static inline size_t SIZE2PAGES(size_t size)
+{
+	if (size == 0)
+		return 0;
+	
+	return (size_t) ((size - 1) >> PAGE_WIDTH) + 1;
+}
+
+static inline size_t PAGES2SIZE(size_t pages)
+{
+	return (size_t) (pages << PAGE_WIDTH);
+}
+
 extern void *as_area_create(void *address, size_t size, int flags);
 extern int as_area_resize(void *address, size_t size, int flags);
Index: uspace/lib/c/include/malloc.h
===================================================================
--- uspace/lib/c/include/malloc.h	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/include/malloc.h	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -38,6 +38,4 @@
 #include <sys/types.h>
 
-extern uintptr_t get_max_heap_addr(void);
-
 extern void *malloc(const size_t size)
     __attribute__((malloc));
Index: uspace/lib/c/include/unistd.h
===================================================================
--- uspace/lib/c/include/unistd.h	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/lib/c/include/unistd.h	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -44,6 +44,4 @@
 #endif
 
-#define getpagesize()  (PAGE_SIZE)
-
 #ifndef SEEK_SET
 	#define SEEK_SET  0
@@ -57,4 +55,6 @@
 	#define SEEK_END  2
 #endif
+
+#define getpagesize()  (PAGE_SIZE)
 
 extern int dup2(int oldfd, int newfd);
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/devman/devman.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -1215,7 +1215,7 @@
 	if (info != NULL) {
 		memset(info, 0, sizeof(dev_class_info_t));
-		list_initialize(&info->dev_classes);
-		list_initialize(&info->devmap_link);
-		list_initialize(&info->link);
+		link_initialize(&info->dev_classes);
+		link_initialize(&info->devmap_link);
+		link_initialize(&info->link);
 	}
 	
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/devmap/devmap.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -423,5 +423,6 @@
 	 */
 	list_initialize(&driver->devices);
-	list_initialize(&(driver->drivers));
+
+	link_initialize(&driver->drivers);
 	
 	fibril_mutex_lock(&drivers_list_mutex);
@@ -538,6 +539,6 @@
 	}
 	
-	list_initialize(&(device->devices));
-	list_initialize(&(device->driver_devices));
+	link_initialize(&device->devices);
+	link_initialize(&device->driver_devices);
 	
 	/* Check that device is not already registered */
@@ -942,6 +943,6 @@
 	}
 	
-	list_initialize(&(device->devices));
-	list_initialize(&(device->driver_devices));
+	link_initialize(&device->devices);
+	link_initialize(&device->driver_devices);
 	
 	/* Get unique device handle */
Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -130,4 +130,5 @@
 {
 	devfs_node_t *node = (devfs_node_t *) pfn->data;
+	int ret;
 	
 	if (node->handle == 0) {
@@ -145,6 +146,7 @@
 				
 				if (str_cmp(devs[pos].name, component) == 0) {
+					ret = devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
 					free(devs);
-					return devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
+					return ret;
 				}
 			}
@@ -162,6 +164,7 @@
 				for (pos = 0; pos < count; pos++) {
 					if (str_cmp(devs[pos].name, component) == 0) {
+						ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
 						free(devs);
-						return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
+						return ret;
 					}
 				}
@@ -184,6 +187,7 @@
 			for (pos = 0; pos < count; pos++) {
 				if (str_cmp(devs[pos].name, component) == 0) {
+					ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
 					free(devs);
-					return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
+					return ret;
 				}
 			}
Index: pace/srv/hw/netif/ne2000/dp8390_drv.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390_drv.h	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface driver interface.
- */
-
-#ifndef __NET_NETIF_DP8390_DRIVER_H__
-#define __NET_NETIF_DP8390_DRIVER_H__
-
-#include "dp8390.h"
-
-int do_init(dpeth_t *dep);
-
-/** Stops the network interface.
- *  @param[in,out] dep The network interface structure.
- */
-void do_stop(dpeth_t *dep);
-
-/** Processes the interrupt.
- *  @param[in,out] dep The network interface structure.
- */
-void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, uint8_t isr);
-
-/** Probes and initializes the network interface.
- *  @param[in,out] dep The network interface structure.
- *  @returns EOK on success.
- *  @returns EXDEV if the network interface was not recognized.
- */
-int do_probe(dpeth_t * dep);
-
-/** Sends a packet.
- *  @param[in,out] dep The network interface structure.
- *  @param[in] packet The packet t be sent.
- *  @param[in] from_int The value indicating whether the sending is initialized from the interrupt handler.
- *  @returns
- */
-int do_pwrite(dpeth_t * dep, packet_t *packet, int from_int);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hw/netif/ne2000/dp8390_port.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390_port.h	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ 	(revision )
@@ -1,146 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface types and structures ports.
- */
-
-#ifndef __NET_NETIF_DP8390_PORT_H__
-#define __NET_NETIF_DP8390_PORT_H__
-
-#include <errno.h>
-#include <mem.h>
-#include <stdio.h>
-#include <libarch/ddi.h>
-#include <sys/types.h>
-
-/** Reads 1 byte.
- *  @param[in] port The address to be read.
- *  @returns The read value.
- */
-#define inb(port)  pio_read_8((ioport8_t *) (port))
-
-/** Reads 1 word (2 bytes).
- *  @param[in] port The address to be read.
- *  @returns The read value.
- */
-#define inw(port)  pio_read_16((ioport16_t *) (port))
-
-/** Writes 1 byte.
- *  @param[in] port The address to be written.
- *  @param[in] value The value to be written.
- */
-#define outb(port, value)  pio_write_8((ioport8_t *) (port), (value))
-
-/** Writes 1 word (2 bytes).
- *  @param[in] port The address to be written.
- *  @param[in] value The value to be written.
- */
-#define outw(port, value)  pio_write_16((ioport16_t *) (port), (value))
-
-/** Type definition of a port.
- */
-typedef long port_t;
-
-/** Ethernet statistics.
- */
-typedef struct eth_stat {
-	/** Number of receive errors.
-	 */
-	unsigned long ets_recvErr;
-	/** Number of send error.
-	 */
-	unsigned long ets_sendErr;
-	/** Number of buffer overwrite warnings.
-	 */
-	unsigned long ets_OVW;
-	/** Number of crc errors of read.
-	 */
-	unsigned long ets_CRCerr;
-	/** Number of frames not alligned (number of bits % 8 != 0).
-	 */
-	unsigned long ets_frameAll;
-	/** Number of packets missed due to slow processing.
-	 */
-	unsigned long ets_missedP;
-	/** Number of packets received.
-	 */
-	unsigned long ets_packetR;
-	/** Number of packets transmitted.
-	 */
-	unsigned long ets_packetT;
-	/** Number of transmission defered (Tx was busy).
-	 */
-	unsigned long ets_transDef;
-	/** Number of collissions.
-	 */
-	unsigned long ets_collision;
-	/** Number of Tx aborted due to excess collisions.
-	 */
-	unsigned long ets_transAb;
-	/** Number of carrier sense lost.
-	 */
-	unsigned long ets_carrSense;
-	/** Number of FIFO underruns (processor too busy).
-	 */
-	unsigned long ets_fifoUnder;
-	/** Number of FIFO overruns (processor too busy).
-	 */
-	unsigned long ets_fifoOver;
-	/** Number of times unable to transmit collision sig.
-	 */
-	unsigned long ets_CDheartbeat;
-	/** Number of times out of window collision.
-	 */
-	unsigned long ets_OWC;
-} eth_stat_t;
-
-/** Minimum Ethernet packet size in bytes.
- */
-#define ETH_MIN_PACK_SIZE  60
-
-/** Maximum Ethernet packet size in bytes.
- */
-#define ETH_MAX_PACK_SIZE_TAGGED  1518
-
-/** Ethernet address type definition.
- */
-typedef struct ether_addr {
-	/** Address data.
-	 */
-	uint8_t ea_addr[6];
-} ether_addr_t;
-
-#endif
-
-/** @}
- */
Index: pace/srv/hw/netif/ne2000/ne2000.h
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.h	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ 	(revision )
@@ -1,119 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This code is based upon the NE2000 driver for MINIX,
- * distributed according to a BSD-style license.
- *
- * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
- * Copyright (c) 1992, 1994 Philip Homburg
- * Copyright (c) 1996 G. Falzoni
- *
- */
-
-/** @addtogroup ne2k
- *  @{
- */
-
-/** @file
- *  NE1000 and NE2000 network interface definitions.
- */
-
-#ifndef __NET_NETIF_NE2000_H__
-#define __NET_NETIF_NE2000_H__
-
-#include <libarch/ddi.h>
-#include "dp8390_port.h"
-
-/** DP8390 register offset.
- */
-#define NE_DP8390  0x00
-
-/** Data register.
- */
-#define NE_DATA  0x10
-
-/** Reset register.
- */
-#define NE_RESET  0x1f
-
-/** NE1000 data start.
- */
-#define NE1000_START  0x2000
-
-/** NE1000 data size.
- */
-#define NE1000_SIZE  0x2000
-
-/** NE2000 data start.
- */
-#define NE2000_START  0x4000
-
-/** NE2000 data size.
- */
-#define NE2000_SIZE  0x4000
-
-/** Reads 1 byte register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inb_ne(dep, reg)  (inb(dep->de_base_port + reg))
-
-/** Writes 1 byte register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outb_ne(dep, reg, data)  (outb(dep->de_base_port + reg, data))
-
-/** Reads 1 word (2 bytes) register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inw_ne(dep, reg)  (inw(dep->de_base_port + reg))
-
-/** Writes 1 word (2 bytes) register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outw_ne(dep, reg, data)  (outw(dep->de_base_port + reg, data))
-
-struct dpeth;
-
-extern int ne_probe(struct dpeth *);
-extern void ne_init(struct dpeth *);
-extern void ne_stop(struct dpeth *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/loader/arch/abs32le/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/abs32le/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/loader/arch/abs32le/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -3,4 +3,5 @@
  * is the base address and the special interp section.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -54,8 +55,4 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	
-	_heap = .;
-	
 	/DISCARD/ : {
 		*(*);
Index: uspace/srv/loader/arch/amd64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/amd64/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/loader/arch/amd64/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -54,7 +54,4 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	_heap = .;
-	
 #ifdef CONFIG_LINE_DEBUG
 	.comment 0 : { *(.comment); } :debug
Index: uspace/srv/loader/arch/arm32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/arm32/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/loader/arch/arm32/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -3,4 +3,5 @@
  * is the base address.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -16,13 +17,14 @@
 		*(.interp);
 	} : interp
-
+	
 	. = 0x70001000;
-
+	
 	.init ALIGN(0x1000): SUBALIGN(0x1000) {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
-        *(.rodata*);
+		*(.rodata*);
 	} :text
 	
@@ -32,4 +34,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -37,4 +40,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -42,18 +46,16 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
 		*(.scommon);
-        *(COMMON);
-        *(.bss);
+		*(COMMON);
+		*(.bss);
 	} :data
-	
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/arch/ia32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia32/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/loader/arch/ia32/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -54,7 +54,4 @@
 	} :data
 	
-	. = ALIGN(0x1000);
-	_heap = .;
-	
 #ifdef CONFIG_LINE_DEBUG
 	.comment 0 : { *(.comment); } :debug
Index: uspace/srv/loader/arch/ia64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia64/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/loader/arch/ia64/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -12,22 +12,24 @@
 		*(.interp);
 	} :interp
-
+	
 	/* On Itanium code sections must be aligned to 16 bytes. */
 	. = ALIGN(0x800000000 + SIZEOF_HEADERS, 16);
-
+	
 	.init : {
 		*(.init);
-	} : text
+	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		_gp = .;
 		*(.got*);
-	} :data	
+	} :data
+	
 	.data : {
 		*(.opd);
@@ -35,4 +37,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -40,4 +43,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -45,5 +49,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
@@ -52,10 +58,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
- 
+	
 	/DISCARD/ : {
 		*(*);
-        }
+	}
 }
Index: uspace/srv/loader/arch/mips32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/mips32/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/loader/arch/mips32/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -3,4 +3,5 @@
  * is the base address.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -16,5 +17,5 @@
 		*(.interp);
 	} :interp
-
+	
 	. = 0x70004000;
 	
@@ -22,19 +23,22 @@
 		*(.init);
 	} :text
+	
 	.text : {
-	        *(.text);
+		*(.text);
 		*(.rodata*);
 	} :text
-
+	
+	. = . + 0x4000;
+	
 	.data : {
 		*(.data);
 		*(.data.rel*);
 	} :data
-
+	
 	.got : {
 		_gp = .;
 		*(.got);
 	} :data
-
+	
 	.tdata : {
 		_tdata_start = .;
@@ -42,4 +46,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -47,18 +52,17 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-
+	
 	.sbss : {
 		*(.scommon);
 		*(.sbss);
-	}	
+	}
+	
 	.bss : {
 		*(.bss);
 		*(COMMON);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
-
+	
 	/DISCARD/ : {
 		*(*);
Index: uspace/srv/loader/arch/ppc32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ppc32/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/loader/arch/ppc32/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -3,4 +3,5 @@
  * is the base address.
  */
+
 STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
 ENTRY(__entry)
@@ -16,10 +17,11 @@
 		*(.interp);
 	} :interp
-
+	
 	. = 0x70001000;
-
+	
 	.init ALIGN(0x1000) : SUBALIGN(0x1000) {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
@@ -31,4 +33,5 @@
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -36,4 +39,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -41,5 +45,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
@@ -47,11 +53,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x1000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/arch/sparc64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/sparc64/_link.ld.in	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/loader/arch/sparc64/_link.ld.in	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -12,25 +12,28 @@
 		*(.interp);
 	} :interp
-
+	
 	. = 0x70004000 + SIZEOF_HEADERS;
-
+	
 	.init : {
 		*(.init);
 	} :text
+	
 	.text : {
 		*(.text);
 		*(.rodata*);
 	} :text
-
+	
 	. = . + 0x4000;
-
+	
 	.got : {
 		 _gp = .;
 		 *(.got*);
 	} :data
+	
 	.data : {
 		*(.data);
 		*(.sdata);
 	} :data
+	
 	.tdata : {
 		_tdata_start = .;
@@ -38,4 +41,5 @@
 		_tdata_end = .;
 	} :data
+	
 	.tbss : {
 		_tbss_start = .;
@@ -43,5 +47,7 @@
 		_tbss_end = .;
 	} :data
+	
 	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
 	.bss : {
 		*(.sbss);
@@ -49,11 +55,7 @@
 		*(.bss);
 	} :data
-
-	. = ALIGN(0x4000);
-	_heap = .;
 	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: uspace/srv/loader/elf_load.c
===================================================================
--- uspace/srv/loader/elf_load.c	(revision aa7dc644425ea445fd1fdb18d7514a66abe2799f)
+++ uspace/srv/loader/elf_load.c	(revision 0c968a174f806fa1ecd217fa560e17d52b328b6a)
@@ -109,5 +109,5 @@
 	int fd;
 	int rc;
-
+	
 	fd = open(file_name, O_RDONLY);
 	if (fd < 0) {
@@ -344,5 +344,5 @@
 	seg_ptr = (void *) seg_addr;
 
-	DPRINTF("Load segment at addr %p, size 0x%x\n", seg_addr,
+	DPRINTF("Load segment at addr %p, size 0x%x\n", (void *) seg_addr,
 		entry->p_memsz);
 
@@ -372,6 +372,7 @@
 	mem_sz = entry->p_memsz + (entry->p_vaddr - base);
 
-	DPRINTF("Map to seg_addr=%p-%p.\n", seg_addr,
-	entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
+	DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
+	    (void *) (entry->p_vaddr + bias +
+	    ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
 
 	/*
@@ -386,6 +387,6 @@
 	}
 
-	DPRINTF("as_area_create(%p, 0x%x, %d) -> 0x%lx\n",
-		base + bias, mem_sz, flags, (uintptr_t)a);
+	DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
+	    (void *) (base + bias), mem_sz, flags, (void *) a);
 
 	/*
@@ -464,5 +465,5 @@
 		    (void *)((uint8_t *)entry->sh_addr + elf->bias);
 		DPRINTF("Dynamic section found at %p.\n",
-			(uintptr_t)elf->info->dynamic);
+		    (void *) elf->info->dynamic);
 		break;
 	default:
