Changes in kernel/generic/src/time/clock.c [25939997:6f7071b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/time/clock.c
r25939997 r6f7071b 1 1 /* 2 2 * Copyright (c) 2001-2004 Jakub Jermar 3 * Copyright (c) 2022 Jiří Zárevúcky4 3 * All rights reserved. 5 4 * … … 59 58 #include <ddi/ddi.h> 60 59 #include <arch/cycle.h> 61 #include <preemption.h>62 60 63 61 /* Pointer to variable with uptime */ … … 66 64 /** Physical memory area of the real time clock */ 67 65 static parea_t clock_parea; 66 67 /** Fragment of second 68 * 69 * For updating seconds correctly. 70 * 71 */ 72 static sysarg_t secfrag = 0; 68 73 69 74 /** Initialize realtime clock counter … … 104 109 * 105 110 * Update it only on first processor 106 */ 107 static void clock_update_counters(uint64_t current_tick) 111 * TODO: Do we really need so many write barriers? 112 * 113 */ 114 static void clock_update_counters(void) 108 115 { 109 116 if (CPU->id == 0) { 110 uint64_t usec = (1000000 / HZ) * current_tick;111 112 sysarg_t secs = usec /1000000;113 sysarg_t usecs = usec % 1000000;114 115 uptime->seconds1 = secs;116 write_barrier();117 uptime->useconds = usecs;118 write_barrier();119 uptime->seconds2 = secs;117 secfrag += 1000000 / HZ; 118 if (secfrag >= 1000000) { 119 secfrag -= 1000000; 120 uptime->seconds1++; 121 write_barrier(); 122 uptime->useconds = secfrag; 123 write_barrier(); 124 uptime->seconds2 = uptime->seconds1; 125 } else 126 uptime->useconds += 1000000 / HZ; 120 127 } 121 128 } … … 123 130 static void cpu_update_accounting(void) 124 131 { 125 // FIXME: get_cycle() is unimplemented on several platforms132 irq_spinlock_lock(&CPU->lock, false); 126 133 uint64_t now = get_cycle(); 127 atomic_time_increment(&CPU->busy_cycles, now - CPU_LOCAL->last_cycle); 128 CPU_LOCAL->last_cycle = now; 134 CPU->busy_cycles += now - CPU->last_cycle; 135 CPU->last_cycle = now; 136 irq_spinlock_unlock(&CPU->lock, false); 129 137 } 130 138 … … 138 146 void clock(void) 139 147 { 140 size_t missed_clock_ticks = CPU_LOCAL->missed_clock_ticks; 141 CPU_LOCAL->missed_clock_ticks = 0; 142 143 CPU_LOCAL->current_clock_tick += missed_clock_ticks + 1; 144 uint64_t current_clock_tick = CPU_LOCAL->current_clock_tick; 145 clock_update_counters(current_clock_tick); 148 size_t missed_clock_ticks = CPU->missed_clock_ticks; 146 149 147 150 /* Account CPU usage */ … … 153 156 * 154 157 */ 155 156 irq_spinlock_lock(&CPU->timeoutlock, false); 157 158 link_t *cur; 159 while ((cur = list_first(&CPU->timeout_active_list)) != NULL) { 160 timeout_t *timeout = list_get_instance(cur, timeout_t, link); 161 162 if (current_clock_tick <= timeout->deadline) { 163 break; 158 size_t i; 159 for (i = 0; i <= missed_clock_ticks; i++) { 160 /* Update counters and accounting */ 161 clock_update_counters(); 162 cpu_update_accounting(); 163 164 irq_spinlock_lock(&CPU->timeoutlock, false); 165 166 link_t *cur; 167 while ((cur = list_first(&CPU->timeout_active_list)) != NULL) { 168 timeout_t *timeout = list_get_instance(cur, timeout_t, 169 link); 170 171 irq_spinlock_lock(&timeout->lock, false); 172 if (timeout->ticks-- != 0) { 173 irq_spinlock_unlock(&timeout->lock, false); 174 break; 175 } 176 177 list_remove(cur); 178 timeout_handler_t handler = timeout->handler; 179 void *arg = timeout->arg; 180 timeout_reinitialize(timeout); 181 182 irq_spinlock_unlock(&timeout->lock, false); 183 irq_spinlock_unlock(&CPU->timeoutlock, false); 184 185 handler(arg); 186 187 irq_spinlock_lock(&CPU->timeoutlock, false); 164 188 } 165 189 166 list_remove(cur);167 timeout_handler_t handler = timeout->handler;168 void *arg = timeout->arg;169 atomic_bool *finished = &timeout->finished;170 171 190 irq_spinlock_unlock(&CPU->timeoutlock, false); 172 173 handler(arg);174 175 /* Signal that the handler is finished. */176 atomic_store_explicit(finished, true, memory_order_release);177 178 irq_spinlock_lock(&CPU->timeoutlock, false);179 191 } 180 181 irq_spinlock_unlock(&CPU->timeoutlock, false); 192 CPU->missed_clock_ticks = 0; 182 193 183 194 /* … … 187 198 188 199 if (THREAD) { 189 if (current_clock_tick >= CPU_LOCAL->preempt_deadline && PREEMPTION_ENABLED) { 190 thread_yield(); 200 uint64_t ticks; 201 202 irq_spinlock_lock(&CPU->lock, false); 203 CPU->needs_relink += 1 + missed_clock_ticks; 204 irq_spinlock_unlock(&CPU->lock, false); 205 206 irq_spinlock_lock(&THREAD->lock, false); 207 if ((ticks = THREAD->ticks)) { 208 if (ticks >= 1 + missed_clock_ticks) 209 THREAD->ticks -= 1 + missed_clock_ticks; 210 else 211 THREAD->ticks = 0; 212 } 213 irq_spinlock_unlock(&THREAD->lock, false); 214 215 if (ticks == 0 && PREEMPTION_ENABLED) { 216 scheduler(); 191 217 #ifdef CONFIG_UDEBUG 192 218 /*
Note:
See TracChangeset
for help on using the changeset viewer.