source: mainline/generic/src/time/clock.c@ cf84d72a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cf84d72a was 1bb2e7a, checked in by Jakub Jermar <jakub@…>, 20 years ago

Updates in Doxygen-style comments.
Make architecture specific modules appear conditionally in the documentation.
Add time management module.
Improve names of other modules and sort module order
to be more like in the design documentation.

  • Property mode set to 100644
File size: 4.9 KB
Line 
1/*
2 * Copyright (C) 2001-2004 Jakub Jermar
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
29/** @addtogroup time
30 * @{
31 */
32
33/**
34 * @file
35 * @brief High-level clock interrupt handler.
36 *
37 * This file contains the clock() function which is the source
38 * of preemption. It is also responsible for executing expired
39 * timeouts.
40 */
41
42#include <time/clock.h>
43#include <time/timeout.h>
44#include <arch/types.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>
52#include <adt/list.h>
53#include <atomic.h>
54#include <proc/thread.h>
55#include <sysinfo/sysinfo.h>
56#include <arch/barrier.h>
57
58/* Pointers to public variables with time */
59struct ptime {
60 __native seconds1;
61 __native useconds;
62 __native seconds2;
63};
64struct ptime *public_time;
65/* Variable holding fragment of second, so that we would update
66 * seconds correctly
67 */
68static __native secfrag = 0;
69
70/** Initialize realtime clock counter
71 *
72 * The applications (and sometimes kernel) need to access accurate
73 * information about realtime data. We allocate 1 page with these
74 * data and update it periodically.
75 *
76 *
77 */
78void clock_counter_init(void)
79{
80 void *faddr;
81
82 faddr = (void *)PFN2ADDR(frame_alloc(0, FRAME_ATOMIC));
83 if (!faddr)
84 panic("Cannot allocate page for clock");
85
86 public_time = (struct ptime *)PA2KA(faddr);
87
88 /* TODO: We would need some arch dependent settings here */
89 public_time->seconds1 = 0;
90 public_time->seconds2 = 0;
91 public_time->useconds = 0;
92
93 sysinfo_set_item_val("clock.faddr", NULL, (__native)faddr);
94}
95
96
97/** Update public counters
98 *
99 * Update it only on first processor
100 * TODO: Do we really need so many write barriers?
101 */
102static void clock_update_counters(void)
103{
104 if (CPU->id == 0) {
105 secfrag += 1000000/HZ;
106 if (secfrag >= 1000000) {
107 secfrag -= 1000000;
108 public_time->seconds1++;
109 write_barrier();
110 public_time->useconds = secfrag;
111 write_barrier();
112 public_time->seconds2 = public_time->seconds1;
113 } else
114 public_time->useconds += 1000000/HZ;
115 }
116}
117
118/** Clock routine
119 *
120 * Clock routine executed from clock interrupt handler
121 * (assuming interrupts_disable()'d). Runs expired timeouts
122 * and preemptive scheduling.
123 *
124 */
125void clock(void)
126{
127 link_t *l;
128 timeout_t *h;
129 timeout_handler_t f;
130 void *arg;
131 count_t missed_clock_ticks = CPU->missed_clock_ticks;
132 int i;
133
134 /*
135 * To avoid lock ordering problems,
136 * run all expired timeouts as you visit them.
137 */
138 for (i = 0; i <= missed_clock_ticks; i++) {
139 clock_update_counters();
140 spinlock_lock(&CPU->timeoutlock);
141 while ((l = CPU->timeout_active_head.next) != &CPU->timeout_active_head) {
142 h = list_get_instance(l, timeout_t, link);
143 spinlock_lock(&h->lock);
144 if (h->ticks-- != 0) {
145 spinlock_unlock(&h->lock);
146 break;
147 }
148 list_remove(l);
149 f = h->handler;
150 arg = h->arg;
151 timeout_reinitialize(h);
152 spinlock_unlock(&h->lock);
153 spinlock_unlock(&CPU->timeoutlock);
154
155 f(arg);
156
157 spinlock_lock(&CPU->timeoutlock);
158 }
159 spinlock_unlock(&CPU->timeoutlock);
160 }
161 CPU->missed_clock_ticks = 0;
162
163 /*
164 * Do CPU usage accounting and find out whether to preempt THREAD.
165 */
166
167 if (THREAD) {
168 __u64 ticks;
169
170 spinlock_lock(&CPU->lock);
171 CPU->needs_relink += 1 + missed_clock_ticks;
172 spinlock_unlock(&CPU->lock);
173
174 spinlock_lock(&THREAD->lock);
175 if ((ticks = THREAD->ticks)) {
176 if (ticks >= 1 + missed_clock_ticks)
177 THREAD->ticks -= 1 + missed_clock_ticks;
178 else
179 THREAD->ticks = 0;
180 }
181 spinlock_unlock(&THREAD->lock);
182
183 if (!ticks && !PREEMPTION_DISABLED) {
184 scheduler();
185 }
186 }
187
188}
189
190/** @}
191 */
192
Note: See TracBrowser for help on using the repository browser.