Index: kernel/generic/include/proc/thread.h
===================================================================
--- kernel/generic/include/proc/thread.h	(revision 11909ce3e9ef283a8861cf0ab4dac3ee0e36f170)
+++ kernel/generic/include/proc/thread.h	(revision 3fa4e22a35608a0c87e62b58f4585811b6d8533e)
@@ -95,4 +95,8 @@
 	waitq_t join_wq;
 
+	/** Thread accounting. */
+	atomic_time_stat_t ucycles;
+	atomic_time_stat_t kcycles;
+
 	/** Lock protecting thread structure.
 	 *
@@ -101,5 +105,28 @@
 	IRQ_SPINLOCK_DECLARE(lock);
 
-	char name[THREAD_NAME_BUFLEN];
+	/** Architecture-specific data. */
+	thread_arch_t arch;
+
+#ifdef CONFIG_UDEBUG
+	/**
+	 * If true, the scheduler will print a stack trace
+	 * to the kernel console upon scheduling this thread.
+	 */
+	atomic_int_fast8_t btrace;
+
+	/** Debugging stuff */
+	udebug_thread_t udebug;
+#endif /* CONFIG_UDEBUG */
+
+	/*
+	 * Immutable fields.
+	 *
+	 * These fields are only modified during initialization, and are not
+	 * changed at any time between initialization and destruction.
+	 * Can be accessed without synchronization in most places.
+	 */
+
+	/** Thread ID. */
+	thread_id_t tid;
 
 	/** Function implementing the thread. */
@@ -108,4 +135,32 @@
 	void *thread_arg;
 
+	char name[THREAD_NAME_BUFLEN];
+
+	/** Thread is executed in user space. */
+	bool uspace;
+
+	/** Thread doesn't affect accumulated accounting. */
+	bool uncounted;
+
+	/** Containing task. */
+	task_t *task;
+
+	/** Thread's kernel stack. */
+	uint8_t *kstack;
+
+	/*
+	 * Local fields.
+	 *
+	 * These fields can be safely accessed from code that _controls execution_
+	 * of this thread. Code controls execution of a thread if either:
+	 *  - it runs in the context of said thread AND interrupts are disabled
+	 *    (interrupts can and will access these fields)
+	 *  - the thread is not running, and the code accessing it can legally
+	 *    add/remove the thread to/from a runqueue, i.e., either:
+	 *    - it is allowed to enqueue thread in a new runqueue
+	 *    - it holds the lock to the runqueue containing the thread
+	 *
+	 */
+
 	/**
 	 * From here, the stored context is restored
@@ -114,4 +169,6 @@
 	context_t saved_context;
 
+	// TODO: we only need one of the two bools below
+
 	/**
 	 * True if this thread is executing copy_from_uspace().
@@ -126,4 +183,9 @@
 	bool in_copy_to_uspace;
 
+	/*
+	 * FPU context is a special case. If lazy FPU switching is disabled,
+	 * it acts as a regular local field. However, if lazy switching is enabled,
+	 * the context is synchronized via CPU->fpu_lock
+	 */
 #ifdef CONFIG_FPU
 	fpu_context_t fpu_context;
@@ -134,4 +196,7 @@
 	unsigned int nomigrate;
 
+	/** Thread was migrated to another CPU and has not run yet. */
+	bool stolen;
+
 	/** Thread state. */
 	atomic_int_fast32_t state;
@@ -139,40 +204,10 @@
 	/** Thread CPU. */
 	_Atomic(cpu_t *) cpu;
-	/** Containing task. */
-	task_t *task;
-	/** Thread was migrated to another CPU and has not run yet. */
-	bool stolen;
-	/** Thread is executed in user space. */
-	bool uspace;
-
-	/** Thread accounting. */
-	atomic_time_stat_t ucycles;
-	atomic_time_stat_t kcycles;
+
+	/** Thread's priority. Implemented as index to CPU->rq */
+	atomic_int_fast32_t priority;
+
 	/** Last sampled cycle. */
 	uint64_t last_cycle;
-	/** Thread doesn't affect accumulated accounting. */
-	bool uncounted;
-
-	/** Thread's priority. Implemented as index to CPU->rq */
-	atomic_int_fast32_t priority;
-	/** Thread ID. */
-	thread_id_t tid;
-
-	/** Architecture-specific data. */
-	thread_arch_t arch;
-
-	/** Thread's kernel stack. */
-	uint8_t *kstack;
-
-#ifdef CONFIG_UDEBUG
-	/**
-	 * If true, the scheduler will print a stack trace
-	 * to the kernel console upon scheduling this thread.
-	 */
-	atomic_int_fast8_t btrace;
-
-	/** Debugging stuff */
-	udebug_thread_t udebug;
-#endif /* CONFIG_UDEBUG */
 } thread_t;
 
