1 /* This file contains the architecture-independent clock functionality, which
2 * handles time related functions. Important events that are handled here
3 * include setting and monitoring alarm timers and deciding when to
4 * (re)schedule processes. System services can access its services through
5 * system calls, such as sys_setalarm().
8 * Aug 18, 2006 removed direct hardware access etc, MinixPPC (Ingmar Alting)
9 * Oct 08, 2005 reordering and comment editing (A. S. Woodhull)
10 * Mar 18, 2004 clock interface moved to SYSTEM task (Jorrit N. Herder)
11 * Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
12 * Sep 24, 2004 redesigned alarm timers (Jorrit N. Herder)
15 #include <minix/endpoint.h>
26 /* Function prototype for PRIVATE functions.
28 static void load_update(void);
30 /* The CLOCK's timers queue. The functions in <minix/timers.h> operate on this.
31 * Each system process possesses a single synchronous alarm timer. If other
32 * kernel parts want to use additional timers, they must declare their own
33 * persistent (static) timer structure, which can be passed to the clock
34 * via (re)set_kernel_timer().
35 * When a timer expires its watchdog function is run by the CLOCK task.
37 static minix_timer_t
*clock_timers
; /* queue of CLOCK timers */
39 /* Number of ticks to adjust realtime by. A negative value implies slowing
40 * down realtime, a positive value implies speeding it up.
42 static int32_t adjtime_delta
= 0;
45 * Initialize the clock variables.
52 /* Initialize clock information structure. */
53 memset(&kclockinfo
, 0, sizeof(kclockinfo
));
55 /* Get clock tick frequency. */
56 value
= env_get("hz");
58 kclockinfo
.hz
= atoi(value
);
59 if (value
== NULL
|| kclockinfo
.hz
< 2 || kclockinfo
.hz
> 50000)
60 kclockinfo
.hz
= DEFAULT_HZ
;
62 /* Load average data initialization. */
63 memset(&kloadinfo
, 0, sizeof(kloadinfo
));
67 * The boot processor's timer interrupt handler. In addition to non-boot cpus
68 * it keeps real time and notifies the clock task if need be.
70 int timer_int_handler(void)
72 /* Update user and system accounting times. Charge the current process
73 * for user time. If the current process is not billable, that is, if a
74 * non-user process is running, charge the billable process for system
75 * time as well. Thus the unbillable process' user time is the billable
79 struct proc
* p
, * billp
;
81 /* FIXME watchdog for slave cpus! */
84 * we need to know whether local timer ticks are happening or whether
85 * the kernel is locked up. We don't care about overflows as we only
86 * need to know that it's still ticking or not
88 watchdog_local_timer_ticks
++;
91 if (cpu_is_bsp(cpuid
)) {
94 /* if adjtime_delta has ticks remaining, apply one to realtime.
95 * limit changes to every other interrupt.
97 if (adjtime_delta
!= 0 && kclockinfo
.uptime
& 0x1) {
98 /* go forward or stay behind */
99 kclockinfo
.realtime
+= (adjtime_delta
> 0) ? 2 : 0;
100 adjtime_delta
+= (adjtime_delta
> 0) ? -1 : +1;
102 kclockinfo
.realtime
++;
106 /* Update user and system accounting times. Charge the current process
107 * for user time. If the current process is not billable, that is, if a
108 * non-user process is running, charge the billable process for system
109 * time as well. Thus the unbillable process' user time is the billable
110 * user's system time.
113 p
= get_cpulocal_var(proc_ptr
);
114 billp
= get_cpulocal_var(bill_ptr
);
118 if (! (priv(p
)->s_flags
& BILLABLE
)) {
122 /* Decrement virtual timers, if applicable. We decrement both the
123 * virtual and the profile timer of the current process, and if the
124 * current process is not billable, the timer of the billed process as
125 * well. If any of the timers expire, do_clocktick() will send out
128 if ((p
->p_misc_flags
& MF_VIRT_TIMER
) && (p
->p_virt_left
> 0)) {
131 if ((p
->p_misc_flags
& MF_PROF_TIMER
) && (p
->p_prof_left
> 0)) {
134 if (! (priv(p
)->s_flags
& BILLABLE
) &&
135 (billp
->p_misc_flags
& MF_PROF_TIMER
) &&
136 (billp
->p_prof_left
> 0)) {
137 billp
->p_prof_left
--;
141 * Check if a process-virtual timer expired. Check current process, but
142 * also bill_ptr - one process's user time is another's system time, and
143 * the profile timer decreases for both!
150 /* Update load average. */
153 if (cpu_is_bsp(cpuid
)) {
155 * If a timer expired, notify the clock task. Keep in mind
156 * that clock tick values may overflow, so we must only look at
157 * relative differences, and only if there are timers at all.
159 if (clock_timers
!= NULL
&&
160 tmr_has_expired(clock_timers
, kclockinfo
.uptime
))
161 tmrs_exptimers(&clock_timers
, kclockinfo
.uptime
, NULL
);
164 if (kinfo
.do_serial_debug
)
170 arch_timer_int_handler();
172 return(1); /* reenable interrupts */
175 /*===========================================================================*
177 *===========================================================================*/
178 clock_t get_realtime(void)
180 /* Get and return the current wall time in ticks since boot. */
181 return(kclockinfo
.realtime
);
184 /*===========================================================================*
186 *===========================================================================*/
187 void set_realtime(clock_t newrealtime
)
189 kclockinfo
.realtime
= newrealtime
;
192 /*===========================================================================*
193 * set_adjtime_delta *
194 *===========================================================================*/
195 void set_adjtime_delta(int32_t ticks
)
197 adjtime_delta
= ticks
;
200 /*===========================================================================*
202 *===========================================================================*/
203 clock_t get_monotonic(void)
205 /* Get and return the number of ticks since boot. */
206 return(kclockinfo
.uptime
);
209 /*===========================================================================*
211 *===========================================================================*/
212 void set_boottime(time_t newboottime
)
214 kclockinfo
.boottime
= newboottime
;
217 /*===========================================================================*
219 *===========================================================================*/
220 time_t get_boottime(void)
222 /* Get and return the number of seconds since the UNIX epoch. */
223 return(kclockinfo
.boottime
);
226 /*===========================================================================*
228 *===========================================================================*/
229 void set_kernel_timer(
230 minix_timer_t
*tp
, /* pointer to timer structure */
231 clock_t exp_time
, /* expiration monotonic time */
232 tmr_func_t watchdog
, /* watchdog to be called */
233 int arg
/* argument for watchdog function */
236 /* Insert the new timer in the active timers list. Always update the
237 * next timeout time by setting it to the front of the active list.
239 (void)tmrs_settimer(&clock_timers
, tp
, exp_time
, watchdog
, arg
, NULL
, NULL
);
242 /*===========================================================================*
243 * reset_kernel_timer *
244 *===========================================================================*/
245 void reset_kernel_timer(
246 minix_timer_t
*tp
/* pointer to timer structure */
249 /* The timer pointed to by 'tp' is no longer needed. Remove it from both the
250 * active and expired lists. Always update the next timeout time by setting
251 * it to the front of the active list.
254 (void)tmrs_clrtimer(&clock_timers
, tp
, NULL
, NULL
);
257 /*===========================================================================*
259 *===========================================================================*/
260 static void load_update(void)
265 struct proc
**rdy_head
;
267 /* Load average data is stored as a list of numbers in a circular
268 * buffer. Each slot accumulates _LOAD_UNIT_SECS of samples of
269 * the number of runnable processes. Computations can then
270 * be made of the load average over variable periods, in the
271 * user library (see getloadavg(3)).
273 slot
= (kclockinfo
.uptime
/ system_hz
/ _LOAD_UNIT_SECS
) %
275 if(slot
!= kloadinfo
.proc_last_slot
) {
276 kloadinfo
.proc_load_history
[slot
] = 0;
277 kloadinfo
.proc_last_slot
= slot
;
280 rdy_head
= get_cpulocal_var(run_q_head
);
281 /* Cumulation. How many processes are ready now? */
282 for(q
= 0; q
< NR_SCHED_QUEUES
; q
++) {
283 for(p
= rdy_head
[q
]; p
!= NULL
; p
= p
->p_nextready
) {
288 kloadinfo
.proc_load_history
[slot
] += enqueued
;
290 /* Up-to-dateness. */
291 kloadinfo
.last_clock
= kclockinfo
.uptime
;
294 int boot_cpu_init_timer(unsigned freq
)
296 if (init_local_timer(freq
))
299 if (register_local_timer_handler(
300 (irq_handler_t
) timer_int_handler
))
306 int app_cpu_init_timer(unsigned freq
)
308 if (init_local_timer(freq
))