2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
28 * All Rights Reserved.
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
54 #include <stat_time.h>
56 #include <mach/kern_return.h>
57 #include <mach/port.h>
58 #include <kern/queue.h>
59 #include <kern/thread.h>
60 #include <kern/sched_prim.h>
61 #include <mach/time_value.h>
62 #include <kern/timer.h>
63 #include <kern/cpu_number.h>
65 #include <kern/assert.h>
66 #include <kern/macro_help.h>
68 timer_t current_timer
[NCPUS
];
69 timer_data_t kernel_timer
[NCPUS
];
80 void db_thread_read_times(
82 time_value_t
*user_time_p
,
83 time_value_t
*system_time_p
);
86 * init_timers initializes all non-thread timers and puts the
87 * service routine on the callout queue. All timers must be
88 * serviced by the callout routine once an hour.
94 register timer_t this_timer
;
97 * Initialize all the kernel timers and start the one
98 * for this cpu (master) slaves start theirs later.
100 this_timer
= &kernel_timer
[0];
101 for ( i
=0 ; i
<NCPUS
; i
++, this_timer
++) {
102 timer_init(this_timer
);
103 current_timer
[i
] = (timer_t
) 0;
106 mp_disable_preemption();
107 start_timer(&kernel_timer
[cpu_number()]);
108 mp_enable_preemption();
112 * timer_init initializes a single timer.
116 register timer_t this_timer
)
118 this_timer
->low_bits
= 0;
119 this_timer
->high_bits
= 0;
120 this_timer
->tstamp
= 0;
121 this_timer
->high_bits_check
= 0;
125 #else /* STAT_TIME */
127 #ifdef MACHINE_TIMER_ROUTINES
130 * Machine-dependent code implements the timer routines.
133 #else /* MACHINE_TIMER_ROUTINES */
136 * start_timer starts the given timer for this cpu. It is called
137 * exactly once for each cpu during the boot sequence.
141 register timer_t timer
)
143 timer
->tstamp
= get_timestamp();
144 mp_disable_preemption();
145 current_timer
[cpu_number()] = timer
;
146 mp_enable_preemption();
150 * time_trap_uentry does trap entry timing. Caller must lock out
151 * interrupts and take a timestamp. ts is a timestamp taken after
152 * interrupts were locked out. Must only be called if trap was
163 mp_disable_preemption();
166 * Calculate elapsed time.
168 mycpu
= cpu_number();
169 mytimer
= current_timer
[mycpu
];
170 elapsed
= ts
- mytimer
->tstamp
;
172 if (elapsed
< 0) elapsed
+= TIMER_MAX
;
173 #endif /* TIMER_MAX */
176 * Update current timer.
178 mytimer
->low_bits
+= elapsed
;
181 if (mytimer
->low_bits
& TIMER_LOW_FULL
) {
182 timer_normalize(mytimer
);
188 mytimer
= &(current_thread()->system_timer
);
189 current_timer
[mycpu
] = mytimer
;
190 mytimer
->tstamp
= ts
;
192 mp_enable_preemption();
196 * time_trap_uexit does trap exit timing. Caller must lock out
197 * interrupts and take a timestamp. ts is a timestamp taken after
198 * interrupts were locked out. Must only be called if returning to
209 mp_disable_preemption();
212 * Calculate elapsed time.
214 mycpu
= cpu_number();
215 mytimer
= current_timer
[mycpu
];
216 elapsed
= ts
- mytimer
->tstamp
;
218 if (elapsed
< 0) elapsed
+= TIMER_MAX
;
219 #endif /* TIMER_MAX */
222 * Update current timer.
224 mytimer
->low_bits
+= elapsed
;
227 if (mytimer
->low_bits
& TIMER_LOW_FULL
) {
228 timer_normalize(mytimer
); /* SYSTEMMODE */
231 mytimer
= &(current_thread()->user_timer
);
236 current_timer
[mycpu
] = mytimer
;
237 mytimer
->tstamp
= ts
;
239 mp_enable_preemption();
243 * time_int_entry does interrupt entry timing. Caller must lock out
244 * interrupts and take a timestamp. ts is a timestamp taken after
245 * interrupts were locked out. new_timer is the new timer to
246 * switch to. This routine returns the currently running timer,
247 * which MUST be pushed onto the stack by the caller, or otherwise
248 * saved for time_int_exit.
259 mp_disable_preemption();
262 * Calculate elapsed time.
264 mycpu
= cpu_number();
265 mytimer
= current_timer
[mycpu
];
267 elapsed
= ts
- mytimer
->tstamp
;
269 if (elapsed
< 0) elapsed
+= TIMER_MAX
;
270 #endif /* TIMER_MAX */
273 * Update current timer.
275 mytimer
->low_bits
+= elapsed
;
279 * Switch to new timer, and save old one on stack.
281 new_timer
->tstamp
= ts
;
282 current_timer
[mycpu
] = new_timer
;
284 mp_enable_preemption();
290 * time_int_exit does interrupt exit timing. Caller must lock out
291 * interrupts and take a timestamp. ts is a timestamp taken after
292 * interrupts were locked out. old_timer is the timer value pushed
293 * onto the stack or otherwise saved after time_int_entry returned
305 mp_disable_preemption();
308 * Calculate elapsed time.
310 mycpu
= cpu_number();
311 mytimer
= current_timer
[mycpu
];
312 elapsed
= ts
- mytimer
->tstamp
;
314 if (elapsed
< 0) elapsed
+= TIMER_MAX
;
315 #endif /* TIMER_MAX */
318 * Update current timer.
320 mytimer
->low_bits
+= elapsed
;
324 * If normalization requested, do it.
326 if (mytimer
->low_bits
& TIMER_LOW_FULL
) {
327 timer_normalize(mytimer
);
329 if (old_timer
->low_bits
& TIMER_LOW_FULL
) {
330 timer_normalize(old_timer
);
334 * Start timer that was running before interrupt.
336 old_timer
->tstamp
= ts
;
337 current_timer
[mycpu
] = old_timer
;
339 mp_enable_preemption();
343 * timer_switch switches to a new timer. The machine
344 * dependent routine/macro get_timestamp must return a timestamp.
345 * Caller must lock out interrupts.
356 mp_disable_preemption();
359 * Calculate elapsed time.
361 mycpu
= cpu_number();
362 mytimer
= current_timer
[mycpu
];
363 ts
= get_timestamp();
364 elapsed
= ts
- mytimer
->tstamp
;
366 if (elapsed
< 0) elapsed
+= TIMER_MAX
;
367 #endif /* TIMER_MAX */
370 * Update current timer.
372 mytimer
->low_bits
+= elapsed
;
376 * Normalization check
378 if (mytimer
->low_bits
& TIMER_LOW_FULL
) {
379 timer_normalize(mytimer
);
385 current_timer
[mycpu
] = new_timer
;
386 new_timer
->tstamp
= ts
;
388 mp_enable_preemption();
391 #endif /* MACHINE_TIMER_ROUTINES */
392 #endif /* STAT_TIME */
395 * timer_normalize normalizes the value of a timer. It is
396 * called only rarely, to make sure low_bits never overflows.
401 register timer_t timer
)
403 unsigned int high_increment
;
406 * Calculate high_increment, then write high check field first
407 * followed by low and high. timer_grab() reads these fields in
408 * reverse order so if high and high check match, we know
409 * that the values read are ok.
412 high_increment
= timer
->low_bits
/TIMER_HIGH_UNIT
;
413 timer
->high_bits_check
+= high_increment
;
414 timer
->low_bits
%= TIMER_HIGH_UNIT
;
415 timer
->high_bits
+= high_increment
;
419 * timer_grab() retrieves the value of a timer.
421 * Critical scheduling code uses TIMER_DELTA macro in timer.h
422 * (called from thread_timer_delta in sched.h).
424 * Keep coherent with db_time_grab below.
433 unsigned int passes
=0;
436 (save
)->high
= (timer
)->high_bits
;
437 (save
)->low
= (timer
)->low_bits
;
439 * If the timer was normalized while we were doing this,
440 * the high_bits value read above and the high_bits check
441 * value will not match because high_bits_check is the first
442 * field touched by the normalization procedure, and
443 * high_bits is the last.
445 * Additions to timer only touch low bits and
446 * are therefore atomic with respect to this.
450 assert(passes
< 10000);
452 } while ( (save
)->high
!= (timer
)->high_bits_check
);
457 * Db_timer_grab(): used by db_thread_read_times. An nonblocking
458 * version of db_thread_get_times. Keep coherent with timer_grab
467 /* Don't worry about coherency */
469 (save
)->high
= (timer
)->high_bits
;
470 (save
)->low
= (timer
)->low_bits
;
475 * timer_read reads the value of a timer into a time_value_t. If the
476 * timer was modified during the read, retry. The value returned
477 * is accurate to the last update; time accumulated by a running
478 * timer since its last timestamp is not included.
484 register time_value_t
*tv
)
486 timer_save_data_t temp
;
488 timer_grab(timer
,&temp
);
490 * Normalize the result
494 #endif /* TIMER_ADJUST */
495 tv
->seconds
= temp
.high
+ temp
.low
/1000000;
496 tv
->microseconds
= temp
.low%1000000
;
500 * thread_read_times reads the user and system times from a thread.
501 * Time accumulated since last timestamp is not included. Should
502 * be called at splsched() to avoid having user and system times
503 * be out of step. Doesn't care if caller locked thread.
505 * Needs to be kept coherent with thread_read_times ahead.
510 time_value_t
*user_time_p
,
511 time_value_t
*system_time_p
)
513 timer_save_data_t temp
;
514 register timer_t timer
;
516 timer
= &thread
->user_timer
;
517 timer_grab(timer
, &temp
);
521 #endif /* TIMER_ADJUST */
522 user_time_p
->seconds
= temp
.high
+ temp
.low
/1000000;
523 user_time_p
->microseconds
= temp
.low
% 1000000;
525 timer
= &thread
->system_timer
;
526 timer_grab(timer
, &temp
);
530 #endif /* TIMER_ADJUST */
531 system_time_p
->seconds
= temp
.high
+ temp
.low
/1000000;
532 system_time_p
->microseconds
= temp
.low
% 1000000;
536 * Db_thread_read_times: A version of thread_read_times that
537 * can be called by the debugger. This version does not call
538 * timer_grab, which can block. Please keep it up to date with
539 * thread_read_times above.
543 db_thread_read_times(
545 time_value_t
*user_time_p
,
546 time_value_t
*system_time_p
)
548 timer_save_data_t temp
;
549 register timer_t timer
;
551 timer
= &thread
->user_timer
;
552 db_timer_grab(timer
, &temp
);
556 #endif /* TIMER_ADJUST */
557 user_time_p
->seconds
= temp
.high
+ temp
.low
/1000000;
558 user_time_p
->microseconds
= temp
.low
% 1000000;
560 timer
= &thread
->system_timer
;
561 timer_grab(timer
, &temp
);
565 #endif /* TIMER_ADJUST */
566 system_time_p
->seconds
= temp
.high
+ temp
.low
/1000000;
567 system_time_p
->microseconds
= temp
.low
% 1000000;
571 * timer_delta takes the difference of a saved timer value
572 * and the current one, and updates the saved value to current.
573 * The difference is returned as a function value. See
574 * TIMER_DELTA macro (timer.h) for optimization to this.
579 register timer_t timer
,
582 timer_save_data_t new_save
;
583 register unsigned result
;
585 timer_grab(timer
,&new_save
);
586 result
= (new_save
.high
- save
->high
) * TIMER_HIGH_UNIT
+
587 new_save
.low
- save
->low
;
588 save
->high
= new_save
.high
;
589 save
->low
= new_save
.low
;