Index: kernel/generic/include/cpu.h
===================================================================
--- kernel/generic/include/cpu.h	(revision 5b19d806b26e4a267739e5ac28bbe9194259b766)
+++ kernel/generic/include/cpu.h	(revision e04b72d69126c4074644c19c920bf771d9c72a1e)
@@ -74,4 +74,7 @@
 	size_t missed_clock_ticks;
 
+	/** Can only be accessed when interrupts are disabled. */
+	uint64_t current_clock_tick;
+
 	/**
 	 * Processor cycle accounting.
Index: kernel/generic/include/time/timeout.h
===================================================================
--- kernel/generic/include/time/timeout.h	(revision 5b19d806b26e4a267739e5ac28bbe9194259b766)
+++ kernel/generic/include/time/timeout.h	(revision e04b72d69126c4074644c19c920bf771d9c72a1e)
@@ -43,10 +43,8 @@
 
 typedef struct {
-	IRQ_SPINLOCK_DECLARE(lock);
-
-	/** Link to the list of active timeouts on CURRENT->cpu */
+	/** Link to the list of active timeouts on timeout->cpu */
 	link_t link;
-	/** Timeout will be activated in this amount of clock() ticks. */
-	uint64_t ticks;
+	/** Timeout will be activated when current clock tick reaches this value. */
+	uint64_t deadline;
 	/** Function that will be called on timeout activation. */
 	timeout_handler_t handler;
@@ -61,5 +59,4 @@
 extern void timeout_init(void);
 extern void timeout_initialize(timeout_t *);
-extern void timeout_reinitialize(timeout_t *);
 extern void timeout_register(timeout_t *, uint64_t, timeout_handler_t, void *);
 extern bool timeout_unregister(timeout_t *);
Index: kernel/generic/src/time/clock.c
===================================================================
--- kernel/generic/src/time/clock.c	(revision 5b19d806b26e4a267739e5ac28bbe9194259b766)
+++ kernel/generic/src/time/clock.c	(revision e04b72d69126c4074644c19c920bf771d9c72a1e)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2022 Jiří Zárevúcky
  * All rights reserved.
  *
@@ -65,11 +66,4 @@
 static parea_t clock_parea;
 
-/** Fragment of second
- *
- * For updating  seconds correctly.
- *
- */
-static sysarg_t secfrag = 0;
-
 /** Initialize realtime clock counter
  *
@@ -109,20 +103,18 @@
  *
  * Update it only on first processor
- * TODO: Do we really need so many write barriers?
- *
- */
-static void clock_update_counters(void)
+ */
+static void clock_update_counters(uint64_t current_tick)
 {
 	if (CPU->id == 0) {
-		secfrag += 1000000 / HZ;
-		if (secfrag >= 1000000) {
-			secfrag -= 1000000;
-			uptime->seconds1++;
-			write_barrier();
-			uptime->useconds = secfrag;
-			write_barrier();
-			uptime->seconds2 = uptime->seconds1;
-		} else
-			uptime->useconds += 1000000 / HZ;
+		uint64_t usec = (1000000 / HZ) * current_tick;
+
+		sysarg_t secs = usec / 1000000;
+		sysarg_t usecs = usec % 1000000;
+
+		uptime->seconds1 = secs;
+		write_barrier();
+		uptime->useconds = usecs;
+		write_barrier();
+		uptime->seconds2 = secs;
 	}
 }
@@ -147,4 +139,9 @@
 {
 	size_t missed_clock_ticks = CPU->missed_clock_ticks;
+	CPU->missed_clock_ticks = 0;
+
+	CPU->current_clock_tick += missed_clock_ticks + 1;
+	uint64_t current_clock_tick = CPU->current_clock_tick;
+	clock_update_counters(current_clock_tick);
 
 	/* Account CPU usage */
@@ -156,39 +153,27 @@
 	 *
 	 */
-	size_t i;
-	for (i = 0; i <= missed_clock_ticks; i++) {
-		/* Update counters and accounting */
-		clock_update_counters();
-		cpu_update_accounting();
+
+	irq_spinlock_lock(&CPU->timeoutlock, false);
+
+	link_t *cur;
+	while ((cur = list_first(&CPU->timeout_active_list)) != NULL) {
+		timeout_t *timeout = list_get_instance(cur, timeout_t, link);
+
+		if (current_clock_tick <= timeout->deadline) {
+			break;
+		}
+
+		list_remove(cur);
+		timeout_handler_t handler = timeout->handler;
+		void *arg = timeout->arg;
+
+		irq_spinlock_unlock(&CPU->timeoutlock, false);
+
+		handler(arg);
 
 		irq_spinlock_lock(&CPU->timeoutlock, false);
-
-		link_t *cur;
-		while ((cur = list_first(&CPU->timeout_active_list)) != NULL) {
-			timeout_t *timeout = list_get_instance(cur, timeout_t,
-			    link);
-
-			irq_spinlock_lock(&timeout->lock, false);
-			if (timeout->ticks-- != 0) {
-				irq_spinlock_unlock(&timeout->lock, false);
-				break;
-			}
-
-			list_remove(cur);
-			timeout_handler_t handler = timeout->handler;
-			void *arg = timeout->arg;
-			timeout_reinitialize(timeout);
-
-			irq_spinlock_unlock(&timeout->lock, false);
-			irq_spinlock_unlock(&CPU->timeoutlock, false);
-
-			handler(arg);
-
-			irq_spinlock_lock(&CPU->timeoutlock, false);
-		}
-
-		irq_spinlock_unlock(&CPU->timeoutlock, false);
 	}
-	CPU->missed_clock_ticks = 0;
+
+	irq_spinlock_unlock(&CPU->timeoutlock, false);
 
 	/*
Index: kernel/generic/src/time/timeout.c
===================================================================
--- kernel/generic/src/time/timeout.c	(revision 5b19d806b26e4a267739e5ac28bbe9194259b766)
+++ kernel/generic/src/time/timeout.c	(revision e04b72d69126c4074644c19c920bf771d9c72a1e)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2022 Jiří Zárevúcky
  * All rights reserved.
  *
@@ -57,20 +58,4 @@
 }
 
-/** Reinitialize timeout
- *
- * Initialize all members except the lock.
- *
- * @param timeout Timeout to be initialized.
- *
- */
-void timeout_reinitialize(timeout_t *timeout)
-{
-	timeout->cpu = NULL;
-	timeout->ticks = 0;
-	timeout->handler = NULL;
-	timeout->arg = NULL;
-	link_initialize(&timeout->link);
-}
-
 /** Initialize timeout
  *
@@ -82,6 +67,6 @@
 void timeout_initialize(timeout_t *timeout)
 {
-	irq_spinlock_initialize(&timeout->lock, "timeout_t_lock");
-	timeout_reinitialize(timeout);
+	link_initialize(&timeout->link);
+	timeout->cpu = NULL;
 }
 
@@ -102,58 +87,28 @@
 {
 	irq_spinlock_lock(&CPU->timeoutlock, true);
-	irq_spinlock_lock(&timeout->lock, false);
 
-	if (timeout->cpu)
-		panic("Unexpected: timeout->cpu != 0.");
+	assert(!link_in_use(&timeout->link));
 
 	timeout->cpu = CPU;
-	timeout->ticks = us2ticks(time);
-
+	timeout->deadline = CPU->current_clock_tick + us2ticks(time);
 	timeout->handler = handler;
 	timeout->arg = arg;
 
-	/*
-	 * Insert timeout into the active timeouts list according to timeout->ticks.
-	 */
-	uint64_t sum = 0;
-	timeout_t *target = NULL;
-	link_t *cur, *prev;
-	prev = NULL;
-	for (cur = list_first(&CPU->timeout_active_list);
-	    cur != NULL; cur = list_next(cur, &CPU->timeout_active_list)) {
-		target = list_get_instance(cur, timeout_t, link);
-		irq_spinlock_lock(&target->lock, false);
+	/* Insert timeout into the active timeouts list according to timeout->deadline. */
 
-		if (timeout->ticks < sum + target->ticks) {
-			irq_spinlock_unlock(&target->lock, false);
-			break;
+	link_t *last = list_last(&CPU->timeout_active_list);
+	if (last == NULL || timeout->deadline >= list_get_instance(last, timeout_t, link)->deadline) {
+		list_append(&timeout->link, &CPU->timeout_active_list);
+	} else {
+		for (link_t *cur = list_first(&CPU->timeout_active_list); cur != NULL;
+		    cur = list_next(cur, &CPU->timeout_active_list)) {
+
+			if (timeout->deadline < list_get_instance(cur, timeout_t, link)->deadline) {
+				list_insert_before(&timeout->link, cur);
+				break;
+			}
 		}
-
-		sum += target->ticks;
-		irq_spinlock_unlock(&target->lock, false);
-		prev = cur;
 	}
 
-	if (prev == NULL)
-		list_prepend(&timeout->link, &CPU->timeout_active_list);
-	else
-		list_insert_after(&timeout->link, prev);
-
-	/*
-	 * Adjust timeout->ticks according to ticks
-	 * accumulated in target's predecessors.
-	 */
-	timeout->ticks -= sum;
-
-	/*
-	 * Decrease ticks of timeout's immediate succesor by timeout->ticks.
-	 */
-	if (cur != NULL) {
-		irq_spinlock_lock(&target->lock, false);
-		target->ticks -= timeout->ticks;
-		irq_spinlock_unlock(&target->lock, false);
-	}
-
-	irq_spinlock_unlock(&timeout->lock, false);
 	irq_spinlock_unlock(&CPU->timeoutlock, true);
 }
@@ -170,40 +125,15 @@
 bool timeout_unregister(timeout_t *timeout)
 {
-	DEADLOCK_PROBE_INIT(p_tolock);
+	assert(timeout->cpu);
 
-grab_locks:
-	irq_spinlock_lock(&timeout->lock, true);
-	if (!timeout->cpu) {
-		irq_spinlock_unlock(&timeout->lock, true);
-		return false;
+	irq_spinlock_lock(&timeout->cpu->timeoutlock, true);
+
+	bool success = link_in_use(&timeout->link);
+	if (success) {
+		list_remove(&timeout->link);
 	}
 
-	if (!irq_spinlock_trylock(&timeout->cpu->timeoutlock)) {
-		irq_spinlock_unlock(&timeout->lock, true);
-		DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD);
-		goto grab_locks;
-	}
-
-	/*
-	 * Now we know for sure that timeout hasn't been activated yet
-	 * and is lurking in timeout->cpu->timeout_active_list.
-	 */
-
-	link_t *cur = list_next(&timeout->link,
-	    &timeout->cpu->timeout_active_list);
-	if (cur != NULL) {
-		timeout_t *tmp = list_get_instance(cur, timeout_t, link);
-		irq_spinlock_lock(&tmp->lock, false);
-		tmp->ticks += timeout->ticks;
-		irq_spinlock_unlock(&tmp->lock, false);
-	}
-
-	list_remove(&timeout->link);
-	irq_spinlock_unlock(&timeout->cpu->timeoutlock, false);
-
-	timeout_reinitialize(timeout);
-	irq_spinlock_unlock(&timeout->lock, true);
-
-	return true;
+	irq_spinlock_unlock(&timeout->cpu->timeoutlock, true);
+	return success;
 }
 
