source: mainline/kernel/generic/src/time/clock.c@ da1bafb

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since da1bafb was da1bafb, checked in by Martin Decky <martin@…>, 15 years ago

major code revision

  • replace spinlocks taken with interrupts disabled with irq_spinlocks
  • change spacing (not indendation) to be tab-size independent
  • use unsigned integer types where appropriate (especially bit flags)
  • visual separation
  • remove argument names in function prototypes
  • string changes
  • correct some formating directives
  • replace various cryptic single-character variables (t, a, m, c, b, etc.) with proper identifiers (thread, task, timeout, as, itm, itc, etc.)
  • unify some assembler constructs
  • unused page table levels are now optimized out in compile time
  • replace several ints (with boolean semantics) with bools
  • use specifically sized types instead of generic types where appropriate (size_t, uint32_t, btree_key_t)
  • improve comments
  • split asserts with conjuction into multiple independent asserts
  • Property mode set to 100644
File size: 5.7 KB
RevLine 
[f761f1eb]1/*
[df4ed85]2 * Copyright (c) 2001-2004 Jakub Jermar
[f761f1eb]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[1bb2e7a]29/** @addtogroup time
[b45c443]30 * @{
31 */
32
[cf26ba9]33/**
[b45c443]34 * @file
[da1bafb]35 * @brief High-level clock interrupt handler.
[cf26ba9]36 *
37 * This file contains the clock() function which is the source
38 * of preemption. It is also responsible for executing expired
39 * timeouts.
[da1bafb]40 *
[cf26ba9]41 */
[da1bafb]42
[f761f1eb]43#include <time/clock.h>
44#include <time/timeout.h>
45#include <config.h>
46#include <synch/spinlock.h>
47#include <synch/waitq.h>
48#include <func.h>
49#include <proc/scheduler.h>
50#include <cpu.h>
51#include <arch.h>
[5c9a08b]52#include <adt/list.h>
[23684b7]53#include <atomic.h>
[1084a784]54#include <proc/thread.h>
[d6e5cbc]55#include <sysinfo/sysinfo.h>
56#include <arch/barrier.h>
[f8ddd17]57#include <mm/frame.h>
58#include <ddi/ddi.h>
59
[4b662f8c]60/* Pointer to variable with uptime */
61uptime_t *uptime;
62
63/** Physical memory area of the real time clock */
[f8ddd17]64static parea_t clock_parea;
[d6e5cbc]65
[da1bafb]66/** Fragment of second
67 *
68 * For updating seconds correctly.
69 *
[d6e5cbc]70 */
[7f1c620]71static unative_t secfrag = 0;
[d6e5cbc]72
73/** Initialize realtime clock counter
74 *
75 * The applications (and sometimes kernel) need to access accurate
76 * information about realtime data. We allocate 1 page with these
77 * data and update it periodically.
[da1bafb]78 *
[d6e5cbc]79 */
80void clock_counter_init(void)
81{
[da1bafb]82 void *faddr = frame_alloc(ONE_FRAME, FRAME_ATOMIC);
[d6e5cbc]83 if (!faddr)
[f651e80]84 panic("Cannot allocate page for clock.");
[d6e5cbc]85
[4b662f8c]86 uptime = (uptime_t *) PA2KA(faddr);
87
88 uptime->seconds1 = 0;
89 uptime->seconds2 = 0;
[9dae191e]90 uptime->useconds = 0;
[da1bafb]91
[f8ddd17]92 clock_parea.pbase = (uintptr_t) faddr;
93 clock_parea.frames = 1;
94 ddi_parea_register(&clock_parea);
[da1bafb]95
[f8ddd17]96 /*
97 * Prepare information for the userspace so that it can successfully
98 * physmem_map() the clock_parea.
[da1bafb]99 *
[f8ddd17]100 */
101 sysinfo_set_item_val("clock.cacheable", NULL, (unative_t) true);
102 sysinfo_set_item_val("clock.faddr", NULL, (unative_t) faddr);
[d6e5cbc]103}
104
105/** Update public counters
106 *
107 * Update it only on first processor
[da1bafb]108 * TODO: Do we really need so many write barriers?
109 *
[d6e5cbc]110 */
111static void clock_update_counters(void)
112{
113 if (CPU->id == 0) {
[4b662f8c]114 secfrag += 1000000 / HZ;
[d6e5cbc]115 if (secfrag >= 1000000) {
[fd8302d]116 secfrag -= 1000000;
[4b662f8c]117 uptime->seconds1++;
[d6e5cbc]118 write_barrier();
[4b662f8c]119 uptime->useconds = secfrag;
[fd8302d]120 write_barrier();
[4b662f8c]121 uptime->seconds2 = uptime->seconds1;
[d6e5cbc]122 } else
[4b662f8c]123 uptime->useconds += 1000000 / HZ;
[d6e5cbc]124 }
125}
[f761f1eb]126
[70527f1]127/** Clock routine
128 *
129 * Clock routine executed from clock interrupt handler
[22f7769]130 * (assuming interrupts_disable()'d). Runs expired timeouts
[70527f1]131 * and preemptive scheduling.
132 *
[f761f1eb]133 */
134void clock(void)
135{
[98000fb]136 size_t missed_clock_ticks = CPU->missed_clock_ticks;
[da1bafb]137
[e257ae3]138 /* Account lost ticks to CPU usage */
[da1bafb]139 if (CPU->idle)
[b8f7ea78]140 CPU->idle_ticks += missed_clock_ticks + 1;
[da1bafb]141 else
[e257ae3]142 CPU->busy_ticks += missed_clock_ticks + 1;
[da1bafb]143
[e257ae3]144 CPU->idle = false;
[da1bafb]145
[f761f1eb]146 /*
147 * To avoid lock ordering problems,
148 * run all expired timeouts as you visit them.
[da1bafb]149 *
[f761f1eb]150 */
[da1bafb]151 size_t i;
[8cf8ee6]152 for (i = 0; i <= missed_clock_ticks; i++) {
[d6e5cbc]153 clock_update_counters();
[da1bafb]154 irq_spinlock_lock(&CPU->timeoutlock, false);
155
156 link_t *cur;
157 while ((cur = CPU->timeout_active_head.next) != &CPU->timeout_active_head) {
158 timeout_t *timeout = list_get_instance(cur, timeout_t, link);
159
160 irq_spinlock_lock(&timeout->lock, false);
161 if (timeout->ticks-- != 0) {
162 irq_spinlock_unlock(&timeout->lock, false);
[c93e805]163 break;
164 }
[da1bafb]165
166 list_remove(cur);
167 timeout_handler_t handler = timeout->handler;
168 void *arg = timeout->arg;
169 timeout_reinitialize(timeout);
170
171 irq_spinlock_unlock(&timeout->lock, false);
172 irq_spinlock_unlock(&CPU->timeoutlock, false);
173
174 handler(arg);
175
176 irq_spinlock_lock(&CPU->timeoutlock, false);
[c93e805]177 }
[da1bafb]178
179 irq_spinlock_unlock(&CPU->timeoutlock, false);
[f761f1eb]180 }
[c93e805]181 CPU->missed_clock_ticks = 0;
[da1bafb]182
[f761f1eb]183 /*
[43114c5]184 * Do CPU usage accounting and find out whether to preempt THREAD.
[da1bafb]185 *
[f761f1eb]186 */
[da1bafb]187
[43114c5]188 if (THREAD) {
[7f1c620]189 uint64_t ticks;
[dbe9ff0]190
[da1bafb]191 irq_spinlock_lock(&CPU->lock, false);
[8cf8ee6]192 CPU->needs_relink += 1 + missed_clock_ticks;
[da1bafb]193 irq_spinlock_unlock(&CPU->lock, false);
194
195 irq_spinlock_lock(&THREAD->lock, false);
[8cf8ee6]196 if ((ticks = THREAD->ticks)) {
197 if (ticks >= 1 + missed_clock_ticks)
198 THREAD->ticks -= 1 + missed_clock_ticks;
199 else
200 THREAD->ticks = 0;
201 }
[da1bafb]202 irq_spinlock_unlock(&THREAD->lock, false);
[dbe9ff0]203
[2e4e706]204 if ((!ticks) && (!PREEMPTION_DISABLED)) {
[f761f1eb]205 scheduler();
[3ff2b54]206#ifdef CONFIG_UDEBUG
207 /*
208 * Give udebug chance to stop the thread
[5d9430d7]209 * before it begins executing userspace code.
[3ff2b54]210 */
[da1bafb]211 istate_t *istate = THREAD->udebug.uspace_state;
212 if ((istate) && (istate_from_uspace(istate)))
[3ff2b54]213 udebug_before_thread_runs();
214#endif
[f761f1eb]215 }
216 }
217}
[b45c443]218
[1bb2e7a]219/** @}
[b45c443]220 */
Note: See TracBrowser for help on using the repository browser.