2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
29 * Mach Operating System
30 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
31 * All Rights Reserved.
33 * Permission to use, copy, modify and distribute this software and its
34 * documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 * Carnegie Mellon requests users of this software to return to
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
50 * any improvements or extensions that they make and grant Carnegie Mellon
51 * the rights to redistribute these changes.
57 #include <stat_time.h>
59 #include <mach/kern_return.h>
60 #include <mach/port.h>
61 #include <kern/queue.h>
62 #include <kern/thread.h>
63 #include <kern/sched_prim.h>
64 #include <mach/time_value.h>
65 #include <kern/timer.h>
66 #include <kern/cpu_number.h>
68 #include <kern/assert.h>
69 #include <kern/macro_help.h>
71 timer_t current_timer
[NCPUS
];
72 timer_data_t kernel_timer
[NCPUS
];
83 void db_thread_read_times(
85 time_value_t
*user_time_p
,
86 time_value_t
*system_time_p
);
89 * init_timers initializes all non-thread timers and puts the
90 * service routine on the callout queue. All timers must be
91 * serviced by the callout routine once an hour.
97 register timer_t this_timer
;
100 * Initialize all the kernel timers and start the one
101 * for this cpu (master) slaves start theirs later.
103 this_timer
= &kernel_timer
[0];
104 for ( i
=0 ; i
<NCPUS
; i
++, this_timer
++) {
105 timer_init(this_timer
);
106 current_timer
[i
] = (timer_t
) 0;
109 mp_disable_preemption();
110 start_timer(&kernel_timer
[cpu_number()]);
111 mp_enable_preemption();
115 * timer_init initializes a single timer.
119 register timer_t this_timer
)
121 this_timer
->low_bits
= 0;
122 this_timer
->high_bits
= 0;
123 this_timer
->tstamp
= 0;
124 this_timer
->high_bits_check
= 0;
128 #else /* STAT_TIME */
130 #ifdef MACHINE_TIMER_ROUTINES
133 * Machine-dependent code implements the timer routines.
136 #else /* MACHINE_TIMER_ROUTINES */
139 * start_timer starts the given timer for this cpu. It is called
140 * exactly once for each cpu during the boot sequence.
144 register timer_t timer
)
146 timer
->tstamp
= get_timestamp();
147 mp_disable_preemption();
148 current_timer
[cpu_number()] = timer
;
149 mp_enable_preemption();
153 * time_trap_uentry does trap entry timing. Caller must lock out
154 * interrupts and take a timestamp. ts is a timestamp taken after
155 * interrupts were locked out. Must only be called if trap was
166 mp_disable_preemption();
169 * Calculate elapsed time.
171 mycpu
= cpu_number();
172 mytimer
= current_timer
[mycpu
];
173 elapsed
= ts
- mytimer
->tstamp
;
175 if (elapsed
< 0) elapsed
+= TIMER_MAX
;
176 #endif /* TIMER_MAX */
179 * Update current timer.
181 mytimer
->low_bits
+= elapsed
;
184 if (mytimer
->low_bits
& TIMER_LOW_FULL
) {
185 timer_normalize(mytimer
);
191 mytimer
= &(current_thread()->system_timer
);
192 current_timer
[mycpu
] = mytimer
;
193 mytimer
->tstamp
= ts
;
195 mp_enable_preemption();
199 * time_trap_uexit does trap exit timing. Caller must lock out
200 * interrupts and take a timestamp. ts is a timestamp taken after
201 * interrupts were locked out. Must only be called if returning to
212 mp_disable_preemption();
215 * Calculate elapsed time.
217 mycpu
= cpu_number();
218 mytimer
= current_timer
[mycpu
];
219 elapsed
= ts
- mytimer
->tstamp
;
221 if (elapsed
< 0) elapsed
+= TIMER_MAX
;
222 #endif /* TIMER_MAX */
225 * Update current timer.
227 mytimer
->low_bits
+= elapsed
;
230 if (mytimer
->low_bits
& TIMER_LOW_FULL
) {
231 timer_normalize(mytimer
); /* SYSTEMMODE */
234 mytimer
= &(current_thread()->user_timer
);
239 current_timer
[mycpu
] = mytimer
;
240 mytimer
->tstamp
= ts
;
242 mp_enable_preemption();
246 * time_int_entry does interrupt entry timing. Caller must lock out
247 * interrupts and take a timestamp. ts is a timestamp taken after
248 * interrupts were locked out. new_timer is the new timer to
249 * switch to. This routine returns the currently running timer,
250 * which MUST be pushed onto the stack by the caller, or otherwise
251 * saved for time_int_exit.
262 mp_disable_preemption();
265 * Calculate elapsed time.
267 mycpu
= cpu_number();
268 mytimer
= current_timer
[mycpu
];
270 elapsed
= ts
- mytimer
->tstamp
;
272 if (elapsed
< 0) elapsed
+= TIMER_MAX
;
273 #endif /* TIMER_MAX */
276 * Update current timer.
278 mytimer
->low_bits
+= elapsed
;
282 * Switch to new timer, and save old one on stack.
284 new_timer
->tstamp
= ts
;
285 current_timer
[mycpu
] = new_timer
;
287 mp_enable_preemption();
293 * time_int_exit does interrupt exit timing. Caller must lock out
294 * interrupts and take a timestamp. ts is a timestamp taken after
295 * interrupts were locked out. old_timer is the timer value pushed
296 * onto the stack or otherwise saved after time_int_entry returned
308 mp_disable_preemption();
311 * Calculate elapsed time.
313 mycpu
= cpu_number();
314 mytimer
= current_timer
[mycpu
];
315 elapsed
= ts
- mytimer
->tstamp
;
317 if (elapsed
< 0) elapsed
+= TIMER_MAX
;
318 #endif /* TIMER_MAX */
321 * Update current timer.
323 mytimer
->low_bits
+= elapsed
;
327 * If normalization requested, do it.
329 if (mytimer
->low_bits
& TIMER_LOW_FULL
) {
330 timer_normalize(mytimer
);
332 if (old_timer
->low_bits
& TIMER_LOW_FULL
) {
333 timer_normalize(old_timer
);
337 * Start timer that was running before interrupt.
339 old_timer
->tstamp
= ts
;
340 current_timer
[mycpu
] = old_timer
;
342 mp_enable_preemption();
346 * timer_switch switches to a new timer. The machine
347 * dependent routine/macro get_timestamp must return a timestamp.
348 * Caller must lock out interrupts.
359 mp_disable_preemption();
362 * Calculate elapsed time.
364 mycpu
= cpu_number();
365 mytimer
= current_timer
[mycpu
];
366 ts
= get_timestamp();
367 elapsed
= ts
- mytimer
->tstamp
;
369 if (elapsed
< 0) elapsed
+= TIMER_MAX
;
370 #endif /* TIMER_MAX */
373 * Update current timer.
375 mytimer
->low_bits
+= elapsed
;
379 * Normalization check
381 if (mytimer
->low_bits
& TIMER_LOW_FULL
) {
382 timer_normalize(mytimer
);
388 current_timer
[mycpu
] = new_timer
;
389 new_timer
->tstamp
= ts
;
391 mp_enable_preemption();
394 #endif /* MACHINE_TIMER_ROUTINES */
395 #endif /* STAT_TIME */
398 * timer_normalize normalizes the value of a timer. It is
399 * called only rarely, to make sure low_bits never overflows.
404 register timer_t timer
)
406 unsigned int high_increment
;
409 * Calculate high_increment, then write high check field first
410 * followed by low and high. timer_grab() reads these fields in
411 * reverse order so if high and high check match, we know
412 * that the values read are ok.
415 high_increment
= timer
->low_bits
/TIMER_HIGH_UNIT
;
416 timer
->high_bits_check
+= high_increment
;
417 timer
->low_bits
%= TIMER_HIGH_UNIT
;
418 timer
->high_bits
+= high_increment
;
422 * timer_grab() retrieves the value of a timer.
424 * Critical scheduling code uses TIMER_DELTA macro in timer.h
425 * (called from thread_timer_delta in sched.h).
427 * Keep coherent with db_time_grab below.
436 unsigned int passes
=0;
439 (save
)->high
= (timer
)->high_bits
;
440 (save
)->low
= (timer
)->low_bits
;
442 * If the timer was normalized while we were doing this,
443 * the high_bits value read above and the high_bits check
444 * value will not match because high_bits_check is the first
445 * field touched by the normalization procedure, and
446 * high_bits is the last.
448 * Additions to timer only touch low bits and
449 * are therefore atomic with respect to this.
453 assert(passes
< 10000);
455 } while ( (save
)->high
!= (timer
)->high_bits_check
);
460 * Db_timer_grab(): used by db_thread_read_times. An nonblocking
461 * version of db_thread_get_times. Keep coherent with timer_grab
470 /* Don't worry about coherency */
472 (save
)->high
= (timer
)->high_bits
;
473 (save
)->low
= (timer
)->low_bits
;
478 * timer_read reads the value of a timer into a time_value_t. If the
479 * timer was modified during the read, retry. The value returned
480 * is accurate to the last update; time accumulated by a running
481 * timer since its last timestamp is not included.
487 register time_value_t
*tv
)
489 timer_save_data_t temp
;
491 timer_grab(timer
,&temp
);
493 * Normalize the result
497 #endif /* TIMER_ADJUST */
498 tv
->seconds
= temp
.high
+ temp
.low
/1000000;
499 tv
->microseconds
= temp
.low%1000000
;
503 * thread_read_times reads the user and system times from a thread.
504 * Time accumulated since last timestamp is not included. Should
505 * be called at splsched() to avoid having user and system times
506 * be out of step. Doesn't care if caller locked thread.
508 * Needs to be kept coherent with thread_read_times ahead.
513 time_value_t
*user_time_p
,
514 time_value_t
*system_time_p
)
516 timer_save_data_t temp
;
517 register timer_t timer
;
519 timer
= &thread
->user_timer
;
520 timer_grab(timer
, &temp
);
524 #endif /* TIMER_ADJUST */
525 user_time_p
->seconds
= temp
.high
+ temp
.low
/1000000;
526 user_time_p
->microseconds
= temp
.low
% 1000000;
528 timer
= &thread
->system_timer
;
529 timer_grab(timer
, &temp
);
533 #endif /* TIMER_ADJUST */
534 system_time_p
->seconds
= temp
.high
+ temp
.low
/1000000;
535 system_time_p
->microseconds
= temp
.low
% 1000000;
539 * Db_thread_read_times: A version of thread_read_times that
540 * can be called by the debugger. This version does not call
541 * timer_grab, which can block. Please keep it up to date with
542 * thread_read_times above.
546 db_thread_read_times(
548 time_value_t
*user_time_p
,
549 time_value_t
*system_time_p
)
551 timer_save_data_t temp
;
552 register timer_t timer
;
554 timer
= &thread
->user_timer
;
555 db_timer_grab(timer
, &temp
);
559 #endif /* TIMER_ADJUST */
560 user_time_p
->seconds
= temp
.high
+ temp
.low
/1000000;
561 user_time_p
->microseconds
= temp
.low
% 1000000;
563 timer
= &thread
->system_timer
;
564 timer_grab(timer
, &temp
);
568 #endif /* TIMER_ADJUST */
569 system_time_p
->seconds
= temp
.high
+ temp
.low
/1000000;
570 system_time_p
->microseconds
= temp
.low
% 1000000;
574 * timer_delta takes the difference of a saved timer value
575 * and the current one, and updates the saved value to current.
576 * The difference is returned as a function value. See
577 * TIMER_DELTA macro (timer.h) for optimization to this.
582 register timer_t timer
,
585 timer_save_data_t new_save
;
586 register unsigned result
;
588 timer_grab(timer
,&new_save
);
589 result
= (new_save
.high
- save
->high
) * TIMER_HIGH_UNIT
+
590 new_save
.low
- save
->low
;
591 save
->high
= new_save
.high
;
592 save
->low
= new_save
.low
;