Index: uspace/app/tasks/tasks.c
===================================================================
--- uspace/app/tasks/tasks.c	(revision bbda5ab736025c36aa1ad4f3179adec67abe36e3)
+++ uspace/app/tasks/tasks.c	(revision e1b674201c97668fa9f3559cca094e0e1865629a)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Stanislav Kozina
+ * Copyright (c) 2010 Martin Decky
  * All rights reserved.
  *
@@ -43,4 +44,5 @@
 #include <malloc.h>
 #include <inttypes.h>
+#include <bool.h>
 #include <arg_parse.h>
 #include "func.h"
@@ -53,15 +55,4 @@
 #define PRINT_LOAD1(x)  ((x) >> 11)
 #define PRINT_LOAD2(x)  (((x) & 0x7ff) / 2)
-
-/** Thread states */
-//static const char *thread_states[] = {
-//	"Invalid",
-//	"Running",
-//	"Sleeping",
-//	"Ready",
-//	"Entering",
-//	"Exiting",
-//	"Lingering"
-//};
 
 static void list_tasks(void)
@@ -90,5 +81,5 @@
 			
 			printf("%8" PRIu64 "%8u %8" PRIu64"%c %12"
-			    PRIu64"%c %12" PRIu64"%c %s\n", ids[i], stats_task->threads,
+			    PRIu64 "%c %12" PRIu64 "%c %s\n", ids[i], stats_task->threads,
 			    virtmem, vmsuffix, ucycles, usuffix, kcycles, ksuffix,
 			    stats_task->name);
@@ -102,39 +93,48 @@
 }
 
-static void list_threads(task_id_t task_id)
-{
-	/* TODO:
-	size_t thread_count = THREAD_COUNT;
-	thread_info_t *threads = malloc(thread_count * sizeof(thread_info_t));
-	size_t result = get_task_threads(threads, sizeof(thread_info_t) * thread_count);
-
-	while (result > thread_count) {
-		thread_count *= 2;
-		threads = realloc(threads, thread_count * sizeof(thread_info_t));
-		result = get_task_threads(threads, sizeof(thread_info_t) * thread_count);
-	}
-
-	if (result == 0) {
-		printf("No task with given pid!\n");
-		exit(1);
-	}
-
-	size_t i;
+static void list_threads(task_id_t task_id, bool all)
+{
+	size_t count;
+	thread_id_t *ids =
+	    (thread_id_t *) stats_get_threads(&count);
+	
+	if (ids == NULL) {
+		fprintf(stderr, "%s: Unable to get threads\n", NAME);
+		return;
+	}
+	
 	printf("    ID    State  CPU   Prio    [k]uCycles    [k]kcycles   Cycle fault\n");
-	for (i = 0; i < result; ++i) {
-		if (threads[i].taskid != taskid) {
-			continue;
-		}
-		uint64_t ucycles, kcycles;
-		char usuffix, ksuffix;
-		order(threads[i].ucycles, &ucycles, &usuffix);
-		order(threads[i].kcycles, &kcycles, &ksuffix);
-		printf("%6llu %-8s %4u %6d %12llu%c %12llu%c\n", threads[i].tid,
-			thread_states[threads[i].state], threads[i].cpu,
-			threads[i].priority, ucycles, usuffix,
-			kcycles, ksuffix);
-	}
-
-	free(threads); */
+	size_t i;
+	for (i = 0; i < count; i++) {
+		stats_thread_t *stats_thread = stats_get_thread(ids[i]);
+		if (stats_thread != NULL) {
+			if ((all) || (stats_thread->task_id == task_id)) {
+				uint64_t ucycles, kcycles;
+				char usuffix, ksuffix;
+				
+				order(stats_thread->ucycles, &ucycles, &usuffix);
+				order(stats_thread->kcycles, &kcycles, &ksuffix);
+				
+				if (stats_thread->on_cpu) {
+					printf("%8" PRIu64 " %-8s %4u %6d %12"
+					    PRIu64"%c %12" PRIu64"%c\n", ids[i],
+					    thread_get_state(stats_thread->state),
+					    stats_thread->cpu, stats_thread->priority,
+					    ucycles, usuffix, kcycles, ksuffix);
+				} else {
+					printf("%8" PRIu64 " %-8s ---- %6d %12"
+					    PRIu64"%c %12" PRIu64"%c\n", ids[i],
+					    thread_get_state(stats_thread->state),
+					    stats_thread->priority,
+					    ucycles, usuffix, kcycles, ksuffix);
+				}
+			}
+			
+			free(stats_thread);
+		} else if (all)
+			printf("%8" PRIu64 "\n", ids[i]);
+	}
+	
+	free(ids);
 }
 
@@ -190,5 +190,5 @@
 {
 	printf(
-	    "Usage: tasks [-t task_id] [-l] [-c]\n" \
+	    "Usage: tasks [-t task_id] [-a] [-l] [-c]\n" \
 	    "\n" \
 	    "Options:\n" \
@@ -197,4 +197,8 @@
 	    "\t\tList threads of the given task\n" \
 	    "\n" \
+	    "\t-a\n" \
+	    "\t--all\n" \
+	    "\t\tList all threads\n" \
+	    "\n" \
 	    "\t-l\n" \
 	    "\t--load\n" \
@@ -217,8 +221,9 @@
 	bool toggle_tasks = true;
 	bool toggle_threads = false;
+	bool toggle_all = false;
 	bool toggle_load = false;
 	bool toggle_cpus = false;
 	
-	task_id_t task_id;
+	task_id_t task_id = 0;
 	
 	int i;
@@ -230,4 +235,12 @@
 			usage();
 			return 0;
+		}
+		
+		/* All threads */
+		if ((off = arg_parse_short_long(argv[i], "-a", "--all")) != -1) {
+			toggle_tasks = false;
+			toggle_threads = true;
+			toggle_all = true;
+			continue;
 		}
 		
@@ -268,5 +281,5 @@
 	
 	if (toggle_threads)
-		list_threads(task_id);
+		list_threads(task_id, toggle_all);
 	
 	if (toggle_load)
Index: uspace/lib/c/generic/stats.c
===================================================================
--- uspace/lib/c/generic/stats.c	(revision bbda5ab736025c36aa1ad4f3179adec67abe36e3)
+++ uspace/lib/c/generic/stats.c	(revision e1b674201c97668fa9f3559cca094e0e1865629a)
@@ -43,4 +43,17 @@
 #define SYSINFO_STATS_MAX_PATH  64
 
+/** Thread states
+ *
+ */
+static const char *thread_states[] = {
+	"Invalid",
+	"Running",
+	"Sleeping",
+	"Ready",
+	"Entering",
+	"Exiting",
+	"Lingering"
+};
+
 /** Get CPUs statistics
  *
@@ -125,4 +138,48 @@
 	
 	return stats_task;
+}
+
+/** Get thread IDs
+ *
+ * @param count Number of IDs returned.
+ *
+ * @return Array of IDs (thread_id_t).
+ *         If non-NULL then it should be eventually freed
+ *         by free().
+ *
+ */
+thread_id_t *stats_get_threads(size_t *count)
+{
+	size_t size = 0;
+	thread_id_t *ids =
+	    (thread_id_t *) sysinfo_get_data("system.threads", &size);
+	
+	assert((size % sizeof(thread_id_t)) == 0);
+	
+	*count = size / sizeof(thread_id_t);
+	return ids;
+}
+
+/** Get single thread statistics
+ *
+ * @param thread_id Thread ID we are interested in.
+ *
+ * @return Pointer to the stats_thread_t structure.
+ *         If non-NULL then it should be eventually freed
+ *         by free().
+ *
+ */
+stats_thread_t *stats_get_thread(thread_id_t thread_id)
+{
+	char name[SYSINFO_STATS_MAX_PATH];
+	snprintf(name, SYSINFO_STATS_MAX_PATH, "system.threads.%" PRIu64, thread_id);
+	
+	size_t size = 0;
+	stats_thread_t *stats_thread =
+	    (stats_thread_t *) sysinfo_get_data(name, &size);
+	
+	assert((size == sizeof(stats_thread_t)) || (size == 0));
+	
+	return stats_thread;
 }
 
@@ -188,4 +245,12 @@
 }
 
+const char *thread_get_state(state_t state)
+{
+	if (state <= Lingering)
+		return thread_states[state];
+	
+	return thread_states[Invalid];
+}
+
 /** @}
  */
Index: uspace/lib/c/include/stats.h
===================================================================
--- uspace/lib/c/include/stats.h	(revision bbda5ab736025c36aa1ad4f3179adec67abe36e3)
+++ uspace/lib/c/include/stats.h	(revision e1b674201c97668fa9f3559cca094e0e1865629a)
@@ -37,14 +37,22 @@
 
 #include <task.h>
+#include <thread.h>
+#include <stdint.h>
+#include <bool.h>
 #include <kernel/sysinfo/abi.h>
 
 extern stats_cpu_t *stats_get_cpus(size_t *);
 extern stats_physmem_t *stats_get_physmem(void);
-extern task_id_t *stats_get_tasks(size_t *);
-extern stats_task_t *stats_get_task(task_id_t);
 extern load_t *stats_get_load(size_t *);
 extern sysarg_t stats_get_uptime(void);
 
+extern task_id_t *stats_get_tasks(size_t *);
+extern stats_task_t *stats_get_task(task_id_t);
+
+extern thread_id_t *stats_get_threads(size_t *);
+extern stats_thread_t *stats_get_thread(thread_id_t);
+
 extern void stats_print_load_fragment(load_t, unsigned int);
+extern const char *thread_get_state(state_t);
 
 #endif
