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

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

The Ultimate Solution To Illegal Virtual Aliases.
It is better to avoid them completely than to fight them.
Switch the sparc64 port to 16K pages. The TLBs and TSBs
continue to operate with 8K pages only. Page tables and
other generic parts operate with 16K pages.

Because the MMU doesn't support 16K directly, each 16K
page is emulated by a pair of 8K pages. With 16K pages,
illegal aliases cannot be created in 16K D-cache.

  • Property mode set to 100644
File size: 5.3 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#include <mm/frame.h>
58#include <ddi/ddi.h>
59
60/** Physical memory area of the real time clock. */
61static parea_t clock_parea;
62
63/* Pointers to public variables with time */
64struct ptime {
65 unative_t seconds1;
66 unative_t useconds;
67 unative_t seconds2;
68};
69struct ptime *public_time;
70/* Variable holding fragment of second, so that we would update
71 * seconds correctly
72 */
73static unative_t secfrag = 0;
74
75/** Initialize realtime clock counter
76 *
77 * The applications (and sometimes kernel) need to access accurate
78 * information about realtime data. We allocate 1 page with these
79 * data and update it periodically.
80 */
81void clock_counter_init(void)
82{
83 void *faddr;
84
85 faddr = frame_alloc(ONE_FRAME, FRAME_ATOMIC);
86 if (!faddr)
87 panic("Cannot allocate page for clock");
88
89 public_time = (struct ptime *) PA2KA(faddr);
90
91 /* TODO: We would need some arch dependent settings here */
92 public_time->seconds1 = 0;
93 public_time->seconds2 = 0;
94 public_time->useconds = 0;
95
96 clock_parea.pbase = (uintptr_t) faddr;
97 clock_parea.vbase = (uintptr_t) public_time;
98 clock_parea.frames = 1;
99 clock_parea.cacheable = true;
100 ddi_parea_register(&clock_parea);
101
102 /*
103 * Prepare information for the userspace so that it can successfully
104 * physmem_map() the clock_parea.
105 */
106 sysinfo_set_item_val("clock.cacheable", NULL, (unative_t) true);
107 sysinfo_set_item_val("clock.faddr", NULL, (unative_t) faddr);
108}
109
110
111/** Update public counters
112 *
113 * Update it only on first processor
114 * TODO: Do we really need so many write barriers?
115 */
116static void clock_update_counters(void)
117{
118 if (CPU->id == 0) {
119 secfrag += 1000000/HZ;
120 if (secfrag >= 1000000) {
121 secfrag -= 1000000;
122 public_time->seconds1++;
123 write_barrier();
124 public_time->useconds = secfrag;
125 write_barrier();
126 public_time->seconds2 = public_time->seconds1;
127 } else
128 public_time->useconds += 1000000/HZ;
129 }
130}
131
132/** Clock routine
133 *
134 * Clock routine executed from clock interrupt handler
135 * (assuming interrupts_disable()'d). Runs expired timeouts
136 * and preemptive scheduling.
137 *
138 */
139void clock(void)
140{
141 link_t *l;
142 timeout_t *h;
143 timeout_handler_t f;
144 void *arg;
145 count_t missed_clock_ticks = CPU->missed_clock_ticks;
146 int i;
147
148 /*
149 * To avoid lock ordering problems,
150 * run all expired timeouts as you visit them.
151 */
152 for (i = 0; i <= missed_clock_ticks; i++) {
153 clock_update_counters();
154 spinlock_lock(&CPU->timeoutlock);
155 while ((l = CPU->timeout_active_head.next) != &CPU->timeout_active_head) {
156 h = list_get_instance(l, timeout_t, link);
157 spinlock_lock(&h->lock);
158 if (h->ticks-- != 0) {
159 spinlock_unlock(&h->lock);
160 break;
161 }
162 list_remove(l);
163 f = h->handler;
164 arg = h->arg;
165 timeout_reinitialize(h);
166 spinlock_unlock(&h->lock);
167 spinlock_unlock(&CPU->timeoutlock);
168
169 f(arg);
170
171 spinlock_lock(&CPU->timeoutlock);
172 }
173 spinlock_unlock(&CPU->timeoutlock);
174 }
175 CPU->missed_clock_ticks = 0;
176
177 /*
178 * Do CPU usage accounting and find out whether to preempt THREAD.
179 */
180
181 if (THREAD) {
182 uint64_t ticks;
183
184 spinlock_lock(&CPU->lock);
185 CPU->needs_relink += 1 + missed_clock_ticks;
186 spinlock_unlock(&CPU->lock);
187
188 spinlock_lock(&THREAD->lock);
189 if ((ticks = THREAD->ticks)) {
190 if (ticks >= 1 + missed_clock_ticks)
191 THREAD->ticks -= 1 + missed_clock_ticks;
192 else
193 THREAD->ticks = 0;
194 }
195 spinlock_unlock(&THREAD->lock);
196
197 if (!ticks && !PREEMPTION_DISABLED) {
198 scheduler();
199 }
200 }
201
202}
203
204/** @}
205 */
Note: See TracBrowser for help on using the repository browser.