Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 4ce914d4d867104231d15513fe8669e434fea7b2)
+++ kernel/generic/include/mm/as.h	(revision bb252caaca456fa3c79db527765634f7d355ba61)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2010 Jakub Jermar
  * All rights reserved.
  *
@@ -227,40 +227,40 @@
 extern void as_init(void);
 
-extern as_t *as_create(int flags);
-extern void as_destroy(as_t *as);
-extern void as_switch(as_t *old_as, as_t *new_as);
-extern int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate);
-
-extern as_area_t *as_area_create(as_t *as, int flags, size_t size,
-    uintptr_t base, int attrs, mem_backend_t *backend,
-    mem_backend_data_t *backend_data);
-extern int as_area_destroy(as_t *as, uintptr_t address);	
-extern int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags);
-int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
-    as_t *dst_as, uintptr_t dst_base, int dst_flags_mask);
-extern int as_area_change_flags(as_t *as, int flags, uintptr_t address);
-
-extern int as_area_get_flags(as_area_t *area);
-extern bool as_area_check_access(as_area_t *area, pf_access_t access);
-extern size_t as_area_get_size(uintptr_t base);
-extern int used_space_insert(as_area_t *a, uintptr_t page, size_t count);
-extern int used_space_remove(as_area_t *a, uintptr_t page, size_t count);
+extern as_t *as_create(int);
+extern void as_destroy(as_t *);
+extern void as_hold(as_t *);
+extern void as_release(as_t *);
+extern void as_switch(as_t *, as_t *);
+extern int as_page_fault(uintptr_t, pf_access_t, istate_t *);
+
+extern as_area_t *as_area_create(as_t *, int, size_t, uintptr_t, int,
+    mem_backend_t *, mem_backend_data_t *);
+extern int as_area_destroy(as_t *, uintptr_t);
+extern int as_area_resize(as_t *, uintptr_t, size_t, int);
+extern int as_area_share(as_t *, uintptr_t, size_t, as_t *, uintptr_t, int);
+extern int as_area_change_flags(as_t *, int, uintptr_t);
+
+extern int as_area_get_flags(as_area_t *);
+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);
 
 
 /* Interface to be implemented by architectures. */
 #ifndef as_constructor_arch
-extern int as_constructor_arch(as_t *as, int flags);
+extern int as_constructor_arch(as_t *, int);
 #endif /* !def as_constructor_arch */
 #ifndef as_destructor_arch
-extern int as_destructor_arch(as_t *as);
+extern int as_destructor_arch(as_t *);
 #endif /* !def as_destructor_arch */
 #ifndef as_create_arch
-extern int as_create_arch(as_t *as, int flags);
+extern int as_create_arch(as_t *, int);
 #endif /* !def as_create_arch */
 #ifndef as_install_arch
-extern void as_install_arch(as_t *as);
+extern void as_install_arch(as_t *);
 #endif /* !def as_install_arch */
 #ifndef as_deinstall_arch
-extern void as_deinstall_arch(as_t *as);
+extern void as_deinstall_arch(as_t *);
 #endif /* !def as_deinstall_arch */
 
@@ -277,15 +277,15 @@
 #define ELD_F_LOADER	1
 
-extern unsigned int elf_load(elf_header_t *header, as_t *as, int flags);
+extern unsigned int elf_load(elf_header_t *, as_t *, int);
 
 /* Address space area related syscalls. */
-extern unative_t sys_as_area_create(uintptr_t address, size_t size, int flags);
-extern unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags);
-extern unative_t sys_as_area_change_flags(uintptr_t address, int flags);
-extern unative_t sys_as_area_destroy(uintptr_t address);
+extern unative_t sys_as_area_create(uintptr_t, size_t, int);
+extern unative_t sys_as_area_resize(uintptr_t, size_t, int);
+extern unative_t sys_as_area_change_flags(uintptr_t, int);
+extern unative_t sys_as_area_destroy(uintptr_t);
 
 /* Introspection functions. */
-extern void as_get_area_info(as_t *as, as_area_info_t **obuf, size_t *osize);
-extern void as_print(as_t *as);
+extern void as_get_area_info(as_t *, as_area_info_t **, size_t *);
+extern void as_print(as_t *);
 
 #endif /* KERNEL */
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 4ce914d4d867104231d15513fe8669e434fea7b2)
+++ kernel/generic/include/proc/task.h	(revision bb252caaca456fa3c79db527765634f7d355ba61)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2010 Jakub Jermar
  * All rights reserved.
  *
@@ -131,24 +131,26 @@
 extern void task_init(void);
 extern void task_done(void);
-extern task_t *task_create(as_t *as, const char *name);
-extern void task_destroy(task_t *t);
-extern task_t *task_find_by_id(task_id_t id);
-extern int task_kill(task_id_t id);
-extern void task_get_accounting(task_t *t, uint64_t *ucycles, uint64_t *kcycles);
+extern task_t *task_create(as_t *, const char *);
+extern void task_destroy(task_t *);
+extern void task_hold(task_t *);
+extern void task_release(task_t *);
+extern task_t *task_find_by_id(task_id_t);
+extern int task_kill(task_id_t);
+extern void task_get_accounting(task_t *, uint64_t *, uint64_t *);
 extern void task_print_list(void);
 
-extern void cap_set(task_t *t, cap_t caps);
-extern cap_t cap_get(task_t *t);
+extern void cap_set(task_t *, cap_t);
+extern cap_t cap_get(task_t *);
 
 #ifndef task_create_arch
-extern void task_create_arch(task_t *t);
+extern void task_create_arch(task_t *);
 #endif
 
 #ifndef task_destroy_arch
-extern void task_destroy_arch(task_t *t);
+extern void task_destroy_arch(task_t *);
 #endif
 
-extern unative_t sys_task_get_id(task_id_t *uspace_task_id);
-extern unative_t sys_task_set_name(const char *uspace_name, size_t name_len);
+extern unative_t sys_task_get_id(task_id_t *);
+extern unative_t sys_task_set_name(const char *, size_t);
 
 #endif
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 4ce914d4d867104231d15513fe8669e434fea7b2)
+++ kernel/generic/src/mm/as.c	(revision bb252caaca456fa3c79db527765634f7d355ba61)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2001-2006 Jakub Jermar
+ * Copyright (c) 2010 Jakub Jermar
  * All rights reserved.
  *
@@ -152,5 +152,5 @@
 	 * reference count never drops to zero.
 	 */
-	atomic_set(&AS_KERNEL->refcount, 1);
+	as_hold(AS_KERNEL);
 }
 
@@ -200,9 +200,10 @@
 	DEADLOCK_PROBE_INIT(p_asidlock);
 
+	ASSERT(as != AS);
 	ASSERT(atomic_get(&as->refcount) == 0);
 	
 	/*
-	 * Since there is no reference to this area,
-	 * it is safe not to lock its mutex.
+	 * Since there is no reference to this address space, it is safe not to
+	 * lock its mutex.
 	 */
 
@@ -225,5 +226,5 @@
 	preemption_enable();	/* Interrupts disabled, enable preemption */
 	if (as->asid != ASID_INVALID && as != AS_KERNEL) {
-		if (as != AS && as->cpu_refcount == 0)
+		if (as->cpu_refcount == 0)
 			list_remove(&as->inactive_as_with_asid_link);
 		asid_put(as->asid);
@@ -258,4 +259,29 @@
 
 	slab_free(as_slab, as);
+}
+
+/** Hold a reference to an address space.
+ *
+ * Holding a reference to an address space prevents destruction of that address
+ * space.
+ *
+ * @param a		Address space to be held.
+ */
+void as_hold(as_t *as)
+{
+	atomic_inc(&as->refcount);
+}
+
+/** Release a reference to an address space.
+ *
+ * The last one to release a reference to an address space destroys the address
+ * space.
+ *
+ * @param a		Address space to be released.
+ */
+void as_release(as_t *as)
+{
+	if (atomic_predec(&as->refcount) == 0)
+		as_destroy(as);
 }
 
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision 4ce914d4d867104231d15513fe8669e434fea7b2)
+++ kernel/generic/src/proc/scheduler.c	(revision bb252caaca456fa3c79db527765634f7d355ba61)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2001-2007 Jakub Jermar
+ * Copyright (c) 2010 Jakub Jermar
  * All rights reserved.
  *
@@ -382,7 +382,19 @@
 	int priority;
 	DEADLOCK_PROBE_INIT(p_joinwq);
+	task_t *old_task = TASK;
+	as_t *old_as = AS;
 
 	ASSERT(CPU != NULL);
 	
+	/*
+	 * Hold the current task and the address space to prevent their
+	 * possible destruction should thread_destroy() be called on this or any
+	 * other processor while the scheduler is still using them.
+	 */
+	if (old_task)
+		task_hold(old_task);
+	if (old_as)
+		as_hold(old_as);
+
 	if (THREAD) {
 		/* must be run after the switch to scheduler stack */
@@ -476,16 +488,5 @@
 	 */
 	if (TASK != THREAD->task) {
-		as_t *as1 = NULL;
-		as_t *as2;
-
-		if (TASK) {
-			spinlock_lock(&TASK->lock);
-			as1 = TASK->as;
-			spinlock_unlock(&TASK->lock);
-		}
-
-		spinlock_lock(&THREAD->task->lock);
-		as2 = THREAD->task->as;
-		spinlock_unlock(&THREAD->task->lock);
+		as_t *new_as = THREAD->task->as;
 		
 		/*
@@ -493,15 +494,21 @@
 		 * space.
 		 */
-		if (as1 != as2) {
+		if (old_as != new_as) {
 			/*
 			 * Both tasks and address spaces are different.
 			 * Replace the old one with the new one.
 			 */
-			as_switch(as1, as2);
+			as_switch(old_as, new_as);
 		}
+
 		TASK = THREAD->task;
 		before_task_runs();
 	}
 
+	if (old_task)
+		task_release(old_task);
+	if (old_as)
+		as_release(old_as);
+	
 	spinlock_lock(&THREAD->lock);	
 	THREAD->state = Running;
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 4ce914d4d867104231d15513fe8669e434fea7b2)
+++ kernel/generic/src/proc/task.c	(revision bb252caaca456fa3c79db527765634f7d355ba61)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2010 Jakub Jermar
  * All rights reserved.
  *
@@ -210,6 +210,10 @@
 	btree_create(&ta->futexes);
 	
+	/*
+	 * Get a reference to the address space.
+	 */
+	as_hold(ta->as);
+
 	ipl = interrupts_disable();
-	atomic_inc(&as->refcount);
 	spinlock_lock(&tasks_lock);
 	ta->taskid = ++task_counter;
@@ -250,9 +254,30 @@
 	 * Drop our reference to the address space.
 	 */
-	if (atomic_predec(&t->as->refcount) == 0) 
-		as_destroy(t->as);
+	as_release(t->as);
 	
 	slab_free(task_slab, t);
-	TASK = NULL;
+}
+
+/** Hold a reference to a task.
+ *
+ * Holding a reference to a task prevents destruction of that task.
+ *
+ * @param t		Task to be held.
+ */
+void task_hold(task_t *t)
+{
+	atomic_inc(&t->refcount);
+}
+
+/** Release a reference to a task.
+ *
+ * The last one to release a reference to a task destroys the task.
+ *
+ * @param t		Task to be released.
+ */
+void task_release(task_t *t)
+{
+	if ((atomic_predec(&t->refcount)) == 0)
+		task_destroy(t);
 }
 
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 4ce914d4d867104231d15513fe8669e434fea7b2)
+++ kernel/generic/src/proc/thread.c	(revision bb252caaca456fa3c79db527765634f7d355ba61)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2010 Jakub Jermar
  * All rights reserved.
  *
@@ -409,9 +409,7 @@
 
 	/*
-	 * t is guaranteed to be the very last thread of its task.
-	 * It is safe to destroy the task.
+	 * Drop the reference to the containing task.
 	 */
-	if (atomic_predec(&t->task->refcount) == 0)
-		task_destroy(t->task);
+	task_release(t->task);
 	
 	slab_free(thread_slab, t);
@@ -436,5 +434,6 @@
 	spinlock_lock(&task->lock);
 
-	atomic_inc(&task->refcount);
+	/* Hold a reference to the task. */
+	task_hold(task);
 
 	/* Must not count kbox thread into lifecount */
