Index: kernel/generic/include/proc/thread.h
===================================================================
--- kernel/generic/include/proc/thread.h	(revision 0843f0254484d658f022d606b3d47bf05f76a621)
+++ kernel/generic/include/proc/thread.h	(revision df58e448060bb6d63ea118d30cb9b3b9b8c059bf)
@@ -91,21 +91,23 @@
 	
 	/** Function implementing the thread. */
-	void (* thread_code)(void *);
+	void (*thread_code)(void *);
 	/** Argument passed to thread_code() function. */
 	void *thread_arg;
 	
 	/**
-	 * From here, the stored context is restored when the thread is
-	 * scheduled.
+	 * From here, the stored context is restored
+	 * when the thread is scheduled.
 	 */
 	context_t saved_context;
-	/**
-	 * From here, the stored timeout context is restored when sleep times
-	 * out.
+	
+	/**
+	 * From here, the stored timeout context
+	 * is restored when sleep times out.
 	 */
 	context_t sleep_timeout_context;
-	/**
-	 * From here, the stored interruption context is restored when sleep is
-	 * interrupted.
+	
+	/**
+	 * From here, the stored interruption context
+	 * is restored when sleep is interrupted.
 	 */
 	context_t sleep_interruption_context;
@@ -125,4 +127,5 @@
 	 */
 	bool in_copy_from_uspace;
+	
 	/**
 	 * True if this thread is executing copy_to_uspace().
@@ -136,4 +139,10 @@
 	 */
 	bool interrupted;
+	
+	/**
+	 * If true, the scheduler will print a stack trace
+	 * to the kernel console upon scheduling this thread.
+	 */
+	bool btrace;
 	
 	/** If true, thread_join_timeout() cannot be used on this thread. */
@@ -236,4 +245,5 @@
 extern void thread_update_accounting(bool);
 extern bool thread_exists(thread_t *);
+extern void thread_stack_trace(thread_id_t);
 
 /** Fpu context slab cache. */
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision 0843f0254484d658f022d606b3d47bf05f76a621)
+++ kernel/generic/src/console/cmd.c	(revision df58e448060bb6d63ea118d30cb9b3b9b8c059bf)
@@ -78,25 +78,28 @@
 static cmd_info_t help_info = {
 	.name = "help",
-	.description = "List of supported commands.",
+	.description = "List supported commands.",
 	.func = cmd_help,
 	.argc = 0
 };
 
+/* Data and methods for 'reboot' command. */
 static int cmd_reboot(cmd_arg_t *argv);
 static cmd_info_t reboot_info = {
 	.name = "reboot",
-	.description = "Reboot.",
+	.description = "Reboot system.",
 	.func = cmd_reboot,
 	.argc = 0
 };
 
+/* Data and methods for 'uptime' command. */
 static int cmd_uptime(cmd_arg_t *argv);
 static cmd_info_t uptime_info = {
 	.name = "uptime",
-	.description = "Print uptime information.",
+	.description = "Show system uptime.",
 	.func = cmd_uptime,
 	.argc = 0
 };
 
+/* Data and methods for 'continue' command. */
 static int cmd_continue(cmd_arg_t *argv);
 static cmd_info_t continue_info = {
@@ -108,4 +111,5 @@
 
 #ifdef CONFIG_TEST
+/* Data and methods for 'test' command. */
 static char test_buf[MAX_CMDLINE + 1];
 static int cmd_test(cmd_arg_t *argv);
@@ -119,5 +123,5 @@
 static cmd_info_t test_info = {
 	.name = "test",
-	.description = "Print list of kernel tests or run a test.",
+	.description = "<test> List kernel tests or run a test.",
 	.func = cmd_test,
 	.argc = 1,
@@ -125,4 +129,5 @@
 };
 
+/* Data and methods for 'bench' command. */
 static int cmd_bench(cmd_arg_t *argv);
 static cmd_arg_t bench_argv[] = {
@@ -138,5 +143,5 @@
 static cmd_info_t bench_info = {
 	.name = "bench",
-	.description = "Run kernel test as benchmark.",
+	.description = "<test> <count> Run kernel test as benchmark.",
 	.func = cmd_bench,
 	.argc = 2,
@@ -148,5 +153,5 @@
 static int cmd_desc(cmd_arg_t *argv);
 static void desc_help(void);
-static char desc_buf[MAX_CMDLINE+1];
+static char desc_buf[MAX_CMDLINE + 1];
 static cmd_arg_t desc_argv = {
 	.type = ARG_TYPE_STRING,
@@ -156,5 +161,5 @@
 static cmd_info_t desc_info = {
 	.name = "describe",
-	.description = "Describe specified command.",
+	.description = "<command> Describe specified command.",
 	.help = desc_help,
 	.func = cmd_desc,
@@ -165,5 +170,5 @@
 /* Data and methods for 'symaddr' command. */
 static int cmd_symaddr(cmd_arg_t *argv);
-static char symaddr_buf[MAX_CMDLINE+1];
+static char symaddr_buf[MAX_CMDLINE + 1];
 static cmd_arg_t symaddr_argv = {
 	.type = ARG_TYPE_STRING,
@@ -173,5 +178,5 @@
 static cmd_info_t symaddr_info = {
 	.name = "symaddr",
-	.description = "Return symbol address.",
+	.description = "<symbol> Return symbol address.",
 	.func = cmd_symaddr,
 	.argc = 1,
@@ -179,5 +184,6 @@
 };
 
-static char set_buf[MAX_CMDLINE+1];
+/* Data and methods for 'set4' command. */
+static char set_buf[MAX_CMDLINE + 1];
 static int cmd_set4(cmd_arg_t *argv);
 static cmd_arg_t set4_argv[] = {
@@ -193,5 +199,5 @@
 static cmd_info_t set4_info = {
 	.name = "set4",
-	.description = "set <dest_addr> <value> - 4byte version",
+	.description = "<addr> <value> Set 4B memory location to a value.",
 	.func = cmd_set4,
 	.argc = 2,
@@ -213,5 +219,5 @@
 static cmd_info_t call0_info = {
 	.name = "call0",
-	.description = "call0 <function> -> call function().",
+	.description = "<function> Call function().",
 	.func = cmd_call0,
 	.argc = 1,
@@ -228,5 +234,5 @@
 static cmd_info_t mcall0_info = {
 	.name = "mcall0",
-	.description = "mcall0 <function> -> call function() on each CPU.",
+	.description = "<function> Call function() on each CPU.",
 	.func = cmd_mcall0,
 	.argc = 1,
@@ -250,5 +256,5 @@
 static cmd_info_t call1_info = {
 	.name = "call1",
-	.description = "call1 <function> <arg1> -> call function(arg1).",
+	.description = "<function> <arg1> Call function(arg1).",
 	.func = cmd_call1,
 	.argc = 2,
@@ -277,5 +283,5 @@
 static cmd_info_t call2_info = {
 	.name = "call2",
-	.description = "call2 <function> <arg1> <arg2> -> call function(arg1,arg2).",
+	.description = "<function> <arg1> <arg2> Call function(arg1, arg2).",
 	.func = cmd_call2,
 	.argc = 3,
@@ -310,5 +316,5 @@
 static cmd_info_t call3_info = {
 	.name = "call3",
-	.description = "call3 <function> <arg1> <arg2> <arg3> -> call function(arg1,arg2,arg3).",
+	.description = "<function> <arg1> <arg2> <arg3> Call function(arg1, arg2, arg3).",
 	.func = cmd_call3,
 	.argc = 4,
@@ -340,5 +346,5 @@
 cmd_info_t tlb_info = {
 	.name = "tlb",
-	.description = "Print TLB of current processor.",
+	.description = "Print TLB of the current CPU.",
 	.help = NULL,
 	.func = cmd_tlb,
@@ -377,9 +383,21 @@
 };
 
+/* Data and methods for 'btrace' command */
+static int cmd_btrace(cmd_arg_t *argv);
+static cmd_arg_t btrace_argv = {
+	.type = ARG_TYPE_INT,
+};
+static cmd_info_t btrace_info = {
+	.name = "btrace",
+	.description = "<threadid> Show thread stack trace.",
+	.func = cmd_btrace,
+	.argc = 1,
+	.argv = &btrace_argv
+};
 
 static int cmd_sched(cmd_arg_t *argv);
 static cmd_info_t sched_info = {
 	.name = "scheduler",
-	.description = "List all scheduler information.",
+	.description = "Show scheduler information.",
 	.func = cmd_sched,
 	.argc = 0
@@ -406,7 +424,21 @@
 static cmd_info_t zones_info = {
 	.name = "zones",
-	.description = "List of memory zones.",
+	.description = "List memory zones.",
 	.func = cmd_zones,
 	.argc = 0
+};
+
+/* Data and methods for 'zone' command */
+static int cmd_zone(cmd_arg_t *argv);
+static cmd_arg_t zone_argv = {
+	.type = ARG_TYPE_INT,
+};
+
+static cmd_info_t zone_info = {
+	.name = "zone",
+	.description = "<zone> Show memory zone structure.",
+	.func = cmd_zone,
+	.argc = 1,
+	.argv = &zone_argv
 };
 
@@ -418,5 +450,5 @@
 static cmd_info_t ipc_info = {
 	.name = "ipc",
-	.description = "ipc <taskid> Show IPC information of given task.",
+	.description = "<taskid> Show IPC information of a task.",
 	.func = cmd_ipc,
 	.argc = 1,
@@ -431,22 +463,8 @@
 static cmd_info_t kill_info = {
 	.name = "kill",
-	.description = "kill <taskid> Kill a task.",
+	.description = "<taskid> Kill a task.",
 	.func = cmd_kill,
 	.argc = 1,
 	.argv = &kill_argv
-};
-
-/* Data and methods for 'zone' command */
-static int cmd_zone(cmd_arg_t *argv);
-static cmd_arg_t zone_argv = {
-	.type = ARG_TYPE_INT,
-};
-
-static cmd_info_t zone_info = {
-	.name = "zone",
-	.description = "Show memory zone structure.",
-	.func = cmd_zone,
-	.argc = 1,
-	.argv = &zone_argv
 };
 
@@ -474,4 +492,5 @@
 
 static cmd_info_t *basic_commands[] = {
+	&btrace_info,
 	&call0_info,
 	&mcall0_info,
@@ -482,19 +501,19 @@
 	&cpus_info,
 	&desc_info,
-	&reboot_info,
-	&uptime_info,
 	&halt_info,
 	&help_info,
 	&ipc_info,
 	&kill_info,
+	&physmem_info,
+	&reboot_info,
+	&sched_info,
 	&set4_info,
 	&slabs_info,
+	&symaddr_info,
 	&sysinfo_info,
-	&symaddr_info,
-	&sched_info,
+	&tasks_info,
 	&threads_info,
-	&tasks_info,
-	&physmem_info,
 	&tlb_info,
+	&uptime_info,
 	&version_info,
 	&zones_info,
@@ -531,5 +550,4 @@
 }
 
-
 /** List supported commands.
  *
@@ -574,5 +592,4 @@
 }
 
-
 /** Reboot the system.
  *
@@ -588,5 +605,4 @@
 	return 1;
 }
-
 
 /** Print system uptime information.
@@ -824,5 +840,4 @@
 }
 
-
 /** Print detailed description of 'describe' command. */
 void desc_help(void)
@@ -911,5 +926,5 @@
  * @return Always 1
  */
-int cmd_slabs(cmd_arg_t * argv)
+int cmd_slabs(cmd_arg_t *argv)
 {
 	slab_print_list();
@@ -923,5 +938,5 @@
  * @return Always 1
  */
-int cmd_sysinfo(cmd_arg_t * argv)
+int cmd_sysinfo(cmd_arg_t *argv)
 {
 	sysinfo_dump(NULL);
@@ -929,6 +944,5 @@
 }
 
-
-/** Command for listings Thread information
+/** Command for listing thread information
  *
  * @param argv Ignored
@@ -948,5 +962,5 @@
 }
 
-/** Command for listings Task information
+/** Command for listing task information
  *
  * @param argv Ignored
@@ -966,5 +980,18 @@
 }
 
-/** Command for listings Thread information
+/** Command for printing thread stack trace
+ *
+ * @param argv Integer argument from cmdline expected
+ *
+ * return Always 1
+ *
+ */
+int cmd_btrace(cmd_arg_t *argv)
+{
+	thread_stack_trace(argv[0].intval);
+	return 1;
+}
+
+/** Command for printing scheduler information
  *
  * @param argv Ignores
@@ -972,5 +999,5 @@
  * @return Always 1
  */
-int cmd_sched(cmd_arg_t * argv)
+int cmd_sched(cmd_arg_t *argv)
 {
 	sched_print_list();
@@ -984,5 +1011,5 @@
  * return Always 1
  */
-int cmd_zones(cmd_arg_t * argv)
+int cmd_zones(cmd_arg_t *argv)
 {
 	zones_print_list();
@@ -996,5 +1023,5 @@
  * return Always 1
  */
-int cmd_zone(cmd_arg_t * argv)
+int cmd_zone(cmd_arg_t *argv)
 {
 	zone_print_one(argv[0].intval);
@@ -1002,5 +1029,5 @@
 }
 
-/** Command for printing task ipc details
+/** Command for printing task IPC details
  *
  * @param argv Integer argument from cmdline expected
@@ -1008,5 +1035,5 @@
  * return Always 1
  */
-int cmd_ipc(cmd_arg_t * argv)
+int cmd_ipc(cmd_arg_t *argv)
 {
 	ipc_print_task(argv[0].intval);
@@ -1020,5 +1047,5 @@
  * return 0 on failure, 1 on success.
  */
-int cmd_kill(cmd_arg_t * argv)
+int cmd_kill(cmd_arg_t *argv)
 {
 	if (task_kill(argv[0].intval) != EOK)
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision 0843f0254484d658f022d606b3d47bf05f76a621)
+++ kernel/generic/src/proc/scheduler.c	(revision df58e448060bb6d63ea118d30cb9b3b9b8c059bf)
@@ -62,4 +62,5 @@
 #include <print.h>
 #include <debug.h>
+#include <stacktrace.h>
 
 static void scheduler_separated_stack(void);
@@ -77,5 +78,5 @@
  * Perform actions that need to be
  * taken before the newly selected
- * tread is passed control.
+ * thread is passed control.
  *
  * THREAD->lock is locked on entry
@@ -87,5 +88,5 @@
 	
 #ifdef CONFIG_FPU_LAZY
-	if(THREAD == CPU->fpu_owner)
+	if (THREAD == CPU->fpu_owner)
 		fpu_enable();
 	else
@@ -100,4 +101,14 @@
 	}
 #endif
+	
+	if (THREAD->btrace) {
+		istate_t *istate = THREAD->udebug.uspace_state;
+		if (istate != NULL) {
+			printf("Thread %" PRIu64 " stack trace:\n", THREAD->tid);
+			stack_trace_istate(istate);
+		}
+		
+		THREAD->btrace = false;
+	}
 }
 
@@ -645,5 +656,4 @@
 				/*
 				 * Ready thread on local CPU
-				 *
 				 */
 				
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 0843f0254484d658f022d606b3d47bf05f76a621)
+++ kernel/generic/src/proc/task.c	(revision df58e448060bb6d63ea118d30cb9b3b9b8c059bf)
@@ -449,10 +449,12 @@
 static void task_kill_internal(task_t *task)
 {
+	irq_spinlock_lock(&task->lock, false);
+	irq_spinlock_lock(&threads_lock, false);
+	
+	/*
+	 * Interrupt all threads.
+	 */
+	
 	link_t *cur;
-	
-	/*
-	 * Interrupt all threads.
-	 */
-	irq_spinlock_lock(&task->lock, false);
 	for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
@@ -471,4 +473,5 @@
 	}
 	
+	irq_spinlock_unlock(&threads_lock, false);
 	irq_spinlock_unlock(&task->lock, false);
 }
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 0843f0254484d658f022d606b3d47bf05f76a621)
+++ kernel/generic/src/proc/thread.c	(revision df58e448060bb6d63ea118d30cb9b3b9b8c059bf)
@@ -239,5 +239,5 @@
  * Switch thread to the ready state.
  *
- * @param t Thread to make ready.
+ * @param thread Thread to make ready.
  *
  */
@@ -246,5 +246,5 @@
 	irq_spinlock_lock(&thread->lock, true);
 	
-	ASSERT(!(thread->state == Ready));
+	ASSERT(thread->state != Ready);
 	
 	int i = (thread->priority < RQ_COUNT - 1)
@@ -338,4 +338,5 @@
 	
 	thread->interrupted = false;
+	thread->btrace = false;
 	thread->detached = false;
 	waitq_initialize(&thread->join_wq);
@@ -535,6 +536,6 @@
 /** Detach thread.
  *
- * Mark the thread as detached, if the thread is already in the Lingering
- * state, deallocate its resources.
+ * Mark the thread as detached. If the thread is already
+ * in the Lingering state, deallocate its resources.
  *
  * @param thread Thread to be detached.
@@ -740,5 +741,5 @@
 	ASSERT(interrupts_disabled());
 	ASSERT(irq_spinlock_locked(&threads_lock));
-
+	
 	thread_iterator_t iterator;
 	
@@ -751,4 +752,46 @@
 }
 
+void thread_stack_trace(thread_id_t thread_id)
+{
+	irq_spinlock_lock(&threads_lock, true);
+	
+	thread_t *thread = thread_find_by_id(thread_id);
+	if (thread == NULL) {
+		printf("No such thread.\n");
+		irq_spinlock_unlock(&threads_lock, true);
+		return;
+	}
+	
+	irq_spinlock_lock(&thread->lock, false);
+	
+	/*
+	 * Schedule a stack trace to be printed
+	 * just before the thread is scheduled next.
+	 *
+	 * If the thread is sleeping then try to interrupt
+	 * the sleep. Any request for printing an uspace stack
+	 * trace from within the kernel should be always
+	 * considered a last resort debugging means, therefore
+	 * forcing the thread's sleep to be interrupted
+	 * is probably justifiable.
+	 */
+	
+	bool sleeping = false;
+	istate_t *istate = thread->udebug.uspace_state;
+	if (istate != NULL) {
+		printf("Scheduling thread stack trace.\n");
+		thread->btrace = true;
+		if (thread->state == Sleeping)
+			sleeping = true;
+	} else
+		printf("Thread interrupt state not available.\n");
+	
+	irq_spinlock_unlock(&thread->lock, false);
+	
+	if (sleeping)
+		waitq_interrupt_sleep(thread);
+	
+	irq_spinlock_unlock(&threads_lock, true);
+}
 
 /** Process syscall to create new thread.
@@ -793,5 +836,4 @@
 				 * has already been created. We need to undo its
 				 * creation now.
-				 *
 				 */
 				
@@ -815,5 +857,4 @@
 		 * THREAD_B events for threads that already existed
 		 * and could be detected with THREAD_READ before.
-		 *
 		 */
 		udebug_thread_b_event_attach(thread, TASK);
Index: kernel/generic/src/synch/waitq.c
===================================================================
--- kernel/generic/src/synch/waitq.c	(revision 0843f0254484d658f022d606b3d47bf05f76a621)
+++ kernel/generic/src/synch/waitq.c	(revision df58e448060bb6d63ea118d30cb9b3b9b8c059bf)
@@ -127,6 +127,10 @@
 /** Interrupt sleeping thread.
  *
- * This routine attempts to interrupt a thread from its sleep in a waitqueue.
- * If the thread is not found sleeping, no action is taken.
+ * This routine attempts to interrupt a thread from its sleep in
+ * a waitqueue. If the thread is not found sleeping, no action
+ * is taken.
+ *
+ * The threads_lock must be already held and interrupts must be
+ * disabled upon calling this function.
  *
  * @param thread Thread to be interrupted.
@@ -138,7 +142,8 @@
 	DEADLOCK_PROBE_INIT(p_wqlock);
 	
-	irq_spinlock_lock(&threads_lock, true);
-	if (!thread_exists(thread))
-		goto out;
+	/*
+	 * The thread is quaranteed to exist because
+	 * threads_lock is held.
+	 */
 	
 grab_locks:
@@ -150,14 +155,13 @@
 			/*
 			 * The sleep cannot be interrupted.
-			 *
 			 */
 			irq_spinlock_unlock(&thread->lock, false);
-			goto out;
+			return;
 		}
 		
 		if (!irq_spinlock_trylock(&wq->lock)) {
+			/* Avoid deadlock */
 			irq_spinlock_unlock(&thread->lock, false);
 			DEADLOCK_PROBE(p_wqlock, DEADLOCK_THRESHOLD);
-			/* Avoid deadlock */
 			goto grab_locks;
 		}
@@ -173,11 +177,9 @@
 		irq_spinlock_unlock(&wq->lock, false);
 	}
+	
 	irq_spinlock_unlock(&thread->lock, false);
 	
 	if (do_wakeup)
 		thread_ready(thread);
-	
-out:
-	irq_spinlock_unlock(&threads_lock, true);
 }
 
@@ -370,5 +372,4 @@
 		 * If the thread was already interrupted,
 		 * don't go to sleep at all.
-		 *
 		 */
 		if (THREAD->interrupted) {
@@ -381,5 +382,4 @@
 		 * Set context that will be restored if the sleep
 		 * of this thread is ever interrupted.
-		 *
 		 */
 		THREAD->sleep_interruptible = true;
